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();
}
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;
$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;
});
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.