Welcome Guest, Not a member yet? Register   Sign In
Codeigniter 3 Model best practices
#1

It's a very first post here so...Hi guys  Big Grin  My name's Jakub (James for friends), I'm using CI from half and past a year, but I need to know some best approach especialy in Model.

Well I'm trying to achieve an OOP principes in Codeigniter, something like ORM but in simpler way. Usually I'm using a simple spl loader in MY_Loader, with my own classess, where properties look like in tables. But the problem are .... relations - espiecially many to many.

For example - I have Database with User($email, $password, $id), Item($name $id) and relation table ($idUser, $idItem).

And now I want to get items what are related to User by item->name. Database makes results by custom_results_object.

Usually I'm just making a several queries to database, table by table, and operate results by standard php methods, to return an array of needed object.

How it's yours idea? I think it's not a good solution to make a several queries, while I can use for example join method. But how to convert it to objects ?
Reply
#2

You can convert the arrays to object like this:

PHP Code:
$object = (object)$array
What did you Try? What did you Get? What did you Expect?

Joined CodeIgniter Community 2009.  ( Skype: insitfx )
Reply
#3

The database library in CI will return query results as objects by default:
PHP Code:
$this->db
->select('name,email')
->
from('users')
->
where('deleted_at'0)
->
order_by('name''ASC');
$query $this->db->get();
return 
$query->result(); 

Now your model returns the records as an array of objects.
If you prefer an array of arrays, then do this:
PHP Code:
return $query->result_array(); 
Reply
#4

this isn't trivial at all, and i'm unsure about your level but i'll try ...

First of all - i strongly suggest the use of objects (respective classes) in any circumstance - because of its flexibility
any kind of array which holds a set of data (multiple rows) - should be an object (one of the better approaches would be the use of ArrayObjects)

lets take an example based on author and books (one author has many books)

That said your structure should be:

PHP Code:
class Collection extends ArrayObject {}
class 
AuthorCollection extends Collection {}
class 
BookCollection extends Collection {}

class 
Author {}
class 
Book {}

$col = new AuthorCollection();

$objAuthorSK = new Author();
$objAuthorSK->firstame 'Stephen';
$objAuthorSK->lastname 'King';
$objAuthorSK->books = new BookCollection();

$col->append($objAuthorSK);

$objBook = new Book();
$objBook->title 'Carrie';
$objAuthorSK->books->append($objBook);

print_r($col); 

You'll see how structured your data are right now

The main problem now is - how to integrate such a simple looking example into Codeigniter - to be honest i just can deliver some abstract basics, because i'm really busy right now 

The first thing i would recommend is to deal with the problem how and where to define your relations

For this matter i strongly suggest one model for each corresponding table

the second thing is - you should think about your type of relations (maybe take a look @laravels eloquent)

But for now there are 2 relations important:

  • One
  • Many
(optional for a later use - ManyByIntermediate and OneByIntermediate)


