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

Why model hooks may not work?

Hello!

Trying to use model hooks before/after create/update/save/delete and they're don't work. What i'm doing wrong?

This page (https://docs.phalcon.io/en/latest/reference/models.html#events-and-events-manager) says, that everything i must to do is just add method to model with this name like onConstruct or initialize.

But when i create model, it not works.

System info

# uname -a
Linux packer-virtualbox-iso 3.11.0-15-generic #25~precise1-Ubuntu SMP Thu Jan 30 17:39:31 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

# php -v
PHP 5.4.36-1+deb.sury.org~precise+2 (cli) (built: Dec 21 2014 20:28:53)
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2014 Zend Technologies
    with Xdebug v2.2.3, Copyright (c) 2002-2013, by Derick Rethans

# php -r "echo \Phalcon\Version::get();"
1.3.4

index.php

<?php

use Phalcon\Mvc\Micro as WebApp;

$root   = dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR;
$config = require_once $root . 'config/config.php';
require_once ROOT_PATH . 'config/services.php';
require_once ROOT_PATH . 'config/loader.php';

$app = new WebApp($di);
require_once ROOT_PATH . 'config/routes.php';

$app->handle();
?>

services.php

<?php
$di = new \Phalcon\DI\FactoryDefault();
$di->setShared('db', function () {
    return new \Phalcon\Db\Adapter\Pdo\Mysql(array(
        'adapter'  => 'Mysql',
        'host'     => 'localhost',
        'username' => 'vasya',
        'password' => 'supersecret',
        'dbname'   => 'vasyas_database',
        'options'  => array(
            \PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_OBJ,
            \PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'UTF8'",
        ),
    ));
});
?>

BaseModel

<?php

namespace Api\Models;

use Phalcon\Mvc\Model;

class Base extends Model
{
    protected function getCache() { /* ... */}
    public function serialize() { /* ... */}

    public function validation() { /* ... */}
    public function validationRules() { /* ... */}
    public function getErrorMessages() { /* ... */}

    public function columnMap() { /* ... */}
    public function publicColumns() { /* ... */}
}

?>

Cars

<?php

namespace Api\Models;

class Cars extends Base
{
    public $id;
    public $name;
    public $status; // NOT NULL in database

    const STATUS_DELETED = 0;
    const STATUS_ACTIVE  = 1;
    public static $statuses = array(
        self::STATUS_DELETED,
        self::STATUS_ACTIVE,
    );

    /* HOOKS */
    public function beforeCreate()
    {
        $this->status = self::STATUS_ACTIVE;
    }

    /* CONFIG */
    public function getSource() { return 'cars_list'; }
    public function columnMap()
    {
        return array(
            'id'     => 'id',
            'name'   => 'name',
            'status' => 'status',
        );
    }
}

?>

Somewhere in controller

<?php

namespace Api\Controllers;

class CarsController extends RestController
{
    public function createOne()
    {
        $whiteList = array(
            'name',
        );

        $car = new Cars();

        // OK it's empty
        var_export($car->toArray()); // array ( 'id' => NULL, 'name' => NULL, 'status' => NULL, )

        // Let's create new!
        $created = $car->create($this->request->getPost(), $whiteList);

        // Why status is NULL? beforeSave does not working?
        var_export($car->toArray()); // array ( 'id' => NULL, 'name' => 'foo', 'status' => NULL, )

        // $created == false
        if ($created) $this->respond($car->toArray());

        // Here i've got error:"status is required"
        $this->error($car->getErrorMessages());
    }
}

?>


2.1k
edited Jan '15

er....

$car->save()?



21.7k

Thanks for the reply!

I've right now tried adding status, fill whitelist from Cars::columnMap() and even use Model::create() without any whitelist.. but no, var_export($car->toArray()) after create is the same in all these tests and i've got same error.

In post data i have in this case simple array: array ('name' => 'foobar')

$whiteList = array( 'name', );

because whitelist doesnt include status maybe? whitelist is used to verify which fields can be altered.



2.1k
Accepted
answer
edited Jan '15

found your answer..

beforeValidationOnCreate

beforeValidationOnCreate Is executed before the fields are validated for not nulls/empty strings or foreign keys when an insertion operation is being made



21.7k
edited Jan '15

Hell yeah, "beforeValidationOnCreate" did the trick!

I didn't know that validation on database layer is validation even on application too (Phalcon in this case) layer (o.0) Strange behaviour.

Thank you!

found your answer..

beforeValidationOnCreate

beforeValidationOnCreate Is executed before the fields are validated for not nulls/empty strings or foreign keys when an insertion operation is being made



2.1k

Its because of meta data =)