CodeIgniter Forums

Full Version: Best practices using multiple object instances?
You're currently viewing a stripped down version of our content. View the full version with proper formatting.

El Forum

[eluser]tarsusc81[/eluser]
Something I've observed since starting with CodeIgniter is that while it is perfectly true that the framework is "object-oriented," I might be apt to call it "class-oriented." What I mean is that the architecture centers around encapsulating functionality in a class, and then loading a single instance of that class to use its functionality.

That's as it should be. But things get a little murky for me when trying to deal with classes intended for actually creating and using objects. (Meaning multiple instances.)

For example (forgive me if my syntax has errors; I'm a little rusty):
Code:
class User extends Model
{
     function save($userID, $data)
     {
          //SQL query
     }
}

This is designed to be stored using the convention User.php and to be loaded and used as a single instance:

Code:
$this->load->model('User');
$this->User->save(324, $data['324']);
$this->User->save(450, $data['450']);

But what if I actually want a User class that corresponds to a single user, with multiple instances holding data for each?

Code:
class User
{
     protected var $id;

     function save($data)
     {
          //SQL query
     }
}
...
$user1 = new User(324);
$user1.save($data['324']);
$user2 = new User(450);
$user2.save($data['450']);

This may not be the best example, but hopefully it gets the idea across.

I have trouble conceptualizing how to use multiple-instance objects leveraging the functionality of CodeIgniter, rather than breaking out of it. (I.e., having to use a normal "require()" instead of "$this->load")

Any advice from those who've created object-heavy applications? What's the best way to get the most out of CodeIgniter when doing so?

It's occurred to me to do something like actually declaring two classes in one model or library file - one as the "master" class to be used with "$this->load" and possibly have methods to interact with the second class, which is designed to have multiple instances. But I don't know if this is a good idea, or if there's a better one.

El Forum

[eluser]WanWizard[/eluser]
Instead of trying to make this yourself, why don't you look at Datamapper (DMZ, search the forum), which provides you with an object model per database table, including automatic relationships, cascading deletes, custom methods per object, pre-update/insert validations, etc.

The alternative is to store them in p.e. a classes subdirectory, and then do
Code:
if ( file_exists(APPPATH.'classes/'.$myclass) )
{
    require_once(APPPATH.'classes/'.$myclass);
}
else
{
    // catch the error here
}
$class = new Myclass();

El Forum

[eluser]tarsusc81[/eluser]
I'm somewhat familiar with Datamapper. I'm leery, as another developer I know who's used it ran into exactly what I would expect: Page loads bogged down by THOUSANDS of queries where only a few would have sufficed. (That's in complex scenarios. I'm sure it's fine when dealing with a one or a few records.)

But that's neither here nor there. I used a model as an example, but I'm talking about any circumstance where functionality with multiple object instances is needed, not just objects that correspond with database entities. (For another example, how about writing HTML form functionality using a technique that represents a form as an object?)

Your example works, but that's the kind of code I was wondering if I could avoid. CodeIgniter makes that kind of manual checking/including unnecessary for it's conventional structures, so I'm exploring whether there's a way to avoid it for this too.

El Forum

[eluser]WanWizard[/eluser]
The queries DMZ creates aren't that much different from what you normally would write.

And nobody's forcing you to use DMZ for ALL queries, I have DMZ models with custom methods that bypass DMZ entirely, and run their own $this->db queries, for exactly this reason. The beauty is that you can do both.

If the above code bothers you, create a MY_Loader extension:
Code:
class MY_Loader extends CI_Loader
{
    function MY_Loader()
    {
        parent::CI_Loader();
    }

    function object($class)
    {
        if ( file_exists(APPPATH.'classes/'.$class.EXT) )
        {
            require_once(APPPATH.'classes/'.$class.EXT);
        }
        else
        {
            return FALSE;
        }
        // you need to check if the file loaded ready defines the requested class...
        $class = new $class;
        return $class;
    }
}

and then use

Code:
$myclass = $this->load->object('myclass');

El Forum

[eluser]jedd[/eluser]
Coincidentally, this is near where I came in - have a read of [url="/forums/viewthread/108763/"]this thread from early last year[/url].

It doesn't contain anything resembling a profound insight or answer - but might give a few hints.

El Forum

[eluser]Unknown[/eluser]
I am pretty new to CI and faced this challenge. This is what I devised to get around this problem without any change or addon to CI.

This is an example code to create multiple instances of an object/model

Code:
foreach($_REQUEST['users'] as $userid){

    $objectName = 'u'.$userid; // each object is given a distinct name

    $this->load->model('USER', $objectName); // load the model with a distinct name

    $usersArray[] = $objectName; //store the object/model names in an array.

}

To use the object use the following code

Code:
foreach($usersArray as $theUser){

    $this->$theUser->show(); // the value of the variable '$theUser' is considered as a variable. So its like a variable inside a variable

}

For more explanation please refer to my post How to Create and Handle an Array of Models or Objects in Codeigniter

El Forum

[eluser]nikes[/eluser]
Coincidentally, this really is near to in which I arrived in - possess a review with this thread from earlier last year.

It does not incorporate something resembling a profound insight or response - but may give different hints.

El Forum

[eluser]scherman[/eluser]
[quote author="WanWizard" date="1280349303"]The queries DMZ creates aren't that much different from what you normally would write.

And nobody's forcing you to use DMZ for ALL queries, I have DMZ models with custom methods that bypass DMZ entirely, and run their own $this->db queries, for exactly this reason. The beauty is that you can do both.

If the above code bothers you, create a MY_Loader extension:
Code:
class MY_Loader extends CI_Loader
{
    function MY_Loader()
    {
        parent::CI_Loader();
    }

    function object($class)
    {
        if ( file_exists(APPPATH.'classes/'.$class.EXT) )
        {
            require_once(APPPATH.'classes/'.$class.EXT);
        }
        else
        {
            return FALSE;
        }
        // you need to check if the file loaded ready defines the requested class...
        $class = new $class;
        return $class;
    }
}

and then use

Code:
$myclass = $this->load->object('myclass');
[/quote]

This is pretty cool. I have the same problem and i don't know how can i resolve it.
But i have a question about this: is there any way to work in my object class with the Active Records ($this->db....)? Because if i can do that, my problem will be resolved!