PHP code example of kinetis / orm

1. Go to this page and download the library: Download kinetis/orm library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

kinetis / orm example snippets


use Kinetis\Orm\Attributes\Column;
use Kinetis\Orm\Attributes\Entity;

#[Entity(table: 'articles')]
final class Article
{
    private int $id;

    private string $title;

    private ?string $summary = null;

    private ArticleStatus $status; // enum ArticleStatus: string

    #[Column(name: 'author')]
    private int $authorId;

    public function __construct(int $id, string $title, int $authorId)
    {
        // Application invariants. Loading an Article never runs this.
        $this->id = $id;
        $this->title = $title;
        $this->authorId = $authorId;
        $this->status = ArticleStatus::Draft;
    }

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

    public function publish(): void
    {
        $this->status = ArticleStatus::Published;
    }
}

use Kinetis\Orm\Attributes\Entity;
use Kinetis\Orm\Attributes\Id;

#[Entity(table: 'tickets')]
final class Ticket
{
    #[Id(generated: true)]
    private ?int $id = null;

    public function __construct(private string $subject) {}

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

use Kinetis\Orm\Metadata\MetadataRegistry;

$metadata = MetadataRegistry::fromClasses([Article::class, Ticket::class]);

// A build step can export it...
file_put_contents('entities.php', ' return ' . var_export($metadata->toArray(), true) . ';');

// ...and a worker load it without scanning a directory.
$metadata = MetadataRegistry::fromArray(

use Kinetis\Orm\OrmFactory;
use Kinetis\Persistence\ConnectionDefinition;
use Kinetis\Persistence\SqlConnectionFactory;

// Once per process.
$db = SqlConnectionFactory::create(new ConnectionDefinition(
    dialect: 'pgsql',
    host: 'db.internal',
    database: 'shop',
    user: 'shop',
    password: $password,
));
$orm = OrmFactory::create($db, $metadata);

// Once per request, job or command.
$entities = $orm->open();

try {
    $article = $entities->repository(Article::class)->findOrFail($id);
    $article->publish();
    $entities->flush();
} finally {
    $entities->close();
}

use Kinetis\Orm\EntityManagerRegistry;
use Kinetis\Orm\OrmFactoryRegistry;

#[Entity(table: 'orders', connection: 'reporting')]
final class Order
{
    // ...
}

// Once per process.
$factories = OrmFactoryRegistry::create(['default' => $db, 'reporting' => $reportingDb], $metadata);

// Once per request, job or command.
$managers = EntityManagerRegistry::create($factories);

try {
    $order = $managers->managerFor(Order::class)->repository(Order::class)->findOrFail($id);
    $article = $managers->manager('default')->repository(Article::class)->findOrFail($articleId);
} finally {
    $managers->close();
}

$articles = $entities->repository(Article::class); // EntityRepository<Article>

$articles->find(42);        // ?Article
$articles->findOrFail(42);  // Article, or EntityNotFoundException
$articles->findBy(['authorId' => 7, 'status' => ArticleStatus::Published]); // list<Article>

$page = $articles->query()  // EntityQuery<Article>
    ->where('status', '=', ArticleStatus::Published)
    ->whereIn('authorId', [7, 8])
    ->orderBy('id', 'DESC')
    ->paginate(perPage: 20, page: 2);

use Kinetis\Orm\EntityManager;

final readonly class PublishedArticles
{
    public function __construct(private EntityManager $entities) {}

    /** @return list<Article> */
    public function by(int $authorId): array
    {
        return $this->entities->repository(Article::class)
            ->findBy(['authorId' => $authorId, 'status' => ArticleStatus::Published]);
    }
}

use Kinetis\Orm\Attributes\BelongsTo;
use Kinetis\Orm\Attributes\Entity;
use Kinetis\Orm\Attributes\HasMany;
use Kinetis\Orm\Attributes\HasOne;

#[Entity(table: 'authors')]
final class Author
{
    public int $id;

    public string $name;

    #[BelongsTo]
    public ?Organization $organization; // organization_id, nullable

    #[HasOne(mappedBy: 'author', owned: true)]
    public ?Profile $profile;

    /** @var list<Post> */
    #[HasMany(target: Post::class, mappedBy: 'author')]
    public array $posts;
}

#[Entity(table: 'posts')]
final class Post
{
    public int $id;

    public string $title;

    #[BelongsTo(column: 'written_by')]
    public Author $author;

    /** @var list<Comment> */
    #[HasMany(target: Comment::class, mappedBy: 'post', owned: true)]
    public array $comments;
}

#[Entity(table: 'comments')]
final class Comment
{
    public int $id;

    #[BelongsTo]
    public Post $post; // post_id

    #[BelongsTo]
    public Author $author; // author_id

    public string $body;
}

#[Entity(table: 'profiles')]
final class Profile
{
    public int $id;

    #[BelongsTo]
    public Author $author; // author_id, with a unique constraint

    public string $bio;
}

$posts = $entities->repository(Post::class)
    ->query()
    ->where('author', '=', 7) // written_by = 7
    ->with('author.organization', 'comments.author')
    ->get();

$posts[0]->author->organization?->name;
$posts[0]->comments[0]->author->name;

$authors = $entities->repository(Author::class)
    ->query()
    ->with('profile', 'posts')
    ->cursorPaginate(25, $cursor);

$authors->data[0]->profile?->bio;

$comments = $entities->repository(Comment::class)
    ->query()
    ->where('post', '=', $postId) // post_id = $postId
    ->cursorPaginate(50, $cursor);

$author = new Author();
[$author->id, $author->name, $author->organization] = [42, 'Jane', null];

$profile = new Profile();
[$profile->id, $profile->author, $profile->bio] = [7, $author, 'Mathematician'];

$author->profile = $profile;    // the owned relationship

$entities->persist($author);    // the profile needs no persist() of its own
$entities->flush();             // INSERT the author, then the profile

$profile->author;               // still $author; nothing in the graph was rewritten

$entities->persist($comment); // $comment->post is not written yet
$entities->persist($post);
$entities->flush();           // INSERT the post, then the comment

$post = $entities->repository(Post::class)->query()->with('comments')->first();

$post->comments = array_values(array_filter($post->comments, fn (Comment $c) => !$c->isSpam()));

$entities->flush(); // DELETE every comment the array no longer holds

$post = $entities->repository(Post::class)->query()->with('comments')->first();

$entities->remove($post);
$entities->flush(); // DELETE each comment, then the post

use Kinetis\Orm\Attributes\Entity;
use Kinetis\Orm\Attributes\ManyToMany;

#[Entity(table: 'courses')]
final class Course
{
    public int $id;

    public string $title;

    /** @var list<Student> */
    #[ManyToMany(
        target: Student::class,
        table: 'course_student',
        joinColumn: 'course_id',
        inverseJoinColumn: 'student_id',
    )]
    public array $students;
}

