D
D
Dmitry Kim2017-10-12 13:25:15
Yii
Dmitry Kim, 2017-10-12 13:25:15

Is such model logic "kosher" in Yii2?

There is a user model, in which the date of birth in the MySQL database is stored in the DATE field in the “Ymd” format (typical situation). For user input, another date format "dmY" is provided (common case). Then the logic is this:

public function afterFind()
{
    parent::afterFind();
    $this->birthdate = \Yii::$app->formatter->asDate(\DateTime::createFromFormat('Y-m-d', $this->birthdate), 'php:d.m.Y');
}

public function beforeSave($insert)
{
    if (parent::beforeSave($insert)) {
        $this->birthdate = \Yii::$app->formatter->asDate(\DateTime::createFromFormat('d.m.Y', $this->birthdate), 'php:Y-m-d');
        return true;
    }
    return false;
}

Let's say the user entered "12/01/1980", we check that the date is correct, save the model, the model saves the date as "1980-12-01", then we send the model to the client and get the date in an "obscene" format for the user. It would be logical to turn the saved date back into the "normal format", or even more logical to pull the trigger, where we are already doing this:
public function afterSave($insert, $changedAttributes)
{
    parent::afterSave($insert, $changedAttributes);
    $this->trigger(self::EVENT_AFTER_FIND);
}

How correct and "kosher" is this? Or suggest another logic?

Answer the question

In order to leave comments, you need to log in

5 answer(s)
D
Dmitry, 2017-10-12
@slo_nik

Good afternoon.
I think it's redundant.
Store the date in a timestamp, and when outputting to the user, format the date however you like.
In the database "data_birthday INT(11)". When you withdraw, you will receive something like "1497301200".
When displaying the date to the user, format as usual using Yii::$app->formatter->asDate(****).
If this is in the admin panel, then in the GridView, for example, it is enough to specify the date format:

'columns' => [
    'date_birthday:date'
]

Or
'columns' => [
   'attribute' =>  'date_birthday',
   'format' => 'date',
]

With this option, you need to correct the validation rules in the model.

M
Maxim Fedorov, 2017-10-12
@qonand

Not kosher. The model should be responsible for logic and not for data transformation for the user. The view must be responsible for the display format and, accordingly, it must convert the Ymd format to dmY and vice versa. In addition, with this approach, you smear the formatting logic throughout the application (and when you need to change the format, you will have to shovel the entire application ...)

V
vism, 2017-10-12
@vism

And in yii there are no heterosetters for attributes or mutators?
In general, it is optimal to convert to Carbon upon receipt and parse with Carbot when setting the attribute and prepare for the server.
This logic is Kosher and very true (but preferably with seters and getters)
You prepare data in 1 place for receiving and installing.

V
VaNnOrus, 2017-11-14
@VaNnOrus

IMHO, to format the output in the model is not at all according to Feng Shui and there is no sense in this. According to the concept, the "V" representation should be responsible for data formatting in MVC. In all other places, the data must be in the format in which it is stored.
And the processing of user input should take place in prevalidation. If you do a transformation before saving the data, how is the validation going? Validation also involves checking the conformity to the format.

Y
yiiworld, 2017-11-24
@yiiworld

The question itself is not asked "kosherly"))
Variant 1) the logic of your AfterFind (for display) should really only be in the view. Those. it is more convenient to work with data in the model in a single format (for example, in the format in which you get them from the database) (except when this is not possible).
Option 2) finding the data preparation logic in BeforeSave is a bit not kosher. data before display and after receipt will have a different format. Therefore, it is preferable to execute this logic where the data was received (for example, incoming POST in the controller)
Var.3) And for your "I want "integrity"" - here you need to "dance" from the data format with which you work in the model (reference format). In this case:
- before saving(for matching and transforming) use validation (see standalone validators) or [not so kosher]beforeSave()
- after getting from db, do transform in afterFind()
- for display, do transform in views
- for getting from query perform the transformation in the controller
and place all these 4 functions (static) in the base model (or the main one, if there is no base model) and pull them as needed.
PS: answers about setters and getters are of course good, but as such they are just a tool and not a solution (for Var3, you can make getters (and, if necessary, setters) for each case (and 4 virtual attributes, respectively), or you can use the conversion functions directly)
PPS: comrade Maxim Fedorov , who, for formatting in JS, writes absolutely stupid things (read the comments about js and the general architecture), (IMHO). But here is the dissonance - in other answers on the toaster, he is quite sensible to himself.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question