A lightweight SQL generation library.

Related tags

Miscellaneous atlas
Overview

Atlas

A lightweight SQL builder library without any query execution or database connection requirements.

The primary goals of this package are:

  1. To provide an easy-to-use, yet flexible, API for building SQL queries
  2. To allow customization without polluting the API with all possibilities
  3. To be dependency injection friendly

Installation

Install with Composer:

composer require rebelcode/atlas

Introduction

Start by creating an Atlas instance, then create table helper objects:

use RebelCode\Atlas\Atlas;
use RebelCode\Atlas\Config;

$atlas = Atlas::createDefault();

$users = $atlas->table('users');
$logs = $atlas->table('logs');

Note: The Atlas::table() method creates table objects on-demand if they don't exist, and will return the same instance on subsequent calls. If you prefer explicit control over this behavior, you can use the Atlas::getTable() (which doesn't automatically create table instances) and the Atlas::createTable() (which will override existing tables with the same name).

The large majority of Atlas' API is available from table objects:

$query = $users->select(/* ... */);
$query = $users->insert(/* ... */);
$query = $users->update(/* ... */);
$query = $users->delete(/* ... */);
$query = $users->create(/* ... */);
$query = $users->drop(/* ... */);

These methods return Query objects, which can be turned into strings using the Query::compile() method:

$sql = $user->select(/*...*/)->compile();

Queries

SELECT

Signature:

$table->select($columns, $where, $order, $limit, $offset);

Examples:

use RebelCode\Atlas\Order;

$table = $atlas->table('users');

$table->select();      // SELECT * FROM users
$table->select(null);  // SELECT * FROM users
$table->select(['*']); // SELECT * FROM users

$table->select(['id', 'name', 'email']);
// SELECT id, name, email
// FROM users

$table->select(null, $table->colum('email')->equals('[email protected]'));
// SELECT *
// FROM users
// WHERE email = '[email protected]'

$table->select(null, null, [
    Order::by('name')->desc(),
    Order::by('email')->asc(),
]);
// SELECT *
// FROM users
// ORDER BY name DESC, email ASC

$table->select(null, null, [], 10, 5);
// SELECT *
// FROM users
// LIMIT 10
// OFFSET 5

INSERT

Signature:

$table->insert($listOrRecords);

Example:

$table = $atlas->table('users');

$table->insert([
    [
        'name' => 'Keanu Reeves',
        'email' => '[email protected]'
    ],
    [
        'name' => 'Tom Hardy',
        'email' => '[email protected]'
    ],
]);
// INSERT INTO users (name, email) VALUES
// ('Keanu Reeves', '[email protected]'),
// ('Tom Hardy', '[email protected]')

UPDATE

Signature:

$table->update($set, $where, $order, $limit);

Examples:

$table = $atlas->table('users');

$table->update([
    'name' => 'John Doe',
    'email' => '[email protected]'
]);
// UPDATE users
// SET name = 'John Doe', email = '[email protected]'

$table->update(
    ['status' => 'verified'],
    $table->column('id')->equals(123)
);
// UPDATE users
// SET status = 'verified'
// WHERE id = 123

$table->update(
    ['status' => 'verified'],
    $table->column('type')->equals('member'),
    [
        new Order('name', Order::DESC),
        new Order('email', Order::ASC),
    ],
    10
);
// UPDATE users
// SET status = 'verified'
// WHERE type = 'member'
// ORDER BY name DEC, email ASC
// LIMIT 10

DELETE

Signature:

$table->delete($where, $order, $limit);

Examples:

use RebelCode\Atlas\Order;

$table = $atlas->table('users');

$table->delete();
// DELETE FROM users

$table->delete($table->column('id')->equals(123));
// DELETE FROM users
// WHERE id = 123

$table->delete(
    $table->column('type')->equals('admin'),
    [Order::by('date_joined')->asc()],
    10
);
// DELETE FROM users
// WHERE id = 123
// ORDER BY date_joined ASC
// LIMIT 10

CREATE TABLE

Signature:

$table->create($ifNotExists, $collate): array;

To create tables, you need to specify a Schema when you first call the Atlas::table() method for that table:

$table = $atlas->table('users', new Schema(/*...*/));

$table->create();
// CREATE TABLE IF NOT EXISTS users (...)

$table->create(false);
// CREATE TABLE users (...)

