Courses/PHP/Query Builders & ORM

    Lesson 22 โ€ข Advanced

    Query Builders & ORM Concepts ๐Ÿ—ƒ๏ธ

    Map database tables to PHP objects with query builders, the Active Record pattern, and Eloquent/Doctrine-style relationships.

    What You'll Learn in This Lesson

    • โ€ข Build a fluent query builder with chained methods
    • โ€ข Understand the Active Record and Data Mapper patterns
    • โ€ข Implement CRUD operations with model classes
    • โ€ข Define relationships: hasMany, belongsTo, manyToMany
    • โ€ข Compare Eloquent (Laravel) vs Doctrine (Symfony)

    Building a Query Builder

    A query builder lets you construct SQL queries with a fluent, chainable API. Each method returns $this, so you can chain ->where()->orderBy()->limit() into readable, composable queries โ€” no string concatenation, no SQL injection risk.

    Try It: Query Builder

    Build SQL queries with a fluent API โ€” select, where, join, order, limit

    Try it Yourself ยป
    JavaScript
    // Building a Query Builder from Scratch
    console.log("=== Why Query Builders? ===");
    console.log();
    console.log("Raw SQL:   'SELECT * FROM users WHERE age > 25 AND city = \"London\" ORDER BY name LIMIT 10'");
    console.log("Builder:   $db->table('users')->where('age', '>', 25)->where('city', 'London')->orderBy('name')->limit(10)->get()");
    console.log();
    console.log("Benefits: No SQL injection, readable, composable, database-agnostic");
    console.log();
    
    class QueryBuilder {
      constructor(table) {
      
    ...

    ORM: Active Record Pattern

    An ORM (Object-Relational Mapper) maps each database table to a PHP class and each row to an object. The Active Record pattern (used by Laravel's Eloquent) puts CRUD methods directly on the model: User::find(1), $user->save(), User::where('role', 'admin')->get().

    Try It: Active Record ORM

    Create, read, update models and define relationships

    Try it Yourself ยป
    JavaScript
    // ORM: Mapping Tables to Objects
    console.log("=== Active Record Pattern ===");
    console.log();
    console.log("Each model class = one database table");
    console.log("Each instance = one row in that table");
    console.log();
    
    class Model {
      static tableName = "models";
      static records = [];
      static nextId = 1;
    
      constructor(attrs = {}) {
        this.id = attrs.id || null;
        this.attributes = { ...attrs };
        this.dirty = {};
      }
    
      static create(attrs) {
        let instance = new this(attrs);
        inst
    ...

    โš ๏ธ Common Mistakes

    โš ๏ธ
    N+1 query problem โ€” loading 100 users then accessing $user->posts on each triggers 101 queries. Use eager loading: User::with('posts')->get().
    โš ๏ธ
    Using ORM for everything โ€” complex reports with aggregations, sub-queries, and unions are often cleaner in raw SQL. Use the ORM for CRUD, raw SQL for analytics.
    ๐Ÿ’ก
    Pro Tip: Enable query logging in development to see exactly what SQL your ORM generates. You'll be surprised how many queries run on a single page.

    ๐Ÿ“‹ Quick Reference โ€” ORM

    ConceptEloquent (Laravel)
    Find by IDUser::find(1)
    FilterUser::where('role', 'admin')->get()
    CreateUser::create(['name' => 'Alice'])
    Update$user->update(['name' => 'Bob'])
    Relationship$user->posts (hasMany)
    Eager loadUser::with('posts')->get()

    ๐ŸŽ‰ Lesson Complete!

    You understand query builders and ORMs! Next, dive into authentication with JWT, OAuth2, and API tokens.

    Sign up for free to track which lessons you've completed and get learning reminders.

    Previous

    Cookie & Privacy Settings

    We use cookies to improve your experience, analyze traffic, and show personalized ads. You can manage your preferences below.

    By clicking "Accept All", you consent to our use of cookies for analytics and personalized advertising. You can customize your preferences or reject non-essential cookies.

    Privacy Policy โ€ข Terms of Service