We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Getters/Setters not working with ORM

According to this page: https://docs.phalcon.io/ja/3.2/db-models#properties-setters-getters

The ORM is compatible with both schemes of defining properties.

However, when I test this:

class Robots extends Model
{
    protected $id;
    protected $name;

    public function setName($name)
    {
        $this->name = 'Robot '.$name;
    }

    public function getName()
    {
        return $this->name;
    }
}

=============
id   | name
1    | Bender
=============

$robot = Robots::findFirstById(1);
var_dump($robot->getName()); //null

But, changing $name to public returns Robot Bender.

What am I missing? Are the docs wrong?



85.5k

i have been using this since forever .. i haven't have any issues

pehaps you messed some other config or orm setting ?



12.1k

Something it's not clear in your example. You should receive Robot Benderonly after using the setName() method. If you access directly to the props, without using methods, you absolutely receive the value on the database and if you receiveRobot Bender, the things could be two:

  1. you have used the set method before the access to the property
  2. you are seeing on a different table/db, or in one previous operation you have used the save() method

My test code is as follows:

 class TestController extends PhalconController{

    public action testAction(){
        $robot = Robots::findFirstById(1);
        var_dump($robot->getName());
        die;
    }

 }

And according to the docs the ORM works with public properties and getters/setters, so I'd expect it to call setName() when loading data from the database. But when dumping $robot and $robot->getName(), I can see that all protected properties are null.

Something it's not clear in your example. You should receive Robot Benderonly after using the setName() method. If you access directly to the props, without using methods, you absolutely receive the value on the database and if you receiveRobot Bender, the things could be two:

  1. you have used the set method before the access to the property
  2. you are seeing on a different table/db, or in one previous operation you have used the save() method

I have this on my index

Model::setup([
        'ignoreUnknownColumns' => true,
        'castOnHydrate'        => true,
    ]);

If this is making the expected behaviour to not work, it should be documented.

i have been using this since forever .. i haven't have any issues

pehaps you messed some other config or orm setting ?



85.5k
edited Feb '18
DESCRIBE _DB_._TABLE_
edited Feb '18

Result for the users table

class User extends Model
{

    public $id;
    protected $name;
    public $email;
    public $password;
    public $type;

    //getters and setters

}
DESCRIBE _DB_._TABLE_


85.5k

and if you remove the model::setup does it work ?

Nope. I also tried to have getters/setters + public properties, but instead of getting null it returns the value from the database without the changes made on the setter.

Phalcon 3.2

and if you remove the model::setup does it work ?



85.5k

i honestly dont know, your example is working for me

OS, PHP and Phalcon version?

edited Feb '18

Ubuntu 16.04

PHP 7.1.12

Phalcon 3.2.4

OS, PHP and Phalcon version?



12.1k

And according to the docs the ORM works with public properties and getters/setters, so I'd expect it to call setName() when loading data from the database. But when dumping $robot and $robot->getName(), I can see that all protected properties are null.

No, it's not, Maybe I'm wrong but... Setter and getter are the interface for external calls, but the ORM populate the object using the properties, not through the setters

edited Feb '18

The ORM is compatible with both schemes of defining properties.

But this is directly extracted from the docs

And according to the docs the ORM works with public properties and getters/setters, so I'd expect it to call setName() when loading data from the database. But when dumping $robot and $robot->getName(), I can see that all protected properties are null.

No, it's not, Maybe I'm wrong but... Setter and getter are the interface for external calls, but the ORM populate the object using the properties, not through the setters

edited Feb '18

to populate from db to model Phalcon use assign() method maybe some options like ignore_unknown_columns or disable_assign_setters are wrong

edited Feb '18

I managed to have some progress. There was an overriden columnMap() that was ignoring protected attributes. After fixing the columnMap Phalcon managed to set the protected attributes with their database values. However, setters are still not being evoked.

My Model

class User extends Model{
    public $id;
    protected $name;

    public function setName($name){
        $this->name = 'Foo '.$name.' bar';
    }

    public function getName(){
        return $this->name;
    }
}

ColumnMap

array ( 'id' => 'id', 'name' => 'name') 

Tests

Model::setup([
   'ignoreUnknownColumns' => true,
   'disableAssignSetters' => false
]);
$user = User::findFirstById(1); // {id:1, name:'John'}
$user->getName(); // 'John' 

Model::setup([
   'ignoreUnknownColumns' => false,
   'disableAssignSetters' => true
]);
$user = User::findFirstById(1); // {id:1, name:'John'}
$user->getName(); // 'John' 

Model::setup([
   'ignoreUnknownColumns' => true,
   'disableAssignSetters' => true
]);
$user = User::findFirstById(1); // {id:1, name:'John'}
$user->getName(); // 'John' 

Model::setup([
   'ignoreUnknownColumns' => false,
   'disableAssignSetters' => false
]);
$user = User::findFirstById(1); // {id:1, name:'John'}
$user->getName(); // 'John' 

to populate from db to model Phalcon use assign() method maybe some options like ignore_unknown_columns or disable_assign_setters are wrong

edited Feb '18

Something more

class User extends Model
{

    public $id;
    protected $name;

    public function setName($name){
        $this->name = 'Foo '.$name.' bar';
    }

    public function getName(){
        return $this->name;
    }
    public function checkSetter(){
        return $this->_possibleSetter('name', 'Acme');
    }
}

$user->getName(); // John
$user->checkSetter(); // true
$user->getName(); // Foo Acme Name

So, is this line not being called?



12.1k

I don't think it's called by default.



12.1k

Another thing.. with this kind of code, if you save your model in other components or controllers, after a while you could obtain values of name could become something like "Foo Foo Foo Acme Name Name Name". Maybe it's better you manage it inside the getter methods or using the afterFetch event.

This is just a sample. If I can manage this to work, then I can implement the expected/correct behavior

Another thing.. with this kind of code, if you save your model in other components or controllers, after a while you could obtain values of name could become something like "Foo Foo Foo Acme Name Name Name". Maybe it's better you manage it inside the getter methods or using the afterFetch event.

Try it with a get/set of the id

public function getId()
    {
        return $this->id;
    }