How would this look in our model ?
A possible approach would be (since namespaces and CI are a special topic - i'll stick with the common practice to suffix the names of the respectivce classes.

PHP Code:
class Author_model extends ORM_Model
{
    protected 
$strTable 'author';
    protected 
$strTableObject 'Author_Object';
    protected 
$strResultCollection 'Author_Collection';
    
    public function 
__construct()
    {
        
$this->addConnections([
            
'book' => Relations_Factory::Many(
                
'Book_model',
                [
                    
'id' => 'author_id'
                
]
            ),
        ]);
    }
}

class 
Book_model extends ORM_Model
{
    protected 
$strTable 'book';
    protected 
$strTableObject 'Book_Object';
    protected 
$strResultCollection 'Book_Collection';
    
    public function 
__construct()
    {
        
$this->addConnections([
            
'author' => Relations_Factory::One(
                
'Author_model',
                [
                    
'author_id' => 'id'
                
]
            ),
        ]);
    }



The next thing would be to think about - whats the job of your ORM Model and which functions and processes should be there ...
I for myself would integrate the query builder and use it for your own purpose

it could look like (keep in mind this is just an abstract shot, in order to understand how to achieve a structured query building process)

PHP Code:
abstract class ORM_model
{
    protected 
$strTable '';
    protected 
$strTableObject 'OrmTable_Object';
    protected 
$objRelationManager;
    protected 
$strIdKey 'id';
    protected 
$arrConnections = array();
    protected 
$objDb;
    protected 
$blnEscapeStrings true;

    private static 
$arrBufferJoinedAliases = array();

    public function 
__construct(?CI_DB_query_builder $objDb null, ?Relation_Manager $objRelationManager null)
    {
        
$this->objRelationManager = (!is_null($objRelationManager)) ?   $objRelationManager : new ORMRelation_Manager($this);
        
$this->objDb = ($objDb) ? $objDb $this->db;
    }
    
    public function 
select($mixedSelect$process true)
    {
        
$this->objDb->select($mixedSelect$this->blnEscapeStrings);
        return 
$this;
    }
    
    public function 
where($strFieldName$mixedValue$process true)
    {
        
$this->objDb->where($strFieldName$mixedValue$this->blnEscapeStrings
        
return $this;
    }
    
    
//where_in, or_where, like, or_like, group_start, and so on (the supported Query Builder functions)
    
    
public function getTableAlias()
    {
        return 
$this->strTableAlias;
    }
    
    private function 
processFieldNameForQuery($strFieldName)
    {
        
//in case of a connection
        
if(strpos($strFieldName':'))
        {
            
$arrConnections explode(':'$strFieldName);
            
$strFieldNameForTargetTable $this->joinConnectionAndGetFieldNameForTargetTable($arrConnections);
        }
        else
        {
            
$strFieldNameForTargetTable $this->getTableAlias() . '.' $strFieldName;
        }
        
        return 
$strFieldNameForTargetTable;

    }
    
    private function 
joinConnectionAndGetFieldNameForTargetTable($arrConnections)
    {
        
$strCurrentConnection array_shift($arrConnections);
        if(
array_key_exists($strCurrentConnection$this->arrConnections))
        {
            
$objCurrentConnection $this->arrConnections[$strCurrentConnection];
            if(!
in_array($objCurrentConnection->getTargetTableAlias(), CrudDb_Model::$arrBufferJoinedAliases))
            {
                
CrudDb_Model::$arrBufferJoinedAliases[] = $objCurrentConnection->getTargetTableAlias();
                
$objCurrentConnection->performJoinsForQuery($this$this->objDb);
                foreach(
$objCurrentConnection->getTargetModel()->getStandardWhere() as $strFieldName => $strFieldValue)
                {
                    
$this->where($objCurrentConnection->getTargetTableAlias().'.'.$strFieldName$strFieldValue);
                }
            }
            
            if(
count($arrConnections) == 1)
            {
                
$strFieldName array_shift($arrConnections);

                if(!
strpos($strFieldName'.'))
                {
                    
$strFieldName $objCurrentConnection->getTargetModel()->processFieldNameForQuery($strFieldName);

                    return 
$strFieldName;
                }
                else
                {
                    return 
$strFieldName;
                }
            }
            else
            {
                return 
$objCurrentConnection->getTargetModel()->joinConnectionAndGetFieldNameForTargetTable($arrConnections);
            }

            
//.... and so on
        
}
        else
        {
            throw new 
InvalidArgumentException('Provided connection '.$strCurrentConnection.' does not exist in '.get_class($this));
        }
    }


the Relation builder is still missing - 

PHP Code:
class Relations_Factory
{
    public static function 
One($strFieldName$strTargetModel$arrObjectToTargetKeys$arrTargetOptions = array())
    {
        return new 
One_Relation($strFieldName$strTargetModel$arrObjectToTargetKeys$arrTargetOptions);
    }

    public static function 
Many($strFieldName$strTargetModel$arrObjectToTargetKeys$arrTargetOptions = array())
    {
        return new 
Many_Relation($strFieldName$strTargetModel$arrObjectToTargetKeys$arrTargetOptions);
    }


Now you have to think about your relation Structure and thats it.

The end goal would be something like:

PHP Code:
$colAuthor $this->Author_model->where('lasname''King')->read();

$objAuthor $colAuthor[0];

//lazy loading principle by calling the corresponding collection - which adds all books to your Authors Objects.
$colBooks $objAuthor->get('book'); 

There is a topic in the CI4 Forum - for additional infos https://forum.codeigniter.com/thread-71733-page-2.html
Reply




Theme © iAndrew 2016 - Forum software by © MyBB