PHPackages                             angel-source-labs/laravel-expressions - 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. angel-source-labs/laravel-expressions

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

angel-source-labs/laravel-expressions
=====================================

Enhanced Database Query Expressions for Laravel. Provides expressions with bindings and expressions that can be used as column values in eloquent

v1.3.1(1mo ago)17.2k1[3 issues](https://github.com/Angel-Source-Labs/laravel-expressions/issues)1MITPHPPHP &gt;=7.3CI failing

Since Aug 30Pushed 5mo ago1 watchersCompare

[ Source](https://github.com/Angel-Source-Labs/laravel-expressions)[ Packagist](https://packagist.org/packages/angel-source-labs/laravel-expressions)[ RSS](/packages/angel-source-labs-laravel-expressions/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (4)Dependencies (16)Versions (8)Used By (1)

Expressions
===========

[](#expressions)

Enhanced Database Query Expressions for Laravel
-----------------------------------------------

[](#enhanced-database-query-expressions-for-laravel)

### What is an Expression?

[](#what-is-an-expression)

An Expression is a string of raw sql that can be used in Laravel Query Builder statements. The Laravel documentation presents the concept of [Raw Expressions](https://laravel.com/docs/master/queries#raw-expressions) as raw SQL strings that can be created via the `DB::raw` facade or by using any of the [raw methods](https://laravel.com/docs/master/queries#raw-methods):

- `selectRaw`
- `whereRaw` / `orWhereRaw`
- `havingRaw` / `orHavingRaw`
- `orderByRaw`
- `groupByRaw`

Laravel represents these expressions as an [Expression](https://laravel.com/api/master/Illuminate/Database/Query/Expression.html)object that can be created using the [DB::raw](https://laravel.com/api/master/Illuminate/Database/Connection.html#method_raw) method.

This package enhances Expressions with the following features

- Add PDO-style bindings to Expressions
- Create `Expression` subclasses that are semantically meaningful
- Assign Expressions to Eloquent attributes
- Make any class into an `Expression` by implementing the `IsExpression` interface
- `ExpressionGrammar`: An Expression can produce the appropriate different grammar for each database by using the `ExpressionGrammar` helper class

### Laravel versions

[](#laravel-versions)

The following Laravel versions are supported:

- Laravel 7.x
- Laravel 8.x
- Laravel 9.x
- Laravel 10.x
- Laravel 11.x
- Laravel 12.x

### install package

[](#install-package)

Install the package with composer

```
composer require angel-source-labs/laravel-expressions
```

### package conflicts: `artisan expressions:doctor`

[](#package-conflicts-artisan-expressionsdoctor)

This package injects new database connection, grammar, and query builder classes, so it potentially conflicts with other packages that inject or override database connections, grammar, or query builder classes.

To test that the installation is working and is not experiencing conflicts from other packages, this package includes an `artisan expressions:doctor` command that will run tests to verify that the database connections are resolving properly and expressions are building properly.

To run the doctor, type `php artisan expressions:doctor` at the command line at the base of your Laravel project.

#### Possible Package Conflicts

[](#possible-package-conflicts)

The following are examples of packages that possibly conflict with this package.

- [grimzy/laravel-mysql-spatial](https://github.com/grimzy/laravel-mysql-spatial)
- [fico7489/laravel-pivot](https://github.com/fico7489/laravel-pivot)
- [chelout/laravel-relationship-events](https://github.com/chelout/laravel-relationship-events)
- [spatie/laravel-query-builder](https://github.com/spatie/laravel-query-builder)
- [dwightwatson/rememberable](https://github.com/dwightwatson/rememberable)
- [kalnoy/nestedset](https://github.com/lazychaser/laravel-nestedset)
- [genealabs/laravel-model-caching](https://github.com/GeneaLabs/laravel-model-caching)

How to Create Expressions
=========================

[](#how-to-create-expressions)

Expression (without bindings)
-----------------------------

[](#expression-without-bindings)

Create an expression by creating a new instance of [AngelSourceLabs\\LaravelExpressions\\Database\\Query\\Expression\\Expression](src/Database/Expression/Expression.php).

```
    public function testSelectRawUsingExpression()
    {
        $expression = new Expression("price as price_before_tax");
        $sql = DB::table('orders')->selectRaw($expression)->toSql();
        $this->assertEquals('select price as price_before_tax from `orders`', $sql);
    }
```

Expression (with bindings)
--------------------------

[](#expression-with-bindings)

Create an expression with bindings by creating a new instance of [AngelSourceLabs\\LaravelExpressions\\Database\\Query\\Expression\\Expression](src/Database/Expression/Expression.php). The first parameter is the raw sql expression using `?` placeholders for the bindings. The second parameter is an array of binding values.

```
        $expression = new Expression("inet_aton(?)", ["192.168.0.1"]);
        DB::table('audits')->where('ip', $expression)->get();
```

This produces the SQL `'select * from `audits`where`ip` = inet_aton(?)'` with a PDO binding of `[1 => "192.168.0.1"]`

Make Expressions Semantically Meaningful
----------------------------------------

[](#make-expressions-semantically-meaningful)

You can create reusable expressions classes with semantic meaning.

```
public class InetAtoN extends Expression
{
    public function __construct($address)
    {
        parent::__construct("inet_aton(?)", $address);
    }
}

DB::table('audits')->where('ip', new InetAtoN("192.168.0.1"))->get();
```

Eloquent - Assign Expressions to Model Attributes
-------------------------------------------------

[](#eloquent---assign-expressions-to-model-attributes)

Expressions can be stored in Eloquent model attributes and will be used in insert and update statements.

```
public class Point extends Expression
{
    public function __construct($lat, $lng)
    {
        parent::__construct("ST_GeomFromText(?, ?)", [$lng, $lat]);
    }
}

$model->point = new Point(44.9561062,-93.1041534);
$model->save();
```

results in the following insert or update statement depending on whether the record is new or already existing:

```
-- example insert statement result
insert into "test_models" ("point") values (ST_GeomFromText(?, ?)) returning "id";

-- example update statement result
update "test_models" set "point" = ST_GeomFromText(?, ?) where "id" = ?;
```

Make Existing Classes into Expressions: `IsExpression` interface and `ProvidesExpression` trait
-----------------------------------------------------------------------------------------------

[](#make-existing-classes-into-expressions-isexpression-interface-and-providesexpression-trait)

When building domain classes, a class may already extend from another class and may not always be able to extend from `Expression`.

You can turn any class into an expression by implementing the `IsExpression` interface.

You can also use the trait `ProvidesExpression` to add the default implementation to your class.

```
class ClassIsExpression implements IsExpression
{
    use ProvidesExpression;
}

function testSelectRawUsingExpression()
{
    $expression = new ClassIsExpression("price as price_before_tax");
    $sql = DB::table('orders')->selectRaw($expression)->toSql();
    $this->assertEquals('select price as price_before_tax from `orders`', $sql);
}
```

In fact the `Expression` class is implemented using the `IsExpression` interface and `ProvidesExpression` trait.

```
use Illuminate\Database\Query\Expression as BaseExpression;

class Expression extends BaseExpression implements IsExpression
{
    use ProvidesExpression;
}
```

`ExpressionGrammar`: Provide expressions with grammar differences by database
-----------------------------------------------------------------------------

[](#expressiongrammar-provide-expressions-with-grammar-differences-by-database)

Sometimes SQL expressions need to provide different grammar for different databases and for different versions of databases.

This package provides an `ExpressionGrammar` class that will produce the appropriate expression for the database and version in use.

For example, when working with `ST_GeomFromText()` between MySQL 8.0 vs MySQL 5.7 and Postgres, the order of latitude and longitude is different, and when switching between databases you might want your code base to work the same without changes. MySQL 8.0 provides an option for `ST_GeomFromText()` to change the axis order. So while the grammar for Postgres will look like `ST_GeomFromText(?, ?)`, the grammar for MySql 8.0 will look like `ST_GeomFromText(?, ?, 'axis-order=long-lat')`.

Creating an `Expression` with an `ExpressionGrammar` to support these three different grammars would look like this:

```
$grammar = ExpressionGrammar::make()
        ->mySql("ST_GeomFromText(?, ?)")
        ->mySql("ST_GeomFromText(?, ?, 'axis-order=long-lat')", "8.0")
        ->postgres("ST_GeomFromText(?, ?)");
$expression = new Expression($grammar, [$lon, $lat]);
```

This will resolve to the following expressions for the specified databases and versions:

databaseversionresultMySQLdefaultST\_GeomFromText(?, ?)MySQL8.0 and higherST\_GeomFromText(?, ?, 'axis-order=long-lat')PostgresdefaultST\_GeomFromText(?, ?)### Available Methods

[](#available-methods)

The `ExpressionGrammar` class provides a fluent interface for adding grammar expressions and has methods for each built-in Laravel driver as well as a generic `grammar` method that allows specifying a driver string for other databases.

#### \#`ExpressionGrammar::make()`

[](#expressiongrammarmake)

Creates a new Grammar instance and provides a fluent interface for adding grammar expressions.

#### \#`ExpressionGrammar->mySql($string, $version (optional))`

[](#expressiongrammar-mysqlstring-version-optional)

Add an expression for MySQL grammar.

#### \#`ExpressionGrammar->postgres($string, $version (optional))`

[](#expressiongrammar-postgresstring-version-optional)

Add an expression for Postgres grammar.

#### \#`ExpressionGrammar->sqLite($string, $version (optional))`

[](#expressiongrammar-sqlitestring-version-optional)

Add an expression for SQLite grammar.

#### \#`ExpressionGrammar->sqlServer($string, $version (optional))`

[](#expressiongrammar-sqlserverstring-version-optional)

Add an expression for SqlServer grammar.

#### \#`ExpressionGrammar->grammar($driver, $string, $version (optional))`

[](#expressiongrammar-grammardriver-string-version-optional)

Add an expression for grammar for other database drivers. `$driver` should match the driver string used by the Laravel query builder driver. For example `$grammar->postgres("ST_GeomFromText(?, ?)")` is equivalent to `$grammar->grammar("pgsql", "ST_GeomFromText(?, ?)")`.

The `$version` parameter is optional. When not specified, the grammar applies as the default. When specified, the grammar applies to the specified version of the database or greater.

`ExpressionGrammar` will throw a `GrammarNotDefinedForDatabaseException` if the Query Builder attempts to resolve an Expression for a Grammar that has not been defined for that database driver.

### Example: Point with ExpressionGrammar

[](#example-point-with-expressiongrammar)

Revisiting the Point example from above using the ExpressionGrammar class to create appropriate grammar for MySql 5.7, MySql 8.0, and Postgres:

```
public class Point extends Expression
{
    public function __construct($lat, $lng)
    {
        parent::__construct(ExpressionGrammar::make()
            ->mySql("ST_GeomFromText(?, ?)")
            ->mySql("ST_GeomFromText(?, ?, 'axis-order=long-lat')", "8.0")
            ->postgres("ST_GeomFromText(?, ?)"),
        [$lng, $lat]);
    }
}

$model->point = new Point(44.9561062,-93.1041534);
$model->save();
```

which will evaluate as an expression and result in the following SQL

```
-- example insert statement result
insert into "test_models" ("point") values (ST_GeomFromText(?, ?)) returning "id";  # MySQL 5.7, postgis
insert into "test_models" ("point") values (ST_GeomFromText(?, ?, 'axis-order=long-lat')) returning "id";  # MySQL 8.0 and greater

-- example update statement result
update "test_models" set "point" = ST_GeomFromText(?, ?) where "id" = ?; # MySQL 5.7, postgis
update "test_models" set "point" = ST_GeomFromText(?, ?, 'axis-order=long-lat') where "id" = ?; # MySQL 8.0 and greater
```

Supported Query Builder Statements
----------------------------------

[](#supported-query-builder-statements)

### `select`

[](#select)

Example:

```
    $expression = new Expression("price * ? as price_with_tax", [1.0825]);
    DB::table('orders')->select($expression)->get();
```

result:

```
    select price * ? as price_with_tax from `orders`; # bindings = [1 => 1.0825]
```

### `selectRaw`

[](#selectraw)

Example 1:

```
    $expression = new Expression("price * ? as price_with_tax", [1.0825]);
    DB::table('orders')->selectRaw($expression)->get();
```

result:

```
    select price * ? as price_with_tax from `orders`; # bindings = [1 => 1.0825]
```

Example 2:

```
    $expression = new Expression("price * ? as price_with_tax, price * ? as profit", [1.0825]);
    DB::table('orders')->selectRaw($expression, [.20])->get();
```

result:

```
    select price * ? as price_with_tax, price * ? as profit from `orders`; # bindings = [1 => 1.0825, 2 => 0.20]
```

### `whereRaw` / `orWhereRaw`

[](#whereraw--orwhereraw)

Example 1:

```
    $expression = new Expression('price > IF(state = "TX", ?, 100)', [200]);
    DB::table('orders')->whereRaw($expression)->get();
```

result:

```
    select * from `orders` where price > IF(state = "TX", ?, 100); # bindings = [1 => 200]
```

Example 2:

```
    $expression = new Expression('price > IF(state = "TX", ?, ?)', [200]);
    DB::table('orders')->whereRaw($expression, [100])->get();
```

result:

```
    select * from `orders` where price > IF(state = "TX", ?, ?); # bindings = [1 => 200, 2 => 100]
```

### `havingRaw` / `orHavingRaw`

[](#havingraw--orhavingraw)

Example 1:

```
    $expression = new Expression('SUM(price) > ?', [2500]);
    $sql = DB::table('orders')
        ->select('department', DB::raw('SUM(price) as total_sales'))
        ->groupBy('department')
        ->havingRaw($expression)
        ->get();
```

result:

```
    select `department`, SUM(price) as total_sales from `orders` group by `department` having SUM(price) > ?; # bindings = [1 => 2500]
```

Example 2:

```
        $expression = new Expression('SUM(price) > ? and AVG(price) > ?', [2500]);
        $sql = DB::table('orders')
            ->select('department', DB::raw('SUM(price) as total_sales'))
            ->groupBy('department')
            ->havingRaw($expression, [100])
            ->get();
```

result:

```
    select `department`, SUM(price) as total_sales from `orders` group by `department` having SUM(price) > ? and AVG(price) > ?; # bindings = [1 => 2500, 2 => 100]
```

### `orderByRaw`

[](#orderbyraw)

Example 1:

```
    $ids = [12,23,34,45];
    $expression = new Expression('field(id, ?, ?, ?, ?)', $ids);
    DB::table('orders')
        ->whereIn('id', $ids)
        ->orderByRaw($expression)
        ->get();
```

result:

```
    select * from `orders` where `id` in (?, ?, ?, ?) order by field(id, ?, ?, ?, ?); # bindings = [1 => 12, 2 => 23, 3 => 34, 4 => 45, 5 => 12, 6 => 23, 7 => 34, 8 => 45]
```

Example 2:

```
    $ids = [12,23,34,45];
    $expression = new Expression('field(id, ?, ?, ?, ?)', [12,23]);
    DB::table('orders')
        ->whereIn('id', $ids)
        ->orderByRaw($expression,[34,45])
        ->get();
```

result:

```
    select * from `orders` where `id` in (?, ?, ?, ?) order by field(id, ?, ?, ?, ?); # bindings = [1 => 12, 2 => 23, 3 => 34, 4 => 45, 5 => 12, 6 => 23, 7 => 34, 8 => 45]
```

### `groupByRaw`

[](#groupbyraw)

Example 1:

```
    $expression = new Expression('price > ?', [100]);
    DB::table('orders')
        ->select('department', 'price')
        ->groupByRaw($expression)
        ->get();
```

result:

```
    select `department`, `price` from `orders` group by price > ?; # bindings = [1 => 100]
```

Example 2:

```
        $expression = new Expression('price > ?, department > ?', [100]);
        DB::table('orders')
            ->select('department', 'price')
            ->groupByRaw($expression, [1560])
            ->get();
```

result:

```
    select `department`, `price` from `orders` group by price > ?, department > ?; # bindings = [1 => 100, 2=> 1560]
```

### `where` / `orWhere`

[](#where--orwhere)

Example:

```
    $expression = new Expression("inet_aton(?)", ["192.168.0.1"]);
    DB::table('audits')->where('ip', $expression)->get();
```

result:

```
    select * from `audits` where `ip` = inet_aton(?); # bindings = [1 => "192.168.0.1"]
```

#### Supported Cases

[](#supported-cases)

##### Basic Where Clauses

[](#basic-where-clauses)

[Basic Where Clauses](https://laravel.com/docs/8.x/queries#basic-where-clauses)

```
$users = DB::table('users')
                ->where('votes', '=', $expression)
                ->where('age', '>', $expression)
                ->get();
```

```
$users = DB::table('users')->where('votes', $expression)->get();
```

##### Or Where Clauses

[](#or-where-clauses)

[Or Where Clauses](https://laravel.com/docs/8.x/queries#or-where-clauses)

##### Additional Where Clauses

[](#additional-where-clauses)

[Additional Where Clauses](https://laravel.com/docs/8.x/queries#additional-where-clauses)

#### Currently Unimplemented / Untested Cases

[](#currently-unimplemented--untested-cases)

These cases are currently not supported (or at least not tested) but likely could be added.

##### Array of Conditions (currently unimplemented / untested)

[](#array-of-conditions-currently-unimplemented--untested)

[Where Clauses](https://laravel.com/docs/8.x/queries#where-clauses)

```
$users = DB::table('users')->where([
    ['status', '=', '1'],
    ['subscribed', '', '1'],
])->get();
```

##### Logical Grouping (currently unimplemented / untested)

[](#logical-grouping-currently-unimplemented--untested)

[Logical Grouping](https://laravel.com/docs/8.x/queries#logical-grouping)

```
$users = DB::table('users')
           ->where('name', '=', 'John')
           ->where(function ($query) {
               $query->where('votes', '>', 100)
                     ->orWhere('title', '=', 'Admin');
           })
           ->get();
```

##### Where Exists Clauses (currently unimplemented / untested)

[](#where-exists-clauses-currently-unimplemented--untested)

[Where Exists Clauses](https://laravel.com/docs/8.x/queries#where-exists-clauses)

```
$users = DB::table('users')
           ->whereExists(function ($query) {
               $query->select(DB::raw(1))
                     ->from('orders')
                     ->whereColumn('orders.user_id', 'users.id');
           })
           ->get();
```

##### Subquery Where Clauses (currently unimplemented / untested)

[](#subquery-where-clauses-currently-unimplemented--untested)

[Subquery Where Clauses](https://laravel.com/docs/8.x/queries#subquery-where-clauses)Case 1: Compare the results of subquery to a value:

```
use App\Models\User;

$users = User::where(function ($query) {
    $query->select('type')
        ->from('membership')
        ->whereColumn('membership.user_id', 'users.id')
        ->orderByDesc('membership.start_date')
        ->limit(1);
}, 'Pro')->get();
```

Case 2: Compare a column to the results of a subquery

```
use App\Models\Income;

$incomes = Income::where('amount', 'dining->meal', 'salad')
                ->get();
```

Run tests
---------

[](#run-tests)

The following tests are run with this pacakge's ExpressionsServiceProvider loaded:

- Unit tests from `vendor/laravel/framework/tests/Database`
- Integration tests from `vendor/laravel/framework/tests/Integration/Database`
- Unit tests from `tests/Unit` (this package)

```
composer test
```

License
-------

[](#license)

Excel Seeder for Laravel is open-sourced software licensed under the MIT license.

###  Health Score

39

—

LowBetter than 86% of packages

Maintenance59

Moderate activity, may be stable

Popularity27

Limited adoption so far

Community14

Small or concentrated contributor base

Maturity47

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 77.8% 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.

###  Release Activity

Cadence

Every ~324 days

Total

5

Last Release

55d ago

PHP version history (2 changes)v1.0PHP &gt;=7.2.5

v1.2PHP &gt;=7.3

### Community

Maintainers

![](https://www.gravatar.com/avatar/75f4790522212e9f5588334a23ab3e4199ea8a465773eb8d7796b84b7055ff26?d=identicon)[bfinlay](/maintainers/bfinlay)

---

Top Contributors

[![bfinlay](https://avatars.githubusercontent.com/u/1757856?v=4)](https://github.com/bfinlay "bfinlay (7 commits)")[![KieranLR](https://avatars.githubusercontent.com/u/39035259?v=4)](https://github.com/KieranLR "KieranLR (2 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/angel-source-labs-laravel-expressions/health.svg)

```
[![Health](https://phpackages.com/badges/angel-source-labs-laravel-expressions/health.svg)](https://phpackages.com/packages/angel-source-labs-laravel-expressions)
```

###  Alternatives

[anourvalar/eloquent-serialize

Laravel Query Builder (Eloquent) serialization

11320.2M21](/packages/anourvalar-eloquent-serialize)[overtrue/laravel-versionable

Make Laravel model versionable.

585308.0k5](/packages/overtrue-laravel-versionable)[abbasudo/laravel-purity

elegant way to add filter and sort in laravel

514330.5k1](/packages/abbasudo-laravel-purity)[statamic-rad-pack/runway

Eloquently manage your database models in Statamic.

135192.6k5](/packages/statamic-rad-pack-runway)[dragon-code/laravel-deploy-operations

Performing any actions during the deployment process

240173.5k2](/packages/dragon-code-laravel-deploy-operations)[stayallive/laravel-eloquent-observable

Register Eloquent model event listeners just-in-time directly from the model.

2928.9k7](/packages/stayallive-laravel-eloquent-observable)

PHPackages © 2026

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