0

I have two tables and I am using phalcon's phql to join them.

In my controller i have:

$oBuilder = $this->modelsManager->createBuilder();
$oBuilder->columns(['Tabone.*', 'Tabtwo.*']);
$oBuilder->from(['Tabone']);
$oBuilder->join('Tabtwo', 'Tabone.id = Tabtwo.id');
$oBuilder->where('Tabone.id = 1');
$aRecords = $oBuilder->getQuery()->execute();

/** @var Phalcon\Mvc\Model\Resultset\Complex $aRecords */

//this doesnt work as expected
$aRecords[0]->tabone->setVal(2);
echo "2 != ".$aRecords[0]->tabone->getVal()."<br>";

echo get_class($aRecords[0]->tabone).'<br>';

//this works as expected
$aRecords->getFirst()->tabone->setVal(2);
echo "2 == ".$aRecords->getFirst()->tabone->getVal()."<br>";

So, with the Phalcon's Complex Traversable resultset I am able to set properties using :

$resultset->getFirst()->tabone->setVal(2);
echo $resultset->getFirst()->tabone->getVal();

But when i try :

echo get_class($aRecords[0]->tabone); // Says tabone
$resultset[0]->tabone->setVal(2);
echo $resultset[0]->tabone->getVal();

the value remains unchanged. even though $aRecords[0]->tabone is the class Tabone.

These are my models

class Tabone extends \Phalcon\Mvc\Model
{
    public $id;
    public $val;
    public function columnMap() {
        return array( 'id' => 'id', 'val' => 'val' );
    }
    public function setVal($val) { $this->val = $val; }
    public function getVal() { return $this->val; }
}
class Tabtwo extends \Phalcon\Mvc\Model
{
    public $id;
    public function columnMap() {
        return array( 'id' => 'id' );
    }
}

these are the mysql tables and values

CREATE TABLE tabone (
    id INT(11) NOT NULL AUTO_INCREMENT,
    val INT(11) NOT NULL DEFAULT '0',
    PRIMARY KEY (id)
);
CREATE TABLE tabtwo (
    id INT(11) NOT NULL,
    PRIMARY KEY (id)
);
INSERT INTO tabone (id, val) VALUES (1, 1);
INSERT INTO tabtwo (id) VALUES (1);

Why are the setters/getters no working when using [0] ? Am i doing something i shouldn't ? ...

aconrad
  • 556
  • 5
  • 12

2 Answers2

3

because it is how it works. you have methods for these things available like:

offsetGet() // Gets row in a specific position of the resultset
getFirst()  // Get first row in the resultset
getLast()   // Get last row in the resultset

all methods are here: http://docs.phalconphp.com/en/latest/api/Phalcon_Mvc_Model_Resultset_Complex.html

it's good practice to not use array's key, to keep it simple imagine this:

you are using setters & getters, instead simply setting var's value. But when you want to implement new validation for some input field, you have to go through all the code where you set value, not only just edit your setter. i believe it has some same logic going on here, but i am not developing core of the phalcon, i if you want to get more details you should go check their C code here: https://github.com/phalcon/cphalcon

Lukas Liesis
  • 24,652
  • 10
  • 111
  • 109
  • I would argue that this is not how it works, because in the phql reference at http://docs.phalconphp.com/en/latest/reference/phql.html it says at some point "The result in this case is an object Phalcon\Mvc\Model\Resultset\Complex. This allows access to both complete objects and scalars at once", although its not clear what at once really means... – aconrad Feb 12 '14 at 10:03
  • i'm going for OOP approach :) – Lukas Liesis Feb 12 '14 at 19:31
  • obviously you can do that, but i am looking for the real reason so i can learn something new. From what i got from out there, i think the traversable interface itself does not keep state, which would fit my case perfectly. – aconrad Feb 12 '14 at 22:32
0

With information found on:

http://forum.phalconphp.com/discussion/945/why-properties-of-models-are-lost-

(...) when a resultset is traversed, only just one record is kept in memory, if you modify a record changes will lost, because the record is freed once it is not used anymore. This scheme is very efficient if you are traversing big resultsets (...)

and on Scala: What is the difference between Traversable and Iterable traits in Scala collections?

(...) complying with the Traversable interface does not require keeping state

So, the reason why [0] does not set properties is because traversable means just that, it only traverses the object, any values set directly in the traversed object will be lost, because the object state is not kept.

This makes perfect sense especially when you are talking about large result sets as it will save tons of memory.

Community
  • 1
  • 1
aconrad
  • 556
  • 5
  • 12