Declare properties in Yii2 Active Record model

375 views Asked by At

I need to declare properties inside an Active Record model. I want to use PHP 8 syntax. So I did:

final class Post extends ActiveRecord
{    
    public ?int $id = null;
    public ?int $user_id = 0;
    public string $slug;
    public ?string $title = null;
    public ?string $content = null;
    public ?string $created_at = null;
    public ?string $updated_at = null;
    public ?string $published_at = null;

    public static function tableName(): string
    {
        return 'posts';
    }

    public function rules(): array
    {
        return [
            [['user_id', 'title', 'content'], 'required'],
            [['user_id'], 'integer'],
            [['content'], 'string'],
            [['slug', 'created_at', 'updated_at', 'published_at'], 'safe'],
            [['title'], 'string', 'max' => 512],
        ];
    }
}

But now all the fields become inaccessible. When I remove them as class fields, everything is ok.

As we can see Yii just removes these model attributes since I declared them as class properties:

SQLSTATE[HY000]: General error: 1364 Field 'user_id' doesn't have a default value The SQL being executed was: INSERT INTO posts (id) VALUES (DEFAULT)

2

There are 2 answers

0
K3v1n 0X90 On

In most active record models in yii2 you put comments to get IDE-support like autocompletion since yii2 is using magic methods to resolve the fields to columns. See Yii2 BaseActiveRecord all the columns are stored in a field _attributes.

So i think the best way you could do is add the doc comments as the following example to your ActiveRecord classes:

/**
 * @property ?int id
 * @property string slug
 * @property-read Author[] authors
 */

note the @property-read indicates a relation and there is a subtile difference when accessing $object->authors; vs $object->getAuthors();. In the first case the relation query is executed and the results are returned as array (via magic methods) and in the second case you get back the raw query that is not executed yet.

And to keep with the authors example the relation method would look like the following:

public function getAuthors(): ActiveQuery
{
    return $this
              ->hasMany(Author::class, ['id' => 'author_id'])
              ->viaTable('post_author', [ 'post_id' => 'id' ]);
}
0
Ravi Thanki On

You can declare property in model like below :

Public $name;

Put name property in rules section for define if you want to apply any rule on that property.