Models
Models represent your database tables as PHP objects using Doctrine ORM's powerful entity system.
Creating Models
Generate a model using Craftsman CLI:
php craftsman make:model User
This creates app/Models/User.php:
app/Models/User.php
<?php
namespace App\Models;
use Doctrine\ORM\Mapping as ORM;
use ZephyrPHP\Database\Model;
#[ORM\Entity]
#[ORM\Table(name: 'users')]
class User extends Model
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private int $id;
#[ORM\Column(type: 'string', length: 255)]
private string $name;
#[ORM\Column(type: 'string', length: 255, unique: true)]
private string $email;
#[ORM\Column(type: 'string', length: 255)]
private string $password;
#[ORM\Column(type: 'datetime')]
private \DateTime $createdAt;
// Getters and setters...
}
Column Types
Doctrine supports various column types:
| Doctrine Type | PHP Type | Description |
|---|---|---|
string |
string | VARCHAR field |
text |
string | TEXT field for long content |
integer |
int | INT field |
bigint |
string | BIGINT field |
boolean |
bool | BOOLEAN field |
decimal |
string | DECIMAL field (precision, scale) |
float |
float | FLOAT field |
datetime |
DateTime | DATETIME field |
date |
DateTime | DATE field |
time |
DateTime | TIME field |
json |
array | JSON field |
Column Options
#[ORM\Column(type: 'string', length: 255)]
private string $name;
#[ORM\Column(type: 'string', unique: true)]
private string $email;
#[ORM\Column(type: 'string', nullable: true)]
private ?string $phone;
#[ORM\Column(type: 'boolean', options: ['default' => false])]
private bool $active = false;
#[ORM\Column(type: 'decimal', precision: 10, scale: 2)]
private string $price;
Querying Models
Finding Records
// Find by primary key
$user = User::find(1);
// Find or fail (throws exception if not found)
$user = User::findOrFail(1);
// Find by criteria
$user = User::findOneBy(['email' => 'john@example.com']);
// Get all records
$users = User::all();
Query Builder
// Simple query
$users = User::query()
->where('active', '=', true)
->all();
// Multiple conditions
$users = User::query()
->where('active', '=', true)
->where('role', '=', 'admin')
->orderBy('created_at', 'DESC')
->all();
// Limit and offset
$users = User::query()
->limit(10)
->offset(20)
->all();
// Count records
$count = User::query()
->where('active', '=', true)
->count();
// Get first record
$user = User::query()
->where('email', '=', 'john@example.com')
->first();
Pagination
// Paginate results (15 per page)
$users = User::query()
->where('active', '=', true)
->paginate(15);
// In your template
{% for user in users.items %}
{{ user.name }}
{% endfor %}
Page {{ users.currentPage }} of {{ users.totalPages }}
Total: {{ users.total }} users
Creating Records
// Create and save
$user = new User();
$user->setName('John Doe');
$user->setEmail('john@example.com');
$user->setPassword(password_hash('secret', PASSWORD_DEFAULT));
$user->save();
// Using fill method
$user = new User();
$user->fill([
'name' => 'John Doe',
'email' => 'john@example.com'
]);
$user->save();
Updating Records
$user = User::find(1);
$user->setName('Jane Doe');
$user->save();
// Or using fill
$user->fill(['name' => 'Jane Doe'])->save();
Deleting Records
$user = User::find(1);
$user->delete();
Relationships
One-to-Many
app/Models/User.php
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection;
#[ORM\Entity]
class User extends Model
{
#[ORM\OneToMany(targetEntity: Post::class, mappedBy: 'author')]
private Collection $posts;
public function __construct()
{
$this->posts = new ArrayCollection();
}
public function getPosts(): Collection
{
return $this->posts;
}
}
app/Models/Post.php
#[ORM\Entity]
class Post extends Model
{
#[ORM\ManyToOne(targetEntity: User::class, inversedBy: 'posts')]
#[ORM\JoinColumn(name: 'author_id', referencedColumnName: 'id')]
private User $author;
public function getAuthor(): User
{
return $this->author;
}
public function setAuthor(User $author): void
{
$this->author = $author;
}
}
Many-to-Many
#[ORM\Entity]
class User extends Model
{
#[ORM\ManyToMany(targetEntity: Role::class)]
#[ORM\JoinTable(name: 'user_roles')]
private Collection $roles;
public function __construct()
{
$this->roles = new ArrayCollection();
}
public function addRole(Role $role): void
{
if (!$this->roles->contains($role)) {
$this->roles->add($role);
}
}
}
Timestamps
Add automatic timestamps to your models:
#[ORM\Entity]
#[ORM\HasLifecycleCallbacks]
class User extends Model
{
#[ORM\Column(type: 'datetime')]
private \DateTime $createdAt;
#[ORM\Column(type: 'datetime')]
private \DateTime $updatedAt;
#[ORM\PrePersist]
public function onPrePersist(): void
{
$this->createdAt = new \DateTime();
$this->updatedAt = new \DateTime();
}
#[ORM\PreUpdate]
public function onPreUpdate(): void
{
$this->updatedAt = new \DateTime();
}
}
Doctrine Documentation
For advanced features like inheritance mapping, custom types, and DQL queries, see the Doctrine ORM documentation.