StormPHP Queries - Guide

StormPHP Queries is a combination of a query builder and an Object-Relational Mapping (ORM) library designed to fetch data effectively. It’s intuitive, lightweight, and flexible — with zero configuration required.


Table of Contents

  1. Quick Start
  2. Basic Queries
  3. Select Query
  4. ORM
  5. Subqueries
  6. Assembling Queries
  7. Insert
  8. Update
  9. Delete
  10. Union
  11. Transactions
  12. RawQueries
  13. Profiling and Logging
  14. Notice
  15. Tests
  16. Examples
  17. Author
  18. License

Quick Start

Installation

composer require stormmore/queries

Establishing a Connection

StormPHP Queries uses PDO:

use Stormmore\Queries\ConnectionFactory;
use Stormmore\Queries\StormQueries;

$connection = ConnectionFactory::createFromString("dsn", "user", "password");
$queries = new StormQueries($connection);

Basic Queries

Find product by ID:

$product = $queries->find('products', ['id' => 5]);

Find all products in a category:

$products = $queries->findAll('products', ['category_id' => 10]);

Find products by complex criteria

$queries->findAll('customers', 'country = ? and customer_name LIKE ?', 'France', '%La%');

Find products and map

$products = $queries->find('products', ['category_id' => 7], Map::select([
    'product_it' => 'id',
    'product_name' => 'name'
], Product::class));

Insert:

$id = $queries->insert('products', [
'name' => 'Golden watch',
'price' => 756
]);

Update:

$queries->update('products', ['id' => $id], ['name' => 'Renamed product']);

Delete:

$queries->delete('products', ['id' => $id]);

Count:

$count = $queries->count('products', ['in_sale' => true]);

Existence check:

$exists = $queries->exist('products', ['id' => 5]);

Map to class:

use Stormmore\Queries\Mapper\Map;

$product = $queries->find('products', ['id' => 5], Map::select([
'product_id'   => 'id',
'product_name' => 'name'
], UserProduct::class));

Select Query

Build a query step by step with a fluent API:

$queries
->select("table", ["column1", "column2"])
->where('id', 2)
->find();

Using aliases

$queries
->select("table", ["column1" => 'colA', "column2"])
->where('id', 2)
->find();

Each method (select, join, leftJoin, where, orderBy, etc.) adds parameters instead of replacing them.

$queries->select('columnA')->select('columnB')->select('columnC');

Aggregation Functions

$queries->select('products')->count();
$queries->select('products')->min('price');
$queries->select('products')->max('price');
$queries->select('products')->sum('price');
$queries->select('products')->avg('price');
$queries->select('customers')->distinct('country');

Join / Left Join

$queries
->select('tableA')
->join('tableB', ['tableB.id' => 'tableA.id')
->find();
//or
$queries
->select('tableA')
->join('tableB', ['tableB.id' => 'tableA.id'])
->find();
$queries
->select('tableA')
->leftJoin('tableB', ['tableB.id' => 'tableA.id'])
->find();
//or
$queries
->select('tableA')
->leftJoin('tableB', ['tableB.id' => 'tableA.id'])
->find();

Where

Supports many operators:

$queries
->select('tableA')
->where('column', 'val1')
->where('column', '=', 'val1')
->where('column', 'IN', ['val2', 'val3'])
->where('column', 'LIKE', '%a%')
->where('column', '<>', 15)
->where('column', 'BETWEEN', 5, 10)
->where('column', 'IS NULL')
->where('columnA = ? and columnB = ?', ['valA', 'valB']);

Default conjunction is AND. Use orWhere for OR.

Nested conditions:

$queries
->select('tableA')
->where('columnA', 'val1')
->where(function($q) {
    $q->where('column', 'val2')->orWhere('column', 'val3');
});

OrderBy

$queries->select('table')->orderByDesc('column1');
$queries->select('table')->orderByAsc('column1');

GroupBy

$queries->select('table')->groupBy('column1', 'column2');

Having

$queries
->select('customers', 'country, city, count(*)')
->groupBy('country, city')
->having('count(*)', '>', 1)
->find();

ORM

Define mappings for query results:

$orders = $queries
->select('orders o', Map::select("orders", [
'order_id'   => 'id',
'order_date' => 'date'
]))
->leftJoin('shippers sh', ['sh.shipper_id' => 'o.shipper_id'], Map::one('shipper', [
    'shipper_id'   => 'id',
    'shipper_name' => 'name'
]))
->findAll();

For the ORM to work without additional configuration:

This allows StormQueries to map records to user-defined objects, even if the key fields differ from the standard id.

Supports:


Subqueries

From:

$queries
->select(SubQuery::create($queries->select('products'), 'p'))
->where('p.product_id', 7)
->find();

Left Join:

$queries
->select(SubQuery::create($queries->from('products'), 'p'))
->leftJoin(SubQuery::create($queries->from('suppliers'), 's'), ['s.supplier_id' => 'p.supplier_id'])
->findAll();

Where with subquery:

$queries
->select("products")
->where("category_id", 1)
->where('price', '<=', $queries
    ->select("avg(price)")
    ->from("products")
    ->where("category_id", 1)
)
->findAll();

Assembling Queries

$query = $queries
->select('products')
->join('product_photos', ['product_photos.product_id' => 'products.id'])
->where('is_in_sale', true);

if ($criteria->hasCategory()) {
$query->where('category_id', $criteria->getCategoryId());
}

if ($criteria->hasOrder()) {
$query->orderBy($criteria->getOrderField(), $criteria->getOrderDirection());
}

if ($criteria->hasSearchPhrase()) {
$query->where('description', "LIKE", '%' . $criteria->getPhrase() . '%');
}

$products = $query->findAll();

Insert

$id = $queries->insert('person', ['name' => 'Michael']);

Insert many:

$queries
->insertMany('person', [
    ['name' => 'Michael'],
    ['name' => 'Kevin'],
    ['name' => 'Martin']
])
->execute();

Update

$queries->update('person', ['id' => 2], ['name' => 'Matthew']);

Or with query builder:

$queries->updateQuery('products')
->where('id', 3)
->set('price = price + 5')
->execute();

Union

$suppliers = $queries->select('suppliers', 'contact_name')->where('contact_name', 'LIKE', '%Michael%');
$customers = $queries->select('customers', 'contact_name')->where('contact_name', 'LIKE', '%Maria%');
$items = $queries->union($suppliers, $customers)->find();

Delete

$queries->delete('person', ['id' => 1]);

Or with query builder:

$queries->deleteQuery('person')->where('id', 1)->execute();

Transactions

try {
    $queries->begin();
    // your queries
    $queries->commit();
}
catch(Throwable $throwable) {
    $queries->rollback();
    throw $throwable;
}

Raw queries

$queries->execute("CREATE SCHEMA storm_test");

$items = $queries->query("SELECT * FROM customers WHERE customer_id = ?", [7]);

Profiling and Logging

$connection->onSuccess(function(string $sql, DateInterval $interval) {
// log successful queries
});

$connection->onFailure(function(string $sql, DateInterval $interval, Exception $e) {
// log failed queries
});

Notice


Tests

Run tests with Docker:

docker-compose up
./run.mysql.cmd

Examples

See the tests directory for more detailed use cases.


Author

Michał Czerski


License

StormPHP Queries is licensed under the MIT License.