Question

I am currently developing a Lithium application which requires various things to be added to an object before save() is called.

Ideally I would be able to write a filter to apply to the Model class (the base model that other models extends) such as the following:

Model::applyFilter('save', function($self, $params, $chain) {
    // Logic here
});

Is this possible? If so should it be a bootstrapped file?

Was it helpful?

Solution

If I'm not misunderstanding what you're saying, you want to, for example, automatically add a value for 'created' or 'modified' to an object before save.

Here's how I do that.

From my extensions/data/Model.php

<?php
namespace app\extensions\data;
use lithium\security\Password;

class Model extends \lithium\data\Model {

    public static function __init() {
        parent::__init();

        // {{{ Filters
        static::applyFilter('save', function($self, $params, $chain) {
            $date   = date('Y-m-d H:i:s', time());
            $schema = $self::schema();

            //do these things only if they don't exist (i.e.  on creation of object)
            if (!$params['entity']->exists()) {

                //hash password
                if (isset($params['data']['password'])) {
                    $params['data']['password'] = Password::hash($params['data']['password']);
                }

                //if 'created' doesn't already exist and is defined in the schema...
                if (empty($params['date']['created']) && array_key_exists('created', $schema)) {
                    $params['data']['created'] = $date;
                }
            }

            if (array_key_exists('modified', $schema)) {
                $params['data']['modified'] = $date;
            }
            return $chain->next($self, $params, $chain);
        });
        // }}}
    }
}

?>

I have some password hashing there as well. You can remove that without affecting any functionality.

OTHER TIPS

Filters don't support inheritance*.

You'd better use OOP and have a BaseModel class with an overridden save() method, and from which all your app models inherits.

An other way would be lazily apply filters to each model, in a bootstrapped file. For example:

Filters::apply('app\models\Documents', 'save', $timestamp);
Filters::apply('app\models\Queries', 'save', $timestamp);
Filters::apply('app\models\Projects', 'save', $timestamp);

with $timestamp a closure

* filters inheritance is planned but not yet implemented

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top