简体   繁体   中英

Lithium: Run filter after find() to format output

I wanted to specify the output of a field from within my model so I added a date key to my $_schema :

models/Tags.php

<?php
    protected $_schema = array(
        'id'       => array('type' => 'integer', 'key'  => 'primary'),
        'title'    => array('type' => 'string'),
        'created'  => array('type' => 'integer', 'date' => 'F jS, Y - g:i a'),
        'modified' => array('type' => 'integer')
    );
?>

I store my time as an unsigned integer in the db (output of time() ).

I want my base model to format any field that has the date key for output. I thought the best place to do that would be right after a find :

extensions/data/Model.php

<?php
    static::applyFilter('find', function($self, $params, $chain) {
        $schema = $self::schema();
        $entity = $chain->next($self, $params, $chain);

        foreach ($schema as $field => $options) {
            if (array_key_exists('date', $options)) {
                //format as a date
                $params['data'][$field] = $entity->formatDate($field, $options['date']);
            }
        }
        return $entity;
    });


    public function formatdate($entity, $field, $format, $timezone = 'Asia/Colombo') {
        $dt = new \DateTime();
        $tz = new \DateTimeZone($timezone);
        $dt->setTimestamp($entity->$field);
        $dt->setTimezone($tz);
        return $dt->format($format);
    }

?>

This doesn't seem to be working. When I execute a find all, this filter seems to get hit twice. The first time, $entity contains a count() of the results and only on the second hit does it contain the Records object.

What am I doing wrong? How do I alter this so that simply doing <?= $tag->created; ?> <?= $tag->created; ?> in my view will format the date the way I want? This, essentially, needs to be an 'after filter', of sorts.

EDIT

If I can find a way to access the current model entity object (not the full namespaced path, $self contains that), I can probably solve my problem.

Regardless of a small fix for your after find filter, I would do it differently.

Every time you'll do a find, you'll override your date format, even if you don't want to display it, but only do a business logic like comparing dates etc ...

Since you want to format your output only in your views (we are not talking about formatting on the fly json responses for an API, etc.), why not using a helper method ?

An other way is to add an instance method in your model (or a BaseModel), called created_at() . Then, you will call it from a view with <?= $entity->created_at() ?> You can still force a format fetched from your $_schema, or pass it as a param, etc ...

A helper seems cleaner as we are talking about presenting data in your views.

I'm reading the OP's problem as the find filter executes twice. If that's right, then why not just check to see if the $entity contains a recordset?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM