Welcome Guest, Not a member yet? Register   Sign In
When Does Entity Attributes Get Filled
#1

(This post was last modified: 12-11-2019, 08:45 PM by viewfromthenorth.)

So I've been thinking a lot about these discussions around ORM and building relationships between items. All of the extensions are great, but I feel like the Entity class in CI4 is capable of a LOT, and I've been playing around with it a bunch to try and collect/install parameters based on relationships.

See this code here:
PHP Code:
<?php
namespace App\Entities;

use 
CodeIgniter\Entity;
use 
App\Models\PostsModel;

class 
User extends Entity
{
    public function __construct(array $data null)
    {
        parent::__construct($data);

        $this->attributes['posts'] = $this->getPosts();
    }

    public function getPosts()
    {
        $model = new PostsModel();

        $posts $model
            
->where('user_id'$this->attributes['id'])
            ->asArray()
            ->findAll();

        $this->attributes['posts'] = $posts;

        return $posts;
    }


Imagine two tables and two Entities, Users and Posts. All you need to know is Users has an ID and can have many posts.

I know that I can call $user->posts and get the array of posts at any time. What I'm trying to do is build my Entity in such a way that when I call $user->toArray(), $user->posts becomes the array of posts. 

I tried initially putting in like a render() function that updates it but then I have to call it BEFORE ->toArray() and seems clunky.

I tried extending the __construct() function to update it then ($this->attributes['posts'] = $this->getPosts()) but I get an error message saying that ['id'] doesn't exist yet. Which is weird, because as parent::__construct runs, it should be filling in the data for that item from the database (I know an item is there and I can collect it, and I can display all properties of the entity fine, there just seems to be some kind of timing issue with how I'm using __construct and ['id'] hasn't been set yet in the process).

So the question remains... what can I do, so that everytime I instantiate an Entity of this type, the Entity can run code that will take the id property (when does it finally get loaded in?), collect related items and store them as an already available property (array) so I can just call ->toArray() directly after?

I should also note that I am receiving the Entity instance as the return type of a corresponding model.
Reply
#2

Entities aren’t filled via the constructor when returned as part of a database query result (this includes Models), but rather have each attribute set one at a time. See e.g.:
https://github.com/codeigniter4/CodeIgni...t.php#L179

You could probably create your own magic getter for posts that would load it on-the-fly, but I’m not entirely sure of its interaction with toArray(). I use this kind of “lazy load” for my Relations Entity trait and it works very well - no extra loading of related items if you don’t need them.
Reply
#3

(12-12-2019, 08:12 PM)MGatner Wrote: Entities aren’t filled via the constructor when returned as part of a database query result (this includes Models), but rather have each attribute set one at a time. See e.g.:
https://github.com/codeigniter4/CodeIgni...t.php#L179

You could probably create your own magic getter for posts that would load it on-the-fly, but I’m not entirely sure of its interaction with toArray(). I use this kind of “lazy load” for my Relations Entity trait and it works very well - no extra loading of related items if you don’t need them.

I know this is an old thread, but I am trying to accomplish something very similar.  Unfortunately, I am not experienced enough to know how to do this kind of "lazy load".  Could I trouble you to provide some boiler plate code?
Reply




Theme © iAndrew 2016 - Forum software by © MyBB