Welcome Guest, Not a member yet? Register   Sign In
getCustomResultObject() bypasses my custom __set() method
#1

I want to use a model to retrieve entries from my database and instantiate my own custom entity class for each row. I do not want to use or extend the CI4 entity class.

getCustomResultObject() correctly instantiates my custom entity classes but it bypasses the __set() method of my entity class. It sets the properties directly even though the parameters are declared protected. This prevents me from doing any business logic on the properties as they are set. 

I am going crazy trying to work out my error. 

I have even started a fresh install of CI4 using the sample code from the user guide (https://codeigniter.com/user_guide/models/model.html). To my astonishment even the user guide code on a fresh install has this problem and does not work as described in the user guide. I have adjusted the Job class slightly to add .' intercepted' to demonstrate if properties are being set by the __set() method and they are not.

PHP Code:
class Job
{
    protected $id;
    protected $name;
    protected $description;
    protected $demo 'test';

    public function __get($key)
    {
        if (property_exists($this$key)) {
            return $this->{$key};
        }
    }

    public function __set($key$value)
    {
        if (property_exists($this$key)) {
            $this->{$key} = $value.' intercepted';
        }
    }



PHP Code:
use CodeIgniter\Model;

class 
JobModel extends Model
{
    protected $table 'jobs';
    protected $returnType Job::class;
    protected $allowedFields = [
        'name''description',
    ];



PHP Code:
class Dev extends BaseController
{
    public function index()
    {
        $jobModel = new \App\Domains\Dev\JobModel();
        
        $job 
= new \App\Domains\Dev\Job(); 
        $jobs $jobModel->findAll();
        foreach ($jobs as $job) {
            echo "{$job->name} <br>";
        }
    }



This displays the dummy job names I put in my test database without appending the string ' intercepted' to each.

I would be incredibly grateful for any help understanding what is going on. It seems incredibly unlikely that anything as fundamental to the CI4 Models would be bugged like this. But I just can't fathom what I am doing wrong, even with code almost straight from the user guide.

Thanks in advance.
Reply
#2

(This post was last modified: 01-31-2021, 11:34 AM by iRedds.)

I'll tell you using mysqli as an example, because I didn't deal with postgre, but I think that the behavior is the same.
If you are using a class that does not inherit from Entity, then the mysqli_result::fetch_object() method is called.

I don't know exactly how properties are assigned a value, but the __set() method only works when the property is not set.
It's as if the property visibility is being ignored.

I hope you have already understood that this is not a problem with the framework.

The example from the User's Guide shows a class with the __get and __set magic methods as a way to access protected properties.
Another way is getter and setter methods for each property.

I hope I helped you figure out the reason
Reply
#3

Thanks for your input.
I don't understand your explanation.
I have set a __set() method in my custom class, just as it was in the user guide example (see code above). 
Do you have any suggestions for how I should change my code. 

Thanks
Reply
#4

The __set method will not be called when filling with data from the database. 
PHP Code:
class Job
{
    protected $id;
    protected $name;
    protected $description;
    protected $demo = 'test';

    public function __get($key) {}

    public function __set($key, $value) {}
}
  

The __set method will be called when filling with data from the database.
But anymore it (and __get too) will not be called, because automatically created properties will have public visibility
PHP Code:
class Job
{
    public function __get($key) {}
    public function __set($key, $value) {}
}
  

This is not a framework problem. This is how the php + php-mysqli extension works.

A simple solution.

PHP Code:
class Job
{
    protected  $attributes = [];

    public function __get($key)
    {
        return $this->attributes[$key] ?? null;
    }

    public function __set($key$value)
    {
        $this->attributes[$key] = $value ' intercepted';
    }

Reply
#5
Big Grin 

Thank you so much! 
I finally understand. 
You have saved me from my madness. 
Thank you.
Reply




Theme © iAndrew 2016 - Forum software by © MyBB