Solved thread

This post is marked as solved. If you think the information contained on this thread must be part of the official documentation, please contribute submitting a pull request to its repository.

Getters/Setters aren't working

Hi!

I have following model:

class Users extends \Phalcon\Mvc\Model
{
    public $ip;
    public function getIp() { return long2ip($this->ip); }
    public function setIp() { $this->ip = ip2long($this->ip); }
}

Testing:

function test($real, $need)
{
    $isOk   = $real == $need;
    $status = $isOk ? ' OK ' : 'FAIL';
    echo "$status | $real => $need\n";
}

// Data for test
$test = [
    'old' => [
        'str' => '127.255.255.255',
        'int' => 2147483647,
    ],
    'new' => [
        'str' => '192.168.1.42',
        'int' => 3232235818,
    ],
];

/** @type Users $user */
$user = Users::findFirst(42);

echo "=== Get ===\n";
test($user->ip             , $test['old']['str']); // FAIL | 2147483647      => 127.255.255.255
test($user->getIp()        , $test['old']['str']); //  OK  | 127.255.255.255 => 127.255.255.255
test($user->toArray()['ip'], $test['old']['str']); // FAIL | 2147483647      => 127.255.255.255

echo "=== Set ===\n";
$user->ip = $test['new']['int'];
test($user->ip             , $test['new']['str']); // FAIL | 3232235818   => 192.168.1.42
test($user->getIp()        , $test['new']['str']); //  OK  | 192.168.1.42 => 192.168.1.42
test($user->toArray()['ip'], $test['new']['str']); // FAIL | 3232235818   => 192.168.1.42

$user->save(); // PDOException: SQLSTATE[22003]: Numeric value out of range: 1264 Out of range value for column 'ip' at row 1

Why getters/setters not working?



3.5k

Check this toppic: http://forum.phalconphp.com/discussion/1131/model-getters-and-setters According to Phalcon ORM documentation all behaviors that you tested are correct.



11.3k
edited Nov '14

Thank you for reply! It now much clearer for me.

Has Phalcon something, that i try to achieve here? Or i must extend framework methods?



11.3k
edited Nov '14

If you set the value using Model::assign, Model::save, Model::create or Model::update it will check for a setter.

Nope ):

$user = new Users();
$user->ip = '127.0.0.1';
$user->save(); // PDOException: SQLSTATE[01000]: Warning: 1265 Data truncated for column 'ip' at row 1

If i see to sql it will be like this:

INSERT INTO `users` (`username`, `ip`) VALUES ('foobar', '127.0.0.1')

But why? I have setter for ip and it must be called to convert string into integer.



2.4k
Accepted
answer

You should try

$user = new Users();
$user->assign(array(
    'ip' => '127.0.0.1'
));
$user->save();

or maybe this (found it in documentation)

$user = new Users();
$user->save(array(
    'ip' => '127.0.0.1'
));

Both functions should check if setter exists and use it.

From my point of view, as you're providing getter and setter, the $ip property should be protected or private, not public.

@Roman small advice

don't use setters and getters as filter

public function setIp() { 
    $this->ip = ip2long($this->ip); 
}

better to use setters and getters with filter

public function setIp($ip) { 
    $this->ip = ip2long($ip); 
}


11.3k
edited Dec '14

From my point of view, as you're providing getter and setter, the $ip property should be protected or private, not public.

Why? I'm trying to hide some background magic with get/set (see below). But i like public properties (except relations).

You should try

Yeah, thank you!

$user = Users::findFirst(42);
if (!$user->save(['ip' => '127.0.0.1']))
    var_dump($user->getMessages());

This snippet works as i expected and issue might be closed – subject solved. But don't hide integers at all (see below).

don't use setters and getters as filter better to use setters and getters with filter

Hm, it seems logical. I need to keep old database structure (for legacy production code) in new api with future migrations in mind. In this case getters/setters are just decorators and/or aggregators between new api and legacy database.

So.. i don't need true setters here – they must totally hide legacy structure from other "client" code.

If you know a better solution for this than getter/setter i'll be grateful for the shared experience.