# Simplifying Database Operations with Eloquent ORM

> From writing raw SQL to model-based access: a practical look at Laravel's Eloquent ORM and how it fits into day-to-day development.

- Published: 2014-10-05
- Category: Framework & Library
- Tags: Laravel
- Reading time: 3 min read
- Source: https://www.muhammetsafak.com.tr/en/blog/simplifying-database-operations-with-eloquent-orm/
- Language: en-US
- Author: Muhammet Şafak

---
Before [switching to Laravel](/en/blog/getting-started-with-my-first-laravel-4-project/), I handled most of my database work by writing SQL by hand. I started with `mysqli_query()`, eventually moved to PDO, but every query still meant writing the same `prepare`, `bindParam`, `execute` cycle over and over. It was repetitive and error-prone.

Laravel's **Eloquent ORM** approaches this from a completely different angle. I've been using it for just over a month now, and the difference in day-to-day work is noticeable.

## What is an ORM?

An **ORM (Object-Relational Mapper)** is the layer that represents database tables as objects on the application side. Instead of talking directly to a table, you work with a PHP object — the ORM handles the query work behind the scenes.

Eloquent is Laravel's implementation of this layer. You define a model class for each database table.

## Defining a Model

`app/models/User.php`:

```php
<?php

class Kullanici extends Eloquent
{
    protected $table = 'kullanicilar';
}
```

That's it. If you leave out the `$table` property, Eloquent will derive the table name from the class name automatically: `Kullanici` → `kullanicis` (using English pluralization rules). If you're using non-English table names, it's safer to specify `$table` explicitly.

## Reading Records

```php
// All users
$kullanicilar = Kullanici::all();

// Single record by ID
$kullanici = Kullanici::find(1);

// Conditional query
$aktifler = Kullanici::where('durum', '=', 'aktif')->get();

// First matching record
$yonetici = Kullanici::where('rol', 'admin')->first();
```

Methods like `all()`, `find()`, and `where()` build the SQL query in the background. You work with PHP methods throughout.

## Creating and Updating Records

```php
// New record
$kullanici = new Kullanici();
$kullanici->ad = 'Ahmet';
$kullanici->email = 'ahmet@ornek.com';
$kullanici->save();

// Or in one line with create() (mass assignment protection must be enabled)
Kullanici::create([
    'ad' => 'Mehmet',
    'email' => 'mehmet@ornek.com'
]);

// Updating
$kullanici = Kullanici::find(5);
$kullanici->email = 'yeni@ornek.com';
$kullanici->save();
```

When using the `create()` method, you need to define the `$fillable` property on the model — this specifies which fields are open to mass assignment:

```php
class Kullanici extends Eloquent
{
    protected $table = 'kullanicilar';
    protected $fillable = ['ad', 'email'];
}
```

Any field not listed in `$fillable` will not be saved, even if it's passed in directly from user input. This is a simple but important protection against attacks where someone adds a field like `role=admin` to a form submission to escalate their privileges. You can also set `$guarded = []` to open all fields, but starting with everything closed and adding fields as needed is a much safer habit.

## Deleting Records

```php
$kullanici = Kullanici::find(3);
$kullanici->delete();

// Or directly
Kullanici::destroy(3);
```

## Query Chaining

One of the things I appreciate about Eloquent is the ability to chain methods:

```php
$sonuc = Kullanici::where('durum', 'aktif')
    ->orderBy('olusturuldu_at', 'desc')
    ->take(10)
    ->get();
```

This fetches the 10 most recently created active users, sorted from newest to oldest. Writing the equivalent in raw SQL would be longer and more prone to mistakes.

## Relationships

Defining relationships between tables at the model level is one of Eloquent's strongest features. Here's a basic example:

```php
class Kullanici extends Eloquent
{
    public function yorumlar()
    {
        return $this->hasMany('Yorum');
    }
}

class Yorum extends Eloquent
{
    public function kullanici()
    {
        return $this->belongsTo('Kullanici');
    }
}
```

After defining these relationships:

```php
$kullanici = Kullanici::find(1);
$yorumlar = $kullanici->yorumlar; // all comments by this user

$yorum = Yorum::find(10);
$yazanKisi = $yorum->kullanici; // the user who wrote the comment
```

You access related data just like a property — a separate SELECT query runs behind the scenes for each relation.

## `firstOrCreate` and `updateOrCreate`

Two methods I find myself reaching for frequently in daily work are those that check whether a record already exists, and create it if it doesn't. Doing this manually looks like:

```php
// Manual: find first, create if not found
$kullanici = Kullanici::where('email', $email)->first();
if (!$kullanici) {
    $kullanici = Kullanici::create(['email' => $email, 'ad' => $ad]);
}
```

Eloquent's `firstOrCreate` method reduces this to a single call:

```php
$kullanici = Kullanici::firstOrCreate([
    'email' => $email,         // Search criteria, and the fields set if not found
    'ad' => $ad
]);
```

`updateOrCreate` takes it a step further — it creates the record if it doesn't exist, or updates it if it does. This is invaluable when working with import jobs or syncing data from external services.

## One Thing to Keep in Mind

Using an ORM doesn't make SQL knowledge unnecessary. It's important to understand what kinds of queries are being generated under the hood. In particular, when fetching related data inside loops, you need to watch out for the **N+1 query problem**.

Here's how N+1 happens: you fetch 10 users (1 query), then fetch each user's comments separately (10 more queries) — 11 queries in total. When the user count reaches 100, that's 101 queries and the page starts to crawl.

Eloquent's `with()` method solves this by eager loading related data in a single query. That's a separate topic in itself, but once you start working with relationships, learning this concept becomes unavoidable.

For now, Eloquent makes day-to-day work considerably less tiring than writing raw SQL. Once the model is defined, everything else flows naturally.

At some point while using an ORM, the question "where is the real SQL actually being written?" comes up. In Laravel, you can inspect the queries Eloquent generates using `DB::listen()` or `dd(DB::getQueryLog())`. Keeping this open in your development environment is a good habit for catching performance issues early. You'll spot unexpected JOIN counts or subqueries in a single query and reconsider how you've structured the model. An ORM abstracts you away from SQL, but when you truly respect the tool, you want to understand what's happening beneath the abstraction.
