Cphalcon: \Phalcon\Mvc\Model to allow constructor parameters

Created on 17 Mar 2014  ·  13Comments  ·  Source: phalcon/cphalcon

Hi, guys!
Would be nice if Phalcon adds a readable and transparent way to require/collect parameters on object construction like below:

use Phalcon\Mvc\Model;

class Foo extends Model
{
    public function onConstruct($bar, $baz)
    {
        // do stuff with $bar and $baz
    }
}

"It prepares the new object for use, often accepting arguments that the constructor uses to set member variables required." - Wikipedia

Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.

All 13 comments

What is the difference between your suggestion and something like:

use Phalcon\Mvc\Model;

class Foo extends Model
{
    public function __construct($bar, $baz)
    {
        // do stuff with $bar and $baz
        parent::__construct();
    }
}

I may be grossly misunderstanding though. ;-)

@btleffler would be awesome use default PHP constructor, but if I try I've got:

Fatal error: Cannot override final method Phalcon\Mvc\Model::__construct() in ....

Phalcon turns all Model's constructor final, so we can't redefine them. In other hand, it give to us initialize and onConstruct methods those will be called after object initialization, but can't define any parameters :/

Thanks for the clarification @hlegius, I didn't realize that the Model's constructor is final.

Additionally, I can't double a Phalcon Model, due its final constructor.

// phpspec snippet
function let($anotherModel)
{
    $anotherModel->beADoubleOf('AnotherModel');
}

It's not a PHPSpec issue. It only can't override Model's __construct. This is a little bit annoying, because to properly test a Phalcon Model I do create real instances.

just run into this, how can I provide model defaults without having a constructor?

I'm also facing the same problem, I'd like to change the table name dynamically during the construction. I need something like

public function onConstruct($tableSuffix)
    {
        $this->setSource("table_".$tableSuffix);
    }

Anyone knows how I can achieve it?

I think you should move code from onConstruct function to initialize function ex:

public function initialize() {
        $prefix = $this->getdi()->getService( 'config' )->getDefinition()->database->prefix;
        $this->setSource( $prefix. strtolower( 'table' ) );     
}

Custom setter wont be enough?

public function dynamicInitialize($var)
{
    $this->whatever($var);
    $this->setSource($var);
    $this->etc();
}

then just $model->dynamicInitialize('blah')

@becca0330
Hi,
i resolved it via static variables:

class MyModel extends \Phalcon\Mvc\Model {

    public static $database = 'xxxxxx';

    public static $source = 'yyyyyy';

    public function initialize() {
        $this->setSchema(static::$database);
        $this->setSource(static::$source);
    }

    public function getSource() {
        return static::$source;
    }

    public function getSchema() {
        return static::$database;
    }

So i am able to change the database and table whenever i want. When i use find() the model uses the values ​​that are currently set.

Swen

@swen100
Hey! Thanks, didn't expect to get an answer so fast! (It was my first post :))
I've tried and it works!!

Implemented in 2.1.x as follows:

$robot = new Robots(array(
    'name' => 'hello'
    'type' => 'Mechanical'
));
$robot->save();

@andresgutierrez
This is cool. Still, I think it would be event better if we could pass the arguments in QueryBuilder.
I am now trying to dynamically set a source to a model, and I find it impossible to use it when working with QueryBuilder - and I need to use in to join the model.
Is it a cool feature?
For my project it would be really great :).

@andresgutierrez @sergeyklay

if we use find() or findFirst() to get data, it will call onConstruct method again without parameters, is this right?

try on v3.1.2 - v3.2.4
such as ..

$robot->find();
or
$robot->findFirst();

some log in my local.

#0  App\Models\Robots->onConstruct(Array ([name] => hello,[type] => Mechanical))
#1  Phalcon\Mvc\Model->__construct(Array ([name] => hello,[type] => Mechanical)) called at [...]
#2  App\Models\BaseModel::getModel(Robots, Array ([name] => hello,[type] => Mechanical)) called at [...]
#3  App\Controllers\Test2Controller->tAction()
#4  Phalcon\Dispatcher->callActionMethod(App\Controllers\Test2Controller Object (...))
#5  Phalcon\Dispatcher->_dispatch()
#6  Phalcon\Dispatcher->dispatch()
#7  Phalcon\Mvc\Application->handle() called at [...]


#0 [internal function]: App\Models\Robots->onConstruct(NULL)
#1 [internal function]: Phalcon\Mvc\Model->__construct(NULL, Object(Phalcon\Di\FactoryDefault), Object(Phalcon\Mvc\Model\Manager))
#2 [internal function]: Phalcon\Mvc\Model\Manager->load('App\\Models\\Robots', true)
#3 [internal function]: Phalcon\Mvc\Model\Query->_prepareSelect()
#4 [internal function]: Phalcon\Mvc\Model\Query->parse()
#5 [internal function]: Phalcon\Mvc\Model\Query->execute()
...

this is the related issue:
https://forum.phalconphp.com/discussion/17411/models-onconstruct-method-will-be-called-twice-when-use-find-or-

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ruudboon picture ruudboon  ·  3Comments

Yakovlev-Melarn picture Yakovlev-Melarn  ·  3Comments

mynameisbogdan picture mynameisbogdan  ·  3Comments

linxlad picture linxlad  ·  3Comments

borisdelev picture borisdelev  ·  3Comments