Revision #21 has been created by
rackycz on Oct 9, 2025, 10:14:33 AM with the memo:
edit
« previous (#20) next (#22) »
Changes
Title
unchanged
Yii3 - How to start
Category
unchanged
Tutorials
Yii version
unchanged
3.0
Tags
unchanged
Content
changed
[...]
}
```
Register the new command in file `config/console/commands.php`.
> You can also obtain the ConnectionInterface in the same way as you did it in `IndexAction` with the `Query` object. Just use `ContainerInterface $container` in the constructor instead of `ConnectionInterface $db`. Then you can call `$db = $this->container->get(ConnectionInterface::class);`.
## Using Repository and the Model class
Each entity should have its Model class and Repository class if you are storing it in DB. Have a look at the demo application "blog-api": https://github.com/yiisoft/demo
In my case User model (file `src/Entity/User.php`) will only contain private attributes, setters and getters. UserRepository (placed in the same folder) may look like this to enable CRUD (compressed code):
```php
<?php
declare(strict_types=1);
namespace App\Entity;
use DateTimeImmutable;
use Yiisoft\Db\Connection\ConnectionInterface;
use Yiisoft\Db\Exception\Exception;
use Yiisoft\Db\Exception\InvalidConfigException;
use Yiisoft\Db\Query\Query;
final class UserRepository
{
public const TABLE_NAME = 'user';
public function __construct(private readonly ConnectionInterface $db){}
public function findAll(array $orderBy = [], $asArray = false): array
{
$query = (new Query($this->db))->select('*')->from(self::TABLE_NAME)->orderBy($orderBy ?: ['created_at' => SORT_DESC]);
if ($asArray) {
return $query->all();
}
return array_map(
fn(array $row) => $this->hydrate($row),
$query->all()
);
}
public function findBy(string $attr, mixed $value): ?User
{
$row = (new Query($this->db))->select('*')->from(self::TABLE_NAME)->where([$attr => $value])->one();
return $row ? $this->hydrate($row) : null;
}
public function save(User $user): void
{
$data = ['name' => $user->getName(), 'surname' => $user->getSurname(), 'username' => $user->getUsername(), 'email' => $user->getEmail(), 'auth_key' => $user->getAuthKey()];
if ($user->getId() === null) {
$data['created_at'] = (new DateTimeImmutable())->format('Y-m-d H:i:s');
$this->db->createCommand()->insert(self::TABLE_NAME, $data)->execute();
} else {
$this->db->createCommand()->update(self::TABLE_NAME, $data, ['id' => $user->getId()])->execute();
}
}
public function delete(int $id): bool
{
try {
$this->db->createCommand()->delete(self::TABLE_NAME, ['id' => $id])->execute();
} catch (\Throwable $e) {
return false;
}
return true;
}
private function hydrate(array $row): User
{
$user = new User();
$reflection = new \ReflectionClass($user);
$this->hydrateAttribute($reflection, $user, 'id', (int) $row['id']);
$this->hydrateAttribute($reflection, $user, 'name', ($row['name']));
$this->hydrateAttribute($reflection, $user, 'surname', $row['surname']);
$this->hydrateAttribute($reflection, $user, 'username', $row['username']);
$this->hydrateAttribute($reflection, $user, 'email', $row['email']);
$this->hydrateAttribute($reflection, $user, 'created_at', new DateTimeImmutable($row['created_at']));
$this->hydrateAttribute($reflection, $user, 'updated_at', new DateTimeImmutable($row['updated_at'] ?? ''));
return $user;
}
private function hydrateAttribute(\ReflectionClass $reflection, object $obj, string $attribute, mixed $value)
{
$idProperty = $reflection->getProperty($attribute);
$idProperty->setAccessible(true);
$idProperty->setValue($obj, $value);
}
}
```