Behaviors and filters
A behavior is a ready piece of logic attached to a class without changing its code. To a model it adds, for example, automatic filling of dates. A filter is a controller behavior that runs before the action and can forbid it. Both are attached the same way, in the behaviors() method.
TimestampBehavior in a model
Until now the created_at and updated_at columns had to be filled by hand. Add to models/Post.php:
// models/Post.php
use yii\behaviors\TimestampBehavior;
public function behaviors(): array
{
return [
TimestampBehavior::class,
];
}Now the current time is written to both columns when a post is created, and updated_at is refreshed on update. The lines $post->created_at = time() can be removed from the controller. By default the behavior expects exactly these column names and stores time as a number of seconds.
Configuring a behavior
If the columns are named differently or have the DATETIME type, the behavior is configured with an array:
use yii\db\Expression;
public function behaviors(): array
{
return [
[
'class' => TimestampBehavior::class,
'createdAtAttribute' => 'created',
'updatedAtAttribute' => 'modified',
'value' => new Expression('NOW()'),
],
];
}Expression passes an SQL expression into the query as it is, so the database server supplies the time.
Other model behaviors
| Class | What it does |
|---|---|
yii\behaviors\TimestampBehavior | Fills the creation and update dates |
yii\behaviors\BlameableBehavior | Writes the current user's number to created_by and updated_by |
yii\behaviors\SluggableBehavior | Builds the slug, a part of the URL, from the title |
VerbFilter in a controller
Deleting a record with an ordinary link is dangerous: a search robot may open it. VerbFilter allows an action only the listed request methods. Add to controllers/PostController.php:
// controllers/PostController.php
use yii\filters\VerbFilter;
public function behaviors(): array
{
return [
'verbs' => [
'class' => VerbFilter::class,
'actions' => [
'delete' => ['POST'],
],
],
];
}
public function actionDelete(int $id)
{
Post::findOne($id)?->delete();
return $this->redirect(['post/index']);
}If you open /post/delete?id=1 in the address bar, Yii answers with the 405 "Method Not Allowed" error, and the post stays in place.
A link that sends POST
To make the delete button work, the link gets the data-method attribute:
<?php
// views/post/view.php
use yii\helpers\Html;
?>
<?= Html::a('Delete', ['post/delete', 'id' => $post->id], [
'data' => ['method' => 'post', 'confirm' => 'Delete the post?'],
]) ?>The Yii script intercepts the click, asks for confirmation and sends a POST request together with the _csrf protection key.
Other filters
| Class | What it does |
|---|---|
yii\filters\VerbFilter | Limits request methods |
yii\filters\AccessControl | Lets in only logged-in users or roles |
yii\filters\PageCache | Caches the whole page |
AccessControl is covered in the lesson on authorization.
Common mistake
A controller generated by Gii already has a behaviors() method. If you add a second method with the same name below, PHP stops with the "Cannot redeclare" error. Add new filters to the array of the existing method, each under its own key.