Revision: Tue, 29 Oct 2024 10:57:31 GMT

Active Entities

Defining Entities

To work with the Cycle Active Record, you need to extend the entity class with the ActiveRecord.

Note Below are examples of defining entities using attributes (see Annotated Entities), but you are still free to define entities in any other way.

Strict Approach:

In the strict approach, you define your entity with private properties and provide public getter and setter methods to access and modify the properties.

This approach encapsulates the entity's internal state and provides better control over how the properties are accessed and modified.

php
<?php

declare(strict_types=1);

namespace App\Entities;

use Cycle\ActiveRecord\ActiveRecord;
use Cycle\Annotated\Annotation\Column;
use Cycle\Annotated\Annotation\Entity;
use Cycle\ORM\Entity\Behavior\CreatedAt;

#[CreatedAt(field: 'createdAt')]
#[Entity(table: 'users')]
class User extends ActiveRecord
{
    #[Column(type: 'bigInteger', primary: true, typecast: 'int')]
    private int $id;

    #[Column(type: 'string')]
    private string $name;

    #[Column(type: 'string', unique: true)]
    private string $email;

    private \DatetimeImmutable $createdAt;

    public function __construct(string $name, string $email)
    {
        $this->name = $name;
        $this->email = $email;
    }

    public static function create(string $name, string $email): static
    {
        return static::make([
            'name' => $name,
            'email' => $email,
        ]);
    }

    public function id(): int
    {
        return $this->id;
    }

    public function name(): string
    {
        return $this->name;
    }

    public function changeName(string $name): void
    {
        $this->name = $name;
    }

    public function email(): string
    {
        return $this->email;
    }

    public function changeEmail(string $email): void
    {
        $this->email = $email;
    }
}

Creating Entities

Once the entities are described, we can start working with them.

Using constructors is not recommended, as it can lead to undesirable effects, but it's still possible to use them. Look at the Extended Defining Entities section for more information.

Using make() Method

The make() method is a static factory method that accepts an array of properties and returns a new instance of the entity.

php
$user = User::make([
    'name' => $name,
    'email' => $email,
]);

Persisting Entities

To save the entity to the database, you can use the save() method: The save() method returns a result object that contains information about the operation.

php
$result = $user->save();

// Check if the operation was successful
$result->isSuccess();

If you prefer to have an exception thrown when the operation fails, you can use the saveOrFail() method:

php
$user->saveOrFail();

Querying Entities

Entities that extends ActiveRecord class includes powerful Cycle-ORM Query Builder allowing you to fluently query the database table associated with the Entity.

The process of querying data usually takes the following three steps:

  1. Create a new query object by calling the ActiveRecord::query() method;
  2. Build the query object by calling query building methods;
  3. Call a query method to retrieve data in terms of Active Record instances.

Building Queries

The ActiveRecord::query() method returns a new instance of the ActiveQuery class, which is a wrapper around the query builder provided by Cycle ORM. It means that you can use all the methods provided by the query builder and additionally some methods provided by the related ActiveQuery class.

php
// Query all the dog people
$dogsGuys = User::query()
    ->where('likes_dogs', true)
    ->fetchAll();

// Query 10 users who have a dog named Rex
$rexOwners = User::query()
    ->load('pet', ['where' => ['type' => 'dog', 'name' => 'Rex']])
    ->limit(10)
    ->fetchAll();

// Query user by id
$user = User::findByPK($id);

Deleting Entities

To delete a single record, first retrieve the Active Record entity and then call the delete() or deleteOrFail() method.

php
User::findByPK($id)->delete();

Post::findByPK($id)->deleteOrFail();

Transactions

Each call to the save(), delete(), deleteOrFail(), or saveOrFail() method runs at least one transaction to the database. However, you may need to save multiple distinct entities in a single transaction. To achieve this, you can use the transact() method:

php
ActiveRecord::transct(
    function () use ($users, $user, $account, $post) {
        array_walk($users, fn ($user) => $user->save());
        $user->save();
        $account->save();
        $post->delete();
    }
);

All the ActiveRecord write operations within the callback will be registered using the common Entity Manager without being executed until the end of the callback.

It is different from the database transaction because it doesn't start a new DB transaction outside the Entity Manager. To configure the transaction behavior of the Entity Manager, you can use the second parameter of the transact() method:

php
ActiveRecord::transact(
    function () use ($users, $user, $account, $post) {
        array_walk($users, fn ($user) => $user->save());
        $user->save();
        $account->save();
        $post->delete();
    },
    TransactionMode::Ignore,
);

The TransactionMode enum provides the following options:

  • TransactionMode::OpenNew (default) starts a new transaction when the Entity Manager is running after the callback.
  • TransactionMode::Current uses the current transaction and throws an exception if there is no active transaction.
  • TransactionMode::Ignore does nothing about transactions. If there is an active transaction, it won't be committed or rolled back.
Edit this page