PHPackages                             rougin/ezekiel - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. rougin/ezekiel

ActiveLibrary[Database &amp; ORM](/categories/database)

rougin/ezekiel
==============

An expressive SQL query builder in PHP.

11PHPCI passing

Since Sep 22Pushed 6mo ago1 watchersCompare

[ Source](https://github.com/rougin/ezekiel)[ Packagist](https://packagist.org/packages/rougin/ezekiel)[ RSS](/packages/rougin-ezekiel/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependenciesVersions (2)Used By (0)

Ezekiel
=======

[](#ezekiel)

[![Latest Version on Packagist](https://camo.githubusercontent.com/4d8b94b2cb80ee4e359b562780f6d2302da42a7d6d33f70930c19e82e3069f3e/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f726f7567696e2f657a656b69656c2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/rougin/ezekiel)[![Software License](https://camo.githubusercontent.com/55c0218c8f8009f06ad4ddae837ddd05301481fcf0dff8e0ed9dadda8780713e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d627269676874677265656e2e7376673f7374796c653d666c61742d737175617265)](https://github.com/rougin/ezekiel/blob/master/LICENSE.md)[![Build Status](https://camo.githubusercontent.com/cf83250a3269e773586daeef9950282fc13eb7097cf0219aeac0516eb9ec2e63/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f726f7567696e2f657a656b69656c2f6275696c642e796d6c3f7374796c653d666c61742d737175617265)](https://github.com/rougin/ezekiel/actions)[![Coverage Status](https://camo.githubusercontent.com/e851b06e26048a77052b7b597d5e5c0ebd5b516cfe4daa1bdc21634514840d4a/68747470733a2f2f696d672e736869656c64732e696f2f636f6465636f762f632f6769746875622f726f7567696e2f657a656b69656c3f7374796c653d666c61742d737175617265)](https://app.codecov.io/gh/rougin/ezekiel)[![Total Downloads](https://camo.githubusercontent.com/41523b0e508b05393c172cc6e17d9df85e87e1dfd47e4280a045d609f4f1fe9e/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f726f7567696e2f657a656b69656c2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/rougin/ezekiel)

An expressive SQL query builder in PHP. This package is previously known as [Windstorm](https://github.com/rougin/ezekiel/tree/c95c77506087db19033997d1e752ce01c9294056).

Why
---

[](#why)

I tried to unify [Doctrine](https://www.doctrine-project.org/) and [Eloquent](https://laravel.com/docs/5.0/eloquent) into a single interface for them to be swappable. Unfortunately the implementation is not possible because of the different core design patterns ([data mapper](https://en.wikipedia.org/wiki/Data_mapper_pattern) for Doctrine while [active record](https://en.wikipedia.org/wiki/Active_record_pattern) for Eloquent). I realized later that the one thing common for both is their query builder and it was also common on all existing ORM packages and SQL query builders.

Installation
------------

[](#installation)

Install `Ezekiel` through [Composer](https://getcomposer.org/):

```
$ composer require rougin/ezekiel
```

Basic usage
-----------

[](#basic-usage)

Use the `Query` class to create SQL queries:

```
use Rougin\Ezekiel\Query;

$query = (new Query)
    ->select(array('u.id', 'u.name', 'p.name as position'))
    ->from('users u')
    ->leftJoin('positions p')->on('p.id', 'u.position_id')
    ->where('u.name')->like('%winds%')
    ->having('u.id')->greaterThan(0)
    ->orderBy('u.created_at')->desc();

// SELECT u.id, u.name, p.name as position
// FROM users u
// LEFT JOIN positions p ON p.id = u.position_id
// WHERE u.name LIKE ? HAVING u.id > ?
// ORDER BY u.created_at DESC
$sql = $query->toSql();

// array('name' => '%winds%', 'id' => 0)
$binds = $query->getBinds();
```

After creating the query, use the `Result` class to return its contents:

```
use Rougin\Ezekiel\Query;
use Rougin\Ezekiel\Result;

$query = (new Query)
    ->select(array('u.id', 'u.name'))
    ->from('users', 'u')
    ->where('name')->like('%winds%')
    ->orderBy('created_at')->desc();

$pdo = /** returns a PDO instance */;

$result = new Result($pdo);

$items = $result->items($query);

echo json_encode($items);
```

```
[
  {
    "id": 2,
    "name": "Windsor",
    "created_at": "2018-10-15 23:09:47",
    "updated_at": null
  },
  {
    "id": 1,
    "name": "Windstorm",
    "created_at": "2018-10-15 23:06:28",
    "updated_at": null
  },
  {
    "id": 3,
    "name": "Windsy",
    "created_at": "2018-10-15 23:14:45",
    "updated_at": null
  }
]
```

For returning only one item from the result, use the `first` method instead:

```
// ...

use Rougin\Ezekiel\Result;

// ...

$result = new Result($pdo);

$items = $result->first($query);

echo json_encode($items);
```

```
{
  "id": 2,
  "name": "Windsor",
  "created_at": "2018-10-15 23:09:47",
  "updated_at": null
}
```

Using entities
--------------

[](#using-entities)

For mapping query results into an entity object, the entity can be extended to the `Entity` class:

```
// src/Entities/User.php

namespace Test\Entities;

use Rougin\Ezekiel\Entity;

class User extends Entity
{
    protected $id;

    protected $name;

    public function getId()
    {
        return $this->id;
    }

    public function getName()
    {
        return $this->name;
    }

    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }
}
```

If an `Entity` is passed to the `Result` class, the results will be automatically to new instances of that `Entity`:

```
use Rougin\Ezekiel\Query;
use Rougin\Ezekiel\Result;
use Test\Entities\User;

$user = (new User)
    ->select('id, name')->from('users')
    ->where('name')->equals('Windsor');

$pdo = /** returns a PDO instance */ ;

$result = new Result($pdo);

/** @var \Rougin\Ezekiel\Fixture\Entities\User[] */
$users = $result->items($user);

foreach ($users as $user)
{
    echo 'Hello ' . $user->getName() . '!';
}
```

Available methods
-----------------

[](#available-methods)

All available SQL statements should be supported by `Ezekiel`. These includes `DELETE FROM`, `INSERT INTO`, `SELECT`, and `UPDATE`:

### DELETE

[](#delete)

```
use Rougin\Ezekiel\Query;

$query = (new Query)
    ->deleteFrom('users')
    ->where('id')->equals(12);

// DELETE FROM users WHERE id = ?
$sql = $query->toSql();

// array('id' => 12)
$binds = $query->getBinds();
```

### INSERT

[](#insert)

```
use Rougin\Ezekiel\Query;

$query = (new Query)
    ->insertInto('users')
    ->values(array('name' => 'Ezekiel', 'age' => 20));

// INSERT INTO users (name, age) VALUES (?, ?)
$sql = $query->toSql();

// array('name' => 'Ezekiel', 'age' => 20)
$binds = $query->getBinds();
```

### SELECT

[](#select)

```
$query = (new Query)
    ->select(array('u.id', 'u.name'))
    ->from('users u')
    ->where('u.name')->like('%winds%')
    ->orderBy('u.created_at')->desc();

// SELECT u.id, u.name FROM users u
// WHERE u.name LIKE ?
// ORDER BY u.created_at DESC
$sql = $query->toSql();

// array('name' => '%winds%')
$binds = $query->getBinds();
```

### UPDATE

[](#update)

```
use Rougin\Ezekiel\Query;

$query = (new Query)
    ->update('users')
    ->set('name', 'Ezekiel')
    ->where('id')->equals(12);

// UPDATE users SET name = ? WHERE id = ?
$sql = $query->toSql();

// array('name' => 'Ezekiel', 'id' => 12)
$binds = $query->getBinds();
```

Renaming from `Windstorm`
-------------------------

[](#renaming-from-windstorm)

As being renamed from `Windstorm`, this will introduce [backward compatibility](https://en.wikipedia.org/wiki/Backward_compatibility) (BC) breaks through out the source code. This was done to increase extensibility, simplicity and maintainbility and was discussed in one of [my blog post](https://roug.in/hello-world-again/) which aims to solve overengineering of my own open source packages:

> I also want to extend this plan to my personal packages as well like [Staticka](https://github.com/staticka/staticka) and [Transcribe](https://github.com/rougin/transcribe). With this, I will introduce backward compatibility breaks to them initially as it is hard to migrate their codebase due to minimal to no documentation being provided in its basic usage and its internals. As I checked their code, I realized that they are also over engineered, which is a mistake that I needed to atone for when updating my packages in the future.

Please see the [UPGRADING](https://github.com/rougin/ezekiel/blob/master/UPGRADING.md) page for the specified breaking changes.

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more recent changes.

Contributing
------------

[](#contributing)

See [CONTRIBUTING](CONTRIBUTING.md) on how to contribute.

License
-------

[](#license)

The MIT License (MIT). Please see [LICENSE](https://github.com/rougin/ezekiel/blob/master/LICENSE.md) for more information.

###  Health Score

18

—

LowBetter than 8% of packages

Maintenance47

Moderate activity, may be stable

Popularity3

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity15

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://www.gravatar.com/avatar/c7721589a958a1fbcef1b527c794d820d75b82988f14b2ed86a1c6904d76a59e?d=identicon)[rougin](/maintainers/rougin)

---

Top Contributors

[![rougin](https://avatars.githubusercontent.com/u/6078637?v=4)](https://github.com/rougin "rougin (148 commits)")

### Embed Badge

![Health badge](/badges/rougin-ezekiel/health.svg)

```
[![Health](https://phpackages.com/badges/rougin-ezekiel/health.svg)](https://phpackages.com/packages/rougin-ezekiel)
```

###  Alternatives

[doctrine/orm

Object-Relational-Mapper for PHP

10.2k285.3M6.2k](/packages/doctrine-orm)[jdorn/sql-formatter

a PHP SQL highlighting library

3.9k115.1M102](/packages/jdorn-sql-formatter)[illuminate/database

The Illuminate Database package.

2.8k52.4M9.4k](/packages/illuminate-database)[mongodb/mongodb

MongoDB driver library

1.6k64.0M546](/packages/mongodb-mongodb)[ramsey/uuid-doctrine

Use ramsey/uuid as a Doctrine field type.

90340.3M211](/packages/ramsey-uuid-doctrine)[reliese/laravel

Reliese Components for Laravel Framework code generation.

1.7k3.4M16](/packages/reliese-laravel)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