#[Entity(table: 'students')]
final class Student
{
    public int $id;

    public string $name;

    /** @var list<Course> */
    #[ManyToMany(target: Course::class, mappedBy: 'students')]
    public array $courses;
}

$course = $entities->repository(Course::class)->query()->with('students')->first();

$course->students = [...array_filter($course->students, fn (Student $s) => $s !== $dropped), $enrolled];

$entities->flush(); // DELETE the pair that left, INSERT the pair that joined

$ticket = new Ticket('Printer on fire');
$entities->persist($ticket);    // awaiting insert

$article = $entities->repository(Article::class)->findOrFail(42);
$article->publish();            // a change, found against the snapshot

$entities->remove($entities->repository(Article::class)->findOrFail(43)); // scheduled for deletion

$entities->flush();             // one transaction
$ticket->id();                  // the key the database generated

use Kinetis\Orm\Attributes\Entity;
use Kinetis\Orm\Attributes\Version;
use Kinetis\Orm\Exception\OptimisticLockException;

#[Entity(table: 'orders')]
final class Order
{
    #[Version]
    private int $version = 1; // a signed BIGINT NOT NULL column

    public function __construct(private int $id, private string $status) {}

    public function ship(): void
    {
        $this->status = 'shipped';
    }
}

$entities->repository(Order::class)->findOrFail($id)->ship();

try {
    $entities->flush(); // UPDATE ... WHERE id = ? AND version = <loaded>
} catch (OptimisticLockException) {
    // Another writer changed or deleted the row. Nothing of the flush was written.
    $entities->clear();
    $entities->repository(Order::class)->findOrFail($id)->ship(); // decide again on the current row
    $entities->flush();
}

use DateTimeImmutable;
use DateTimeZone;
use Kinetis\Orm\Attributes\Entity;

#[Entity(table: 'shipments')]
final class Shipment
{
    public ?DateTimeImmutable $deliveredAt = null; // delivered_at DATETIME(6) NULL

    public function __construct(
        private int $id,
        private DateTimeImmutable $shippedAt, // shipped_at DATETIME(6) NOT NULL
    ) {}
}

$entities->repository(Shipment::class)
    ->query()
    ->where('shippedAt', '>=', new DateTimeImmutable('2026-03-04 00:00', new DateTimeZone('Europe/Paris')))
    ->get(); // shipped_at >= ?, bound as '2026-03-03 23:00:00.000000'

use Kinetis\Orm\Attributes\Entity;
use Kinetis\Orm\Date;

#[Entity(table: 'bookings')]
final class Booking
{
    public ?Date $cancelledOn = null; // cancelled_on DATE NULL

    public function __construct(
        private int $id,
        private Date $arrivesOn, // arrives_on DATE NOT NULL
    ) {}
}

new Date(2026, 9, 25);          // (string) '2026-09-25'
Date::fromString('2024-02-29'); // ->year 2024, ->month 2, ->day 29

$entities->repository(Booking::class)
    ->query()
    ->where('arrivesOn', '>=', new Date(2026, 9, 1))
    ->get(); // arrives_on >= ?, bound as '2026-09-01'

use Kinetis\Orm\EntityManager;

$shipped = $orm->transaction(function (EntityManager $entities) use ($id): bool {
    $order = $entities->repository(Order::class)
        ->query()
        ->where('id', '=', $id)
        ->lockForUpdate()
        ->first();

    if ($order === null) {
        return false;
    }

    $order->ship();
    $entities->builder()->table('order_events')->insert(['order_id' => $id, 'event' => 'shipped']);
    $entities->flush(); // the final ORM operation: COMMIT follows the callback's return

    return true;
});