ORM for PHP: Comparison and Examples
ORM (Object-Relational Mapping) is a layer between PHP code and a relational database. It turns table rows into objects and SQL queries into methods. There are several mature ORM solutions for PHP. In this article, we will cover the three most popular ones: Doctrine, Eloquent (from Laravel), and Cycle. You will learn their philosophy, syntax, and get ready-to-use code examples.
1. Doctrine ORM — Data Mapper
Doctrine is the most powerful and mature ORM for PHP. It uses the Data Mapper pattern: entities are unaware of the database, and all database operations are performed through repositories and the entity manager EntityManager.
// Example entity in Doctrineuse Doctrine\\ORM\\Mapping as ORM;
/** * @ORM\\Entity * @ORM\\Table(name="users") */class User{ /** @ORM\\Id @ORM\\Column(type="integer") @ORM\\GeneratedValue */ private int $id;
/** @ORM\\Column(type="string", length=100) */ private string $name;
public function getName(): string { return $this->name; }
public function setName(string $name): void { $this->name = $name; }}
// Saving and retrieving$user = new User();$user->setName('Alexey');$entityManager->persist($user);$entityManager->flush();
$users = $entityManager->getRepository(User::class)->findAll();2. Eloquent ORM — Active Record
Eloquent is the ORM from the Laravel framework. It uses the Active Record pattern: each object knows how to save itself to the database. The code is compact and intuitive, ideal for rapid development.
// Eloquent Modeluse Illuminate\\Database\\Eloquent\\Model;
class User extends Model{ protected $table = 'users'; protected $fillable = ['name'];}
// Creating a record$user = User::create(['name' => 'Maria']);
// Reading$users = User::where('name', 'like', '%Ma%')->get();
foreach ($users as $user) { echo $user->name;}
// Updating$user = User::find(1);$user->name = 'Olga';$user->save();3. Cycle ORM — Hybrid Approach
Cycle is a modern ORM from the creators of the Spiral framework. It combines the best features of Data Mapper and Active Record. It works faster than Doctrine due to schema caching and the absence of magic. It supports strict typing.
// Cycle Entityuse Cycle\\Annotated\\Annotation as Cycle;
/** * @Cycle\\Entity * @Cycle\\Table(name="users") */class User{ /** @Cycle\\Column(type="primary") */ public int $id;
/** @Cycle\\Column(type="string") */ public string $name;}
// Saving$user = new User();$user->name = 'Ivan';$orm->persist($user);$orm->run();
// Searching$users = $orm->getRepository(User::class)->select()->fetchAll();Comparison of ORMs for PHP
| Characteristic | Doctrine | Eloquent | Cycle |
|---|---|---|---|
| Pattern | Data Mapper | Active Record | Hybrid |
| Performance | Average | High (with cache) | High |
| Framework Dependency | Independent | Laravel | Spiral / Independent |
| Migration Generation | Built-in | Via Artisan |
Also in library
gRPC for C++: Libraries, Examples, and Usage Guide
Resilience4j for Java: Complete Guide with Examples
CLI Frameworks for Go (Golang): Complete Overview and Comparison
Rate Limiting in Java: Libraries and Tools for Request Control (Bucket4j, Resilience4j)
Recommendations |