marko / database
Marko Framework Database Layer - Entity-driven schema with Data Mapper pattern
Requires
- php: ^8.5
- marko/core: 0.0.1
Requires (Dev)
- pestphp/pest: ^4.0
This package is auto-updated.
Last update: 2026-03-25 21:07:38 UTC
README
Entity-Driven Schema definition with Data Mapper pattern for the Marko framework.
Installation
composer require marko/database
You typically install a driver package (like marko/database-pgsql) which requires this automatically.
Quick Example
use Marko\Database\Attributes\Column; use Marko\Database\Attributes\Index; use Marko\Database\Attributes\Table; use Marko\Database\Entity\Entity; #[Table('blog_posts')] #[Index(columns: ['slug'], unique: true)] class Post extends Entity { #[Column(primaryKey: true, autoIncrement: true)] public int $id; #[Column(length: 255)] public string $title; #[Column(length: 255, unique: true)] public string $slug; #[Column(type: 'text', nullable: true, default: null)] public ?string $content = null; #[Column(nullable: true, default: 'draft')] public ?string $status = 'draft'; }
Entity-Driven Schema
In Marko, the entity class is the single source of truth for both your PHP types and your database schema. You define columns using PHP attributes directly on entity properties — there is no separate migration file to keep in sync.
Marko compares your entity definitions against the live database schema and generates the necessary DDL to bring them into alignment.
Data Mapper
Marko uses the Data Mapper pattern, keeping domain objects free from persistence concerns. Entities extend Entity but contain no query logic — all database interaction goes through a Repository.
Repository
Repositories handle all database reads and writes for an entity type, keeping persistence logic separate from your domain model.
use Marko\Database\Repository\Repository; class PostRepository extends Repository { protected string $entity = Post::class; }
Type Inference
Marko infers SQL column types from PHP type declarations where possible. For example, int maps to INT, string maps to VARCHAR, and bool maps to TINYINT(1). You can always override the inferred type with an explicit type parameter on #[Column].
Attributes
| Attribute | Purpose |
|---|---|
#[Table] |
Maps a class to a database table |
#[Column] |
Maps a property to a table column |
#[Index] |
Defines an index on one or more columns |
CLI Commands
| Command | Description |
|---|---|
db:diff |
Show pending schema changes |
db:migrate |
Apply pending schema changes |
db:rollback |
Roll back the last migration |
db:status |
Show migration status |
Framework Comparison
| Feature | Laravel | Doctrine | Marko |
|---|---|---|---|
| Schema definition | Migrations | XML/YAML/Annotations | PHP Attributes |
| Pattern | Active Record | Data Mapper | Data Mapper |
| Source of truth | Migration files | Mapping files | Entity classes |
Available Drivers
- marko/database-mysql --- MySQL/MariaDB driver
- marko/database-pgsql --- PostgreSQL driver
Documentation
Full usage, API reference, and examples: marko/database