$table->create(false, 'utf8_general_ci');
// CREATE TABLE users (...) COLLATE utf8_general_ci

Note: The create() method, unlike the other methods, does not return a Query object, but rather an array of Query objects. The first query in the array is always the CREATE TABLE query. The rest of the queries are CREATE INDEX queries, one for each index in the table's schema.

Table Schema

A table schema is composed of four parts:

  • The table columns
  • An optional list of keys
  • An optional list of foreign keys
  • An optional list of indexes

Example:

use RebelCode\Atlas\Schema;
use RebelCode\Atlas\Order;

$columns = [
    'id' => new Schema\Column(
        'BIGINT', // Type
        null,     // (optional) Default value
        false,    // (optional) Can be null?
        true      // (optional) Auto increment
    ),
    'email' => new Schema\Column('TEXT'),
    'age' => new Schema\Column('TINYINT UNSIGNED', 0),
    'group' => new Schema\Column('BIGINT', null, true),
];

$keys = [
    'users_pk' => new Schema\Key(
        true,    // Is primary?
        ['id']   // Columns
    ),
    'users_unique_email' => new Schema\Key(false, ['email'])
];

$foreignKeys = [
    'users_group_fk' => new Schema\ForeignKey(
        'groups',                    // Foreign table 
        ['group' => 'id'],           // [local => foreign] column mappings
        Schema\ForeignKey::CASCADE,  // Update rule
        Schema\ForeignKey::SET_NULL, // Delete rule
    ),
];

$indexes = [
    'users_age_index' => new Schema\Index(
        false,                 // Is unique?
        ['age' => Order::ASC], // Sorting
    )
];

$schema = new Schema($columns, $keys, $foreignKeys, $indexes);

DROP TABLE

Signature:

$table->drop($ifExists, $cascade);

Examples:

$table = $atlas->table('users');

$table->drop();
// DROP TABLE IF EXISTS users

$table->drop(false);
// DROP TABLE users

$table->drop(false, true);
// DROP TABLE users CASCADE

Expressions

Atlas includes a simple expression-building API. Expressions are used for WHERE conditions, SELECT columns, UPDATE values, etc.

The system recognizes 3 types of expressions: terms, unary expressions, and binary expressions. Each type can be used to build larger expressions from it using fluent methods. See the BaseExpr class.

$expr->equals(/* ... */);
$expr->gt(/* ... */);
$expr->notIn(/* ... */);
$expr->and(/* ... */);
$expr->like(/* ... */);
$expr->regexp(/* ... */);
$expr->plus(/* ... */);
$expr->intDiv(/* ... */);

Terms

Terms are single values, and can be created using the Term::create() method:

use RebelCode\Atlas\Expression\Term;

Term::create(1);
Term::create('hello');
Term::create(true);
Term::create(false);
Term::create([1, 2, 3]);

Column terms can be created using the Term::column() method:

use RebelCode\Atlas\Expression\Term;

Term::column('name');               // `name`
Term::column('users.name');         // `users`.`name`
Term::column(['users', 'name']);    // `users`.`name`

You don't usually need to create terms manually, since the fluent expression methods will automatically convert scalar/array values into term objects. Additionally, column terms can be created directly from a table object:

$table   = $atlas->table('users');
$nameCol = $users->column('name');

Unary Expressions

Unary expressions represent expressions with only a single operand:

use RebelCode\Atlas\Expression\UnaryExpr;
use RebelCode\Atlas\Expression\Term;

new UnaryExpr(UnaryExpr::NOT, Term::column('is_admin')); // !`is_admin`

$users = $atlas->table('users')
$users->column('is_admin')->not();       // !`users`.`is_admin`

Binary Expressions

Binary expressions represent expressions with two operands:

use \RebelCode\Atlas\Expression\BinaryExpr;
use RebelCode\Atlas\Expression\Term;

new BinaryExpr(Term::column('name'), BinaryExpr::EQ, Term::create('John'));
// `name` = `John`

$users = $atlas->table('users');
$users->column('name')->equals('John');
// `users`.`name` = 'John'

Stateful Tables

Table instances can store WHERE conditions and sorting information. This information is then used in these queries:

  • SELECT
  • UPDATE
  • DELETE

Note that tables are immutable. When adding state to a table, a new table is returned that is identical to the original table in every way except for the relevant state.

WHERE conditions

You can add a WHERE condition to a table using the where() method:

$users = $atlas->table('users');
$admins = $users->where($users->column('type')->equals('admin'));

Multiple calls to this method will merge the conditions using an AND expression. The orWhere() method can be used to join the conditions using an OR expression instead.

$users = $atlas->table('users');

$admins = $users->where($users->column('type')->equals('admin'));

$adminsAndOnline = $admins->where($users->column('status')->equals('online'));
$adminsOrOnline = $admins->orWhere($users->column('status')->equals('online'));

$adminsAndOnline->select();
// SELECT *
// FROM users
// WHERE type = 'admin' AND status = 'online'

$adminsOrOnline->select();
// SELECT *
// FROM users
// WHERE type = 'admin' OR status = 'online'

The condition is used in queries as a default, if no condition is specified as an argument:

$admins->select();
// SELECT *
// FROM users
// WHERE type = 'admin'

If an argument is specified, the argument and state conditions are combined using an AND expression:

$admins->select(null, $admins->column('id')->in([1, 2, 3]));
// SELECT *
// FROM users
// WHERE type = 'admin' AND id IN (1, 2, 3)

Sorting

You can add sorting to a table using the orderBy() method:

$users = $atlas->table('users');

$nameSorted = $users->orderBy([Order::by('name')->asc()]);

Multiple calls to this method will merge the order lists, with prior sorting taking precedence:

$users = $atlas->table('users');

$nameSorted = $users->orderBy([Order::by('name')->asc()]);

$nameEmailSorted = $nameSorted->orderBy([Order::by('email')->desc()]);

When creating queries, the table's sorting is used as a default when the order argument is not specified:

$nameSorted->select();
// SELECT *
// FROM users
// ORDER BY name ASC

If the order argument is specified, the order lists are merged:

$nameSorted->select(null, null, [Order::by('email')->desc()]);
// SELECT *
// FROM users
// ORDER BY name ASC, email DESC

Custom Queries

When creating an Atlas instance, you can supply your own Config. This allows you to modify how the queries are generated.

Currently, the Config only accepts a map of string keys to QueryTypeInterface instances. These instances are responsible for converting Query objects into strings. They are picked from the Config by the Table class when a query needs to be created.

For instance, when you call the Table::insert() method, the table will pick the query type that corresponds to the "INSERT" key.

If you need to customize the query generation, you write your own query types to override the default ones. You can even add new types:

use RebelCode\Atlas\Atlas;
use RebelCode\Atlas\Config;
use RebelCode\Atlas\QueryType;

$config = new Config([
    QueryType::SELECT => new QueryType\Select(),
    QueryType::INSERT => new QueryType\Insert(),
    'custom_type' => new MyCustomType(),
]);

$atlas = new Atlas($config);

Important: You will need to specify all the types. If you only want to make modifications to the default config, you should use Config::withOverrides():

use RebelCode\Atlas\Config;

$config = Config::createDefault()->withOverrides([
    QueryType::INSERT => new CustomInsert(),
    'custom_type' => new MyCustomType(),
]);

Refer to QueryTypeInterface to see what you need to implement to create your own types, and use the existing implementations as guides.

Why "Atlas"?

The name is ironic.

The package is meant to be "lightweight" - we're not sure what the threshold for that criteria is. So we named the package after Atlas, the Greek god that holds up the world on his shoulders. Because well ... presumably, the world is pretty heavy, even for a god.

You might also like...
A next-generation package manager for the front-end
A next-generation package manager for the front-end

Duo is a next-generation package manager that blends the best ideas from Component, Browserify and Go to make organizing and writing front-end code qu

FUGIO: Automatic Exploit Generation for PHP Object Injection Vulnerabilities

FUGIO FUGIO is the first automatic exploit generation (AEG) tool for PHP object injection (POI) vulnerabilities. When exploiting a POI vulnerability,

A PHP sitemap generation tool.

Cartographer A sitemap generation tool for PHP following the Sitemap Protocol v0.9. Cartographer can handle Sitemaps of any size. When generating site

Next-generation front-end for Magento 2
Next-generation front-end for Magento 2

The next-generation front-end for Magento 2. Fast. Reliable. Extensible. Getting started – create a new application and deploy it as Magento 2 theme o

Next generation airdrop tooling. try me!
Next generation airdrop tooling. try me!

Supporting Airdrop Task Solver Singkatnya, project ini terinspirasi oleh Viloid, tapi ini jauh lebih kompleks. Airdrop Task Solver adalah Aplikasi ber

A collection of command line scripts for Magento 2 code generation, and a PHP module system for organizing command line scripts.

What is Pestle? Pestle is A PHP Framework for creating and organizing command line programs An experiment in implementing python style module imports

Blacksmith is a code generation tool which automates the creation of common files that you'd typically create for each entity in your application.
Blacksmith is a code generation tool which automates the creation of common files that you'd typically create for each entity in your application.

Blacksmith is a code generation tool which automates the creation of common files that you'd typically create for each entity in your application.

Highly customizable alternative to var_export for PHP code generation

PHP Variable Exporter PHPEncoder is a PHP library for exporting variables and generating PHP code representations for said variables similar to the bu

Nextcloud app to do preview generation

Preview Generator Nextcloud app that allows admins to pre-generate previews. The app listens to edit events and stores this information. Once a cron j

Releases(v0.1-alpha4)
  • v0.1-alpha4(May 19, 2022)

  • v0.1-alpha3(May 17, 2022)

    Added

    • Select queries now support HAVING and GROUP BY
    • A Group class, which is an alias for the Order class, for use with GROUP BY
    • Fluent query sub-classes: SelectQuery, InsertQuery, UpdateQuery, DeleteQuery

    Changed

    • Table methods select(), insert(), update(), and delete() return the new fluent query sub-classes
    Source code(tar.gz)
    Source code(zip)
  • v0.1-alpha2(May 17, 2022)

  • v0.1-alpha(May 12, 2022)

Owner
RebelCode
WordPress plugins, libraries and resources
RebelCode
Dobren Dragojević 6 Jun 11, 2023
Behat Transliterator library inherited from Doctrine1 and used in Behat for snippet generation

Behat Transliterator Behat Transliterator provides transliteration utilities for PHP. Transliteration data are ported from the Perl Text-Unidecode mod

Behat 2k Dec 22, 2022
It's a CodeIgniter Library for Captcha Generation. With additional Flexibility .

Original Source : Pavel Tzonkov <[email protected]> Source Link : http://gscripts.net/free-php-scripts/Anti_Spam_Scripts/Image_Validator/d

Chris # 4 Sep 2, 2022
A bot written in PHP which attempts to link IRC with SQL database, allowing for integration between platforms

Valeyard IRC-SQL-GateWay A bot written in PHP which attempts to link IRC with SQL database, allowing for integration between platforms. This bot is mo

Valerie Pond 10 Oct 6, 2022
CRUD PHP, SQL PDO

PHP-Mastering CRUD em PHP usando MySQL PDO; Configure a ficheiro config.php de acordo com a sua configuração da base de dados PHP CRUD using PDO MySQL

BaltonCome 4 Jun 2, 2022
First SQL Project - HTML, Bootstrap, PHP enabling CRUD from web

DB-Project First SQL Project with HTML, Bootstrap, PHP enabling CRUD from web Java for mocking data, enabling .csv input Idea This model corresponds t

null 2 Jun 16, 2022
PHP tool to scan ADOdb code for SQL Injections

PHP-Reaper PHP tool to scan ADOdb code for SQL Injections Why The main idea is to be able to detect problems as early as possible, when the code is fr

Emanuil Slavov 32 Nov 19, 2022
Provides an object-oriented API to query in-memory collections in a SQL-style.

POQ - PHP Object Query Install composer require alexandre-daubois/poq 1.0.0-beta2 That's it, ready to go! ?? Usage Here is the set of data we're going

Alexandre Daubois 16 Nov 29, 2022
Application with SQL Injection vulnerability and possible privilege escalation

Application with SQL Injection vulnerability and possible privilege escalation. Free vulnerable app for ethical hacking / penetration testing training.

Filip Karczewski 56 Nov 18, 2022
World countries - available in multiple languages, in CSV, JSON, PHP, SQL and XML formats

Constantly updated lists of world countries and their associated alpha-2, alpha-3 and numeric country codes as defined by the ISO 3166 standard, available in CSV, JSON , PHP, SQL and XML formats, in multiple languages and with national flags included; also available are the ISO 3166-2 codes of provinces/ states associated with the countries

Stefan Gabos 1k Dec 29, 2022