PHPackages                             tobento/service-storage - 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. tobento/service-storage

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

tobento/service-storage
=======================

A storage interface for storing and fetching items.

2.0.3(6mo ago)029710MITPHPPHP &gt;=8.4

Since Jun 14Pushed 6mo ago1 watchersCompare

[ Source](https://github.com/tobento-ch/service-storage)[ Packagist](https://packagist.org/packages/tobento/service-storage)[ Docs](https://www.tobento.ch)[ RSS](/packages/tobento-service-storage/feed)WikiDiscussions 2.x Synced today

READMEChangelog (10)Dependencies (8)Versions (36)Used By (10)

Storage Service
===============

[](#storage-service)

The Storage Service comes with a query builder for storing and fetching items.

Table of Contents
-----------------

[](#table-of-contents)

- [Getting started](#getting-started)
    - [Requirements](#requirements)
    - [Highlights](#highlights)
    - [Simple Example](#simple-example)
- [Documentation](#documentation)
    - [Storages](#storages)
        - [Pdo MariaDb Storage](#pdo-mariadb-storage)
        - [Pdo MySql Storage](#pdo-mysql-storage)
        - [Pdo Sqlite Storage](#pdo-sqlite-storage)
        - [Json File Storage](#json-file-storage)
        - [In Memory Storage](#in-memory-storage)
        - [Storage Comparison](#storage-comparison)
    - [Queries](#queries)
        - [Select Statements](#select-statements)
            - [Retrieving Methods](#retrieving-methods)
            - [Where Clauses](#where-clauses)
            - [JSON Where Clauses](#json-where-clauses)
            - [Join Clauses](#join-clauses)
            - [Group Clauses](#group-clauses)
            - [Select Columns](#select-columns)
            - [Index Column](#index-column)
            - [Ordering](#order)
            - [Limit](#limit)
        - [Insert Statements](#insert-statements)
        - [Mass Insert Statements](#mass-insert-statements)
            - [Item Factory](#item-factory)
            - [Json File Items](#json-file-items)
        - [Update Statements](#update-statements)
        - [Delete Statements](#delete-statements)
        - [Raw Statements](#raw-statements)
        - [Transactions](#transactions)
        - [Chunking Results and Inserts](#chunking-results-and-inserts)
        - [Miscellaneous](#miscellaneous)
        - [Debugging](#debugging)
    - [Item Interface](#item-interface)
    - [Items Interface](#items-interface)
    - [Tables](#tables)
- [Credits](#credits)

---

Getting started
===============

[](#getting-started)

Add the latest version of the Storage service running this command.

```
composer require tobento/service-storage

```

Requirements
------------

[](#requirements)

- PHP 8.4 or greater

Highlights
----------

[](#highlights)

- Framework-agnostic, will work with any project
- Decoupled design
- Query Builder
- PDO MariaDb Storage
- PDO MySql Storage
- Json File Storage
- In Memory Storage

Simple Example
--------------

[](#simple-example)

Here is a simple example of how to use the Storage service.

```
use Tobento\Service\Storage\Tables\Tables;
use Tobento\Service\Storage\JsonFileStorage;
use Tobento\Service\Storage\ItemInterface;

$tables = new Tables();
$tables->add('products', ['id', 'sku', 'price'], 'id');

$storage = new JsonFileStorage(
    dir: 'home/private/storage/',
    tables: $tables
);

$inserted = $storage
    ->table('products')
    ->insert([
        'id' => 1,
        'sku' => 'pencil',
        'price' => 1.29,
    ]);

$item = $storage->table('products')->find(1);

var_dump($item instanceof ItemInterface);
// bool(true)
```

Documentation
=============

[](#documentation)

Storages
--------

[](#storages)

### Pdo MariaDb Storage

[](#pdo-mariadb-storage)

```
use Tobento\Service\Database\PdoDatabaseFactory;
use Tobento\Service\Storage\Tables\Tables;
use Tobento\Service\Storage\PdoAwareInterface;
use Tobento\Service\Storage\PdoMariaDbStorage;
use Tobento\Service\Storage\StorageInterface;
use PDO;

$pdo = new PdoDatabaseFactory()->createPdo(
    name: 'mysql',
    config: [
        'dsn' => 'mysql:host=localhost;dbname=db_name',
        'username' => 'root',
        'password' => '',
        'options' => [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_EMULATE_PREPARES => false,
        ],
    ],
);

$tables = new Tables();
$tables->add('products', ['id', 'sku', 'price'], 'id');
$tables->add('users', ['id', 'firstname', 'lastname', 'email'], 'id');

$storage = new PdoMariaDbStorage($pdo, $tables);

var_dump($storage instanceof StorageInterface);
// bool(true)

var_dump($storage instanceof PdoAwareInterface);
// bool(true)
```

### Pdo MySql Storage

[](#pdo-mysql-storage)

```
use Tobento\Service\Database\PdoDatabaseFactory;
use Tobento\Service\Storage\Tables\Tables;
use Tobento\Service\Storage\PdoAwareInterface;
use Tobento\Service\Storage\PdoMySqlStorage;
use Tobento\Service\Storage\StorageInterface;
use PDO;

$pdo = new PdoDatabaseFactory()->createPdo(
    name: 'mysql',
    config: [
        'dsn' => 'mysql:host=localhost;dbname=db_name',
        'username' => 'root',
        'password' => '',
        'options' => [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_EMULATE_PREPARES => false,
        ],
    ],
);

$tables = new Tables();
$tables->add('products', ['id', 'sku', 'price'], 'id');
$tables->add('users', ['id', 'firstname', 'lastname', 'email'], 'id');

$storage = new PdoMySqlStorage($pdo, $tables);

var_dump($storage instanceof StorageInterface);
// bool(true)

var_dump($storage instanceof PdoAwareInterface);
// bool(true)
```

### Pdo Sqlite Storage

[](#pdo-sqlite-storage)

```
use PDO;
use Tobento\Service\Database\PdoDatabaseFactory;
use Tobento\Service\Storage\PdoAwareInterface;
use Tobento\Service\Storage\PdoMySqlStorage;
use Tobento\Service\Storage\StorageInterface;
use Tobento\Service\Storage\Tables\Tables;

$pdo = new PdoDatabaseFactory()->createPdo(
    name: 'sqlite',
    config: [
        'dsn' => 'sqlite:path/to/database.sqlite',
        'options' => [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_EMULATE_PREPARES => false,
        ],
    ],
);

$tables = new Tables();
$tables->add('products', ['id', 'sku', 'price'], 'id');
$tables->add('users', ['id', 'firstname', 'lastname', 'email'], 'id');

$storage = new PdoSqliteStorage($pdo, $tables);

var_dump($storage instanceof StorageInterface);
// bool(true)

var_dump($storage instanceof PdoAwareInterface);
// bool(true)
```

### Json File Storage

[](#json-file-storage)

```
use Tobento\Service\Storage\Tables\Tables;
use Tobento\Service\Storage\JsonFileStorage;
use Tobento\Service\Storage\StorageInterface;

$tables = new Tables();
$tables->add('products', ['id', 'sku', 'price'], 'id');
$tables->add('users', ['id', 'firstname', 'lastname', 'email'], 'id');

$storage = new JsonFileStorage(
    dir: 'home/private/storage/',
    tables: $tables
);

var_dump($storage instanceof StorageInterface);
// bool(true)
```

### In Memory Storage

[](#in-memory-storage)

```
use Tobento\Service\Storage\Tables\Tables;
use Tobento\Service\Storage\InMemoryStorage;
use Tobento\Service\Storage\StorageInterface;

$tables = new Tables();
$tables->add('products', ['id', 'sku', 'price'], 'id');
$tables->add('products_lg', ['product_id', 'language_id', 'title']);
$tables->add('users', ['id', 'firstname', 'lastname', 'email'], 'id');

$storage = new InMemoryStorage([
    'products' => [
        1 => ['id' => 1, 'sku' => 'paper', 'price' => 1.2],
        2 => ['id' => 2, 'sku' => 'pen', 'price' => 1.56],
    ],
    'products_lg' => [
        ['product_id' => 1, 'language_id' => 1, 'title' => 'Papier'],
        ['product_id' => 1, 'language_id' => 2, 'title' => 'Paper'],
        ['product_id' => 2, 'language_id' => 1, 'title' => 'Stift'],
    ],
    'users' => [
        1 => ['id' => 1, 'firstname' => 'Erika', 'lastname' => 'Mustermann', 'email' => 'erika.mustermann@example.com'],
        2 => ['id' => 2, 'firstname' => 'Mustermann', 'lastname' => 'Mustermann', 'email' => 'mustermann@example.com'],
    ],
], $tables);

var_dump($storage instanceof StorageInterface);
// bool(true)
```

### Storage Comparison

[](#storage-comparison)

Return items columns support:

Storageinsert()insertMany()update()delete()[Pdo MariaDb Storage](#pdo-mariadb-storage)yesyesnoyes[Pdo MySql Storage](#pdo-mysql-storage)yesnonono[Pdo Sqlite Storage](#pdo-sqlite-storage)yesyesyesyes[Json File Storage](#json-file-storage)yesyesyesyes[In Memory Storage](#in-memory-storage)yesyesyesyesQueries
-------

[](#queries)

### Select Statements

[](#select-statements)

#### Retrieving methods

[](#retrieving-methods)

**get**

Retrieve items.

```
use Tobento\Service\Storage\ItemsInterface;

$products = $storage->table('products')->get();

var_dump($products instanceof ItemsInterface);
// bool(true)

$products->all();
/*Array
(
    [1] => Array
        (
            [id] => 1
            [sku] => paper
            [price] => 1.2
        )

    [2] => Array
        (
            [id] => 2
            [sku] => pen
            [price] => 1.56
        )

)*/
```

Check out [Items Interface](#items-interface) to learn more about it.

**column**

```
use Tobento\Service\Storage\ItemInterface;

$column = $storage->table('products')->column('price');

var_dump($column instanceof ItemInterface);
// bool(true)

$column->all();
/*Array
(
    [0] => 1.2
    [1] => 1.56
)*/
```

Index by a certain column:

```
$storage->table('products')->column('price', 'sku')->all();
/*Array
(
    [paper] => 1.2
    [pen] => 1.56
)*/
```

Check out [Item Interface](#item-interface) to learn more about it.

**first**

Returns the first found item or NULL.

```
use Tobento\Service\Storage\ItemInterface;

$product = $storage->table('products')->first();

var_dump($product instanceof ItemInterface);
// bool(true)

$product->all();
/*Array
(
    [id] => 1
    [sku] => paper
    [price] => 1.2
)*/
```

Check out [Item Interface](#item-interface) to learn more about it.

**find**

Returns a single item by id or NULL.

```
use Tobento\Service\Storage\ItemInterface;

$product = $storage->table('products')->find(2);

var_dump($product instanceof ItemInterface);
// bool(true)

$product->all();
/*Array
(
    [id] => 2
    [sku] => pen
    [price] => 1.56
)*/
```

Check out [Item Interface](#item-interface) to learn more about it.

**value**

Get a single column's value from the first item found.

```
$value = $storage->table('products')->value('sku');

var_dump($value);
// string(5) "paper"
```

**count**

Get the items count.

```
$count = $storage->table('products')->count();

var_dump($count);
// int(2)
```

#### Where Clauses

[](#where-clauses)

**where / orWhere**

```
$products = $storage->table('products')
    ->where('price', '>', 1.3)
    ->get();

$products = $storage->table('products')
    ->where('price', '>', 1.2)
    ->orWhere(function($query) {
        $query->where('price', '>', 1.2)
              ->where('sku', '=', 'pen');
    })
    ->get();

$products = $storage->table('products')
    ->where(function($query) {
        $query->where('price', '>', 1.2)
              ->orWhere('sku', '=', 'pen');
    })
    ->get();

// Finds any values that start with "a"
$products = $storage->table('products')
    ->where('sku', 'like', 'a%')
    ->get();

// Finds any values that end with "a"
$products = $storage->table('products')
    ->where('sku', 'like', '%a')
    ->get();

// Finds any values that have "a" in any position
$products = $storage->table('products')
    ->where('sku', 'like', '%a%')
    ->get();
```

Supported operators: =, !=, &gt;, &lt;, &gt;=, &lt;=, &lt;&gt;, &lt;=&gt;, like, not like

**whereIn / whereNotIn / orWhereIn / orWhereNotIn**

```
$products = $storage->table('products')
    ->whereIn('id', [2, 3])
    ->get();

$products = $storage->table('products')
    ->whereNotIn('id', [2, 3])
    ->get();
```

**whereNull / whereNotNull / orWhereNull / orWhereNotNull**

```
$products = $storage->table('products')
    ->whereNull('price')
    ->get();

$products = $storage->table('products')
    ->whereNotNull('price')
    ->get();
```

**whereBetween / whereNotBetween / orWhereBetween / orWhereNotBetween**

```
$products = $storage->table('products')
    ->whereBetween('price', [1.2, 15])
    ->get();

$products = $storage->table('products')
    ->whereNotBetween('price', [1.2, 15])
    ->get();
```

**whereColumn / orWhereColumn**

```
$users = $storage->table('users')
    ->whereColumn('firstname', '=', 'lastname')
    ->get();
```

Supported operators: =, !=, &gt;, &lt;, &gt;=, &lt;=, &lt;&gt;, &lt;=&gt;

#### JSON Where Clauses

[](#json-where-clauses)

**whereJsonContains / orWhereJsonContains**

```
$products = $storage->table('products')
    ->whereJsonContains('options->color', 'blue')
    ->get();

$products = $storage->table('products')
    ->whereJsonContains('options->color', ['blue', 'red'])
    ->get();
```

**whereJsonContainsKey / orWhereJsonContainsKey**

```
$products = $storage->table('products')
    ->whereJsonContainsKey('options->color')
    ->get();
```

**whereJsonLength / orWhereJsonLength**

```
$products = $storage->table('products')
    ->whereJsonLength('options->color', '>', 2)
    ->get();
```

Supported operators: =, !=, &gt;, &lt;, &gt;=, &lt;=, &lt;&gt;, &lt;=&gt;

#### Join Clauses

[](#join-clauses)

**join**

```
$products = $storage->table('products')
    ->join('products_lg', 'id', '=', 'product_id')
    ->get();
```

**leftJoin / rightJoin**

```
$products = $storage->table('products')
    ->leftJoin('products_lg', 'id', '=', 'product_id')
    ->get();

$products = $storage->table('products')
    ->rightJoin('products_lg', 'id', '=', 'product_id')
    ->get();
```

**Advanced join clauses**

```
$products = $storage->table('products')
    ->join('products_lg', function($join) {
        $join->on('id', '=', 'product_id')
             ->orOn('id', '=', 'language_id');
    })
    ->get();

$products = $storage->table('products')
    ->join('products_lg', function($join) {
        $join->on('id', '=', 'product_id')
             ->where('product_id', '>', 2);
    })
    ->get();
```

#### Group Clauses

[](#group-clauses)

```
$products = $storage->table('products')
    ->groupBy('price')
    ->having('price', '>', 2)
    ->get();

$products = $storage->table('products')
    ->groupBy('price')
    ->havingBetween('price', [1, 4])
    ->get();
```

#### Select Columns

[](#select-columns)

You may select just specific columns.

```
$products = $storage->table('products')
    ->select('id', 'sku')
    ->get();

$product = $storage->table('products')
    ->select('id', 'sku')
    ->first();
```

#### Index Column

[](#index-column)

Specify the column you want the items to be indexed.

```
$products = $storage->table('products')
    ->index('sku')
    ->get();
```

#### Ordering

[](#ordering)

```
$products = $storage->table('products')
    ->order('sku', 'ASC')
    ->get();

$products = $storage->table('products')
    ->order('sku', 'DESC')
    ->get();
```

#### Limit

[](#limit)

```
$products = $storage->table('products')
    ->limit(number: 2, offset: 10)
    ->get();
```

### Insert Statements

[](#insert-statements)

```
use Tobento\Service\Storage\ItemInterface;

$insertedItem = $storage
    ->table('products')
    ->insert([
        'sku' => 'glue',
        'price' => 4.55,
    ]);

var_dump($insertedItem instanceof ItemInterface);
// bool(true)
```

Check out [Item Interface](#item-interface) to learn more about it.

**return specific columns**

```
$insertedItem = $storage
    ->table('products')
    ->insert(
        item: ['sku' => 'glue'],
        return: ['id']
    );

var_dump($insertedItem->all());
```

**return null**

```
$insertedItem = $storage
    ->table('products')
    ->insert(
        item: ['sku' => 'glue'],
        return: null
    );

var_dump($insertedItem->all());
// array(0) { }
```

### Mass Insert Statements

[](#mass-insert-statements)

```
use Tobento\Service\Storage\ItemsInterface;

$insertedItems = $storage
    ->table('products')
    ->insertItems([
        ['sku' => 'glue', 'price' => 4.55],
        ['sku' => 'pencil', 'price' => 1.99],
    ]);

var_dump($insertedItems instanceof ItemsInterface);
// bool(true)
```

Check out [Items Interface](#items-interface) to learn more about it.

**return specific columns**

```
$insertedItems = $storage
    ->table('products')
    ->insertItems(
        items: [
            ['sku' => 'glue', 'price' => 4.55],
            ['sku' => 'pencil', 'price' => 1.99],
        ],
        return: ['id']
    );

var_dump($insertedItems->all());
// array(2) { [0]=> array(1) { ["id"]=> int(3) } [1]=> array(1) { ["id"]=> int(4) } }
```

**return null**

```
$insertedItems = $storage
    ->table('products')
    ->insertItems(
        items: [
            ['sku' => 'glue', 'price' => 4.55],
            ['sku' => 'pencil', 'price' => 1.99],
        ],
        return: null
    );

var_dump($insertedItems->all());
// array(0) { }
```

##### Item Factory

[](#item-factory)

You may use the item factory iterator to seed items and use the [Seeder Service](https://github.com/tobento-ch/service-seeder) to generate fake data.

```
use Tobento\Service\Iterable\ItemFactoryIterator;
use Tobento\Service\Seeder\Str;
use Tobento\Service\Seeder\Num;

$insertedItems = $storage->table('products')
    ->chunk(length: 20000)
    ->insertItems(
        items: new ItemFactoryIterator(
            function() {
                return [
                    'sku' => Str::string(10),
                    'price' => Num::float(min: 1.5, max: 55.5),
                ];
            },
            create: 1000000 // create 1 million items
        )
    );

foreach($insertedItems as $product) {}
```

##### Json File Items

[](#json-file-items)

```
use Tobento\Service\Iterable\JsonFileIterator;
use Tobento\Service\Iterable\ModifyIterator;

$iterator = new JsonFileIterator(
    file: 'private/src/products.json',
);

// you may use the modify iterator:
$iterator = new ModifyIterator(
    iterable: $iterator,
    modifier: function(array $item): array {
        return [
          'sku' => $item['sku'] ?? '',
          'price' => $item['price'] ?? '',
        ];
    }
);

$insertedItems = $storage->table('products')
    ->chunk(length: 20000)
    ->insertItems($iterator);

foreach($insertedItems as $product) {}
```

### Update Statements

[](#update-statements)

You may constrain the update query using where clauses.

```
use Tobento\Service\Storage\ItemsInterface;

$updatedItems = $storage
    ->table('products')
    ->where('id', '=', 2)
    ->update([
        'price' => 4.55,
    ]);

var_dump($updatedItems instanceof ItemsInterface);
// bool(true)
```

Check out [Items Interface](#items-interface) to learn more about it.

**return specific columns**

```
$updatedItems = $storage
    ->table('products')
    ->where('price', '>', 1.5)
    ->update(
        item: ['price' => 4.55],
        return: ['id']
    );

var_dump($updatedItems->all());
// array(2) { [0]=> array(1) { ["id"]=> int(2) } }
```

> ⚠️ **[Pdo MySql Storage](#pdo-mysql-storage) does not return the items as returning statements are not supported.**

You may get the count though:

```
var_dump($updatedItems->count());
// int(1)
```

**return null**

```
$updatedItems = $storage
    ->table('products')
    ->where('price', '>', 1.5)
    ->update(
        item: ['price' => 4.55],
        return: null
    );

var_dump($updatedItems->all());
// array(0) { }
```

**updateOrInsert**

```
use Tobento\Service\Storage\ItemInterface;
use Tobento\Service\Storage\ItemsInterface;

$items = $storage->table('products')->updateOrInsert(
    ['id' => 2], // where clauses
    ['sku' => 'glue', 'price' => 3.48],
    return: ['id']
);

// if updated:
var_dump($items instanceof ItemsInterface);
// bool(true)

// if inserted:
var_dump($items instanceof ItemInterface);
// bool(true)
```

Check out [Item Interface](#item-interface) to learn more about it.

Check out [Items Interface](#items-interface) to learn more about it.

#### Updating JSON Columns

[](#updating-json-columns)

```
$updated = $storage
    ->table('products')
    ->where('id', 2)
    ->update([
        'options->color' => ['red'],
        'options->active' => true,
    ]);
```

### Delete Statements

[](#delete-statements)

```
use Tobento\Service\Storage\ItemsInterface;

$deletedItems = $storage->table('products')
    ->where('price', '>', 1.33)
    ->delete();

var_dump($deletedItems instanceof ItemsInterface);
// bool(true)
```

Check out [Items Interface](#items-interface) to learn more about it.

**return specific columns**

```
$deletedItems = $storage->table('products')
    ->where('id', '=', 2)
    ->delete(return: ['sku']);

var_dump($deletedItems->all());
// array(1) { [0]=> array(1) { ["sku"]=> string(3) "pen" } }
```

**return null**

```
$deletedItems = $storage->table('products')
    ->where('id', '=', 2)
    ->delete(return: null);

var_dump($deletedItems->all());
// array(0) { }
```

### Raw Statements

[](#raw-statements)

Raw statements are only supported by the following storages:

- [Pdo MariaDb Storage](#pdo-mariadb-storage)
- [Pdo MySql Storage](#pdo-mysql-storage)
- [Pdo Sqlite Storage](#pdo-sqlite-storage)

You may use `supportsRawStatements` method to check if the storage supports raw stements:

```
var_dump($storage->supportsRawStatements());
// bool(true)
```

Warning

Raw statements will be injected into the query as strings, so you should be extremely careful to avoid creating SQL injection vulnerabilities.

**selectRaw**

```
// you will need to add the products_counts column as to be verified:
$storage->tables()->add('products', ['status', 'products_count'], 'id');

$products = $storage->table('products')
    ->selectRaw('count(*) as products_count, status')
    ->where('status', '=', 'active')
    ->groupBy('status')
    ->get();
```

**whereRaw**

```
$products = $storage->table('products')
    ->whereRaw('price > ?', [20])
    ->get();
```

**Using The PdoDatabase**

You may consider to install the [Service Database](https://github.com/tobento-ch/service-database) and use [Pdo Database](https://github.com/tobento-ch/service-database#pdo-database) if you need full control:

```
use Tobento\Service\Database\PdoDatabase;
use Tobento\Service\Storage\PdoAwareInterface;

if ($storage instanceof PdoAwareInterface) {
    $database = new PdoDatabase(pdo: $storage->pdo(), name: 'some-name');

    $products = $database->execute(
        statement: 'SELECT title FROM products WHERE color = ?',
        bindings: ['blue']
    )->fetchAll();
}
```

### Transactions

[](#transactions)

**commit**

```
$storage->begin();

// your queries

$storage->commit();
```

**rollback**

```
$storage->begin();

// your queries

$storage->rollback();
```

**transaction**

You may use the transaction method to run a set of storage operations within a transaction. If an exception is thrown within the transaction closure, the transaction will automatically be rolled back. If the closure executes successfully, the transaction will automatically be committed.

```
use Tobento\Service\Storage\StorageInterface;

$storage->transaction(function(StorageInterface $storage) {
    // your queries
});
```

### Chunking Results and Inserts

[](#chunking-results-and-inserts)

You may use the chunk method if you need to work with thousands or even millions of item(s).

**column**

Returns the column in generator mode.

```
$column = $storage->table('products')
    ->chunk(length: 2000)
    ->column('price');

foreach($column as $price) {
    var_dump($price);
    // float(1.2)
}
```

**get**

Returns the items in generator mode.

```
$products = $storage->table('products')
    ->chunk(length: 2000)
    ->get();

foreach($products as $product) {
    var_dump($product['sku']);
    // string(5) "paper"
}
```

**insertItems**

Returns the inserted items in generator mode.

```
$insertedItems = $storage
    ->table('products')
    ->chunk(length: 10000)
    ->insertItems([
        ['sku' => 'glue', 'price' => 4.55],
        ['sku' => 'pencil', 'price' => 1.99],
        // ...
    ]);

foreach($insertedItems as $product) {
    var_dump($product['id']);
    // int(3)
}
```

If you set the return parameter to null it will immediately insert the items but not return them in generator mode. You may be able to get the number of items created though.

```
$insertedItems = $storage
    ->table('products')
    ->chunk(length: 10000)
    ->insertItems([
        ['sku' => 'glue', 'price' => 4.55],
        ['sku' => 'pencil', 'price' => 1.99],
        // ...
    ], return: null);

var_dump($insertedItems->count());
// int(2)
```

### Miscellaneous

[](#miscellaneous)

**new**

The new method will return a new storage instance.

```
$newStorage = $storage->new();
```

**fetchItems**

The fetchItems method will return all table items.

```
$iterable = $storage->fetchItems(table: 'products');
```

**storeItems**

The storeItems method will store the items to the table which will be truncated first.

```
$storedItems = $storage->storeItems(
    table: 'products',
    items: [] // iterable
);
```

**deleteTable**

The deleteTable method will delete the table completely.

```
$storage->deleteTable('products');
```

### Debugging

[](#debugging)

```
[$statement, $bindings] = $storage->table('products')
    ->where('id', '=', 1)
    ->getQuery();

var_dump($statement);
// string(56) "SELECT `id`,`sku`,`price` FROM `products` WHERE `id` = ?"

var_dump($bindings);
// array(1) { [0]=> int(1) }
```

**Using a Closure**

You must use a Closure if you want to debug other retrieving methods than "get" or insert, update and delete statements.

```
[$statement, $bindings] = $storage->table('products')
    ->where('id', '=', 1)
    ->getQuery(function(StorageInterface $storage) {
        $storage->update([
            'price' => 4.55,
        ]);
    });

var_dump($statement);
// string(48) "UPDATE `products` SET `price` = ? WHERE `id` = ?"

var_dump($bindings);
// array(2) { [0]=> float(4.55) [1]=> int(1) }
```

Item Interface
--------------

[](#item-interface)

Iterating item attributes:

```
use Tobento\Service\Storage\ItemInterface;
use Tobento\Service\Storage\Item;

$item = new Item(['title' => 'Title']);

var_dump($item instanceof ItemInterface);
// bool(true)

foreach($item as $attr) {
    var_dump($attr);
    // string(5) "Title"
}
```

**get**

Get an item value by key.

```
use Tobento\Service\Storage\ItemInterface;
use Tobento\Service\Storage\Item;

$item = new Item(['title' => 'Title']);

var_dump($item instanceof ItemInterface);
// bool(true)

var_dump($item->get('title'));
// string(5) "Title"

// returns the default value if the key does not exist.
var_dump($item->get('sku', 'Sku'));
// string(3) "Sku"
```

**all**

Returns all items (attributes).

```
use Tobento\Service\Storage\Item;

$item = new Item(['title' => 'Title']);

var_dump($item->all());
// array(1) { ["title"]=> string(5) "Title" }
```

**count**

Returns the number of the attributes.

```
use Tobento\Service\Storage\Item;

$item = new Item(['title' => 'Title']);

var_dump($item->count());
// int(1)
```

**collection**

Returns a new Collection with the attributes.

```
use Tobento\Service\Storage\Item;
use Tobento\Service\Collection\Collection;

$item = new Item(['title' => 'Title']);

var_dump($item->collection() instanceof Collection);
// bool(true)
```

Check out the [Collection](https://github.com/tobento-ch/service-collection#collection) to learn more about it.

Items Interface
---------------

[](#items-interface)

Iterating items:

```
use Tobento\Service\Storage\ItemsInterface;
use Tobento\Service\Storage\Items;

$items = new Items([
    'foo' => ['title' => 'Title'],
]);

var_dump($items instanceof ItemsInterface);
// bool(true)

foreach($items as $item) {
    var_dump($item['title']);
    // string(5) "Title"
}
```

**get**

Get an item value by key.

```
use Tobento\Service\Storage\Items;

$items = new Items([
    'foo' => ['title' => 'Title'],
]);

var_dump($items->get('foo.title'));
// string(5) "Title"

// returns the default value if the key does not exist.
var_dump($items->get('foo.sku', 'Sku'));
// string(3) "Sku"
```

**all**

Returns all items.

```
use Tobento\Service\Storage\Items;

$items = new Items([
    'foo' => ['title' => 'Title'],
]);

var_dump($items->all());
// array(1) { ["foo"]=> array(1) { ["title"]=> string(5) "Title" } }
```

**first**

Returns the first item, otherwise null.

```
use Tobento\Service\Storage\Items;

$items = new Items([
    ['foo' => 'Foo'],
    ['bar' => 'Bar'],
]);

var_dump($items->first());
// array(1) { ["foo"]=> string(3) "Foo" }
```

**column**

Returns the column of the items.

```
use Tobento\Service\Storage\Items;

$items = new Items([
    ['name' => 'Foo', 'id' => 3],
    ['name' => 'Bar', 'id' => 5],
]);

var_dump($items->column(column: 'name'));
// array(2) { [0]=> string(3) "Foo" [1]=> string(3) "Bar" }

// with index
var_dump($items->column(column: 'name', index: 'id'));
// array(2) { [3]=> string(3) "Foo" [5]=> string(3) "Bar" }
```

**map**

Map over each of the items returning a new instance.

```
use Tobento\Service\Storage\Items;
use Tobento\Service\Storage\Item;

$items = new Items([
    ['foo' => 'Foo'],
    ['bar' => 'Bar'],
]);

$itemsNew = $items->map(function(array $item): object {
    return new Item($item);
});

var_dump($itemsNew->first());
// object(Tobento\Service\Storage\Item)#8 ...
```

**groupBy**

Returns a new instance with the grouped items.

```
use Tobento\Service\Storage\Items;

$items = new Items([
    ['name' => 'bear', 'group' => 'animals'],
    ['name' => 'audi', 'group' => 'cars'],
    ['name' => 'ant', 'group' => 'animals'],
]);

$groups = $items->groupBy(groupBy: 'group')->all();
/*Array
(
    [animals] => Array
        (
            [0] => Array
                (
                    [name] => bear
                    [group] => animals
                )
            [2] => Array
                (
                    [name] => ant
                    [group] => animals
                )
        )
    [cars] => Array
        (
            [1] => Array
                (
                    [name] => audi
                    [group] => cars
                )
        )
)*/

// using a callable:
$groups = $items->groupBy(
    groupBy: fn ($item) => $item['group'],
);

// using a callable for grouping:
$groups = $items->groupBy(
    groupBy: 'group',
    groupAs: fn (array $group) => (object) $group,
);

// without preserving keys:
$groups = $items->groupBy(
    groupBy: 'group',
    preserveKeys: false,
);
```

**reindex**

Reindex items returning a new instance.

```
use Tobento\Service\Storage\Items;

$items = new Items([
    ['sku' => 'foo', 'name' => 'Foo'],
    ['sku' => 'bar', 'name' => 'Bar'],
]);

$itemsNew = $items->reindex(function(array $item): int|string {
    return $item['sku'];
});

var_dump(array_keys($itemsNew->all()));
// array(2) {[0]=> string(3) "foo" [1]=> string(3) "bar"}
```

**count**

Returns the number of the items.

```
use Tobento\Service\Storage\Items;

$items = new Items([
    'foo' => ['title' => 'Title'],
]);

var_dump($items->count());
// int(1)
```

**collection**

Returns a new Collection with the items.

```
use Tobento\Service\Storage\Items;
use Tobento\Service\Collection\Collection;

$items = new Items([
    'foo' => ['title' => 'Title'],
]);

var_dump($items->collection() instanceof Collection);
// bool(true)
```

Check out the [Collection](https://github.com/tobento-ch/service-collection#collection) to learn more about it.

Tables
------

[](#tables)

Tables are used by the storages for verifying table and column names for building queries.

**add**

```
use Tobento\Service\Storage\Tables\Tables;

$tables = new Tables();
$tables->add(
    table: 'products',
    columns: ['id', 'sku'],
    primaryKey: 'id' // or null if none
);
```

Credits
=======

[](#credits)

- [Tobias Strub](https://www.tobento.ch)
- [All Contributors](../../contributors)

###  Health Score

46

—

FairBetter than 92% of packages

Maintenance66

Regular maintenance activity

Popularity13

Limited adoption so far

Community16

Small or concentrated contributor base

Maturity77

Established project with proven stability

 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.

###  Release Activity

Cadence

Every ~36 days

Recently: every ~18 days

Total

36

Last Release

206d ago

Major Versions

1.x-dev → 2.02025-09-26

PHP version history (2 changes)1.0.0PHP &gt;=8.0

2.0PHP &gt;=8.4

### Community

Maintainers

![](https://www.gravatar.com/avatar/055d6a1b5c2384bb179c75ab0b55914231d898fdc4dffeb30770f81200e52206?d=identicon)[TOBENTOch](/maintainers/TOBENTOch)

---

Top Contributors

[![tobento-ch](https://avatars.githubusercontent.com/u/16684832?v=4)](https://github.com/tobento-ch "tobento-ch (153 commits)")

---

Tags

packagedatabasestoragetobento

###  Code Quality

TestsPHPUnit

Static AnalysisPsalm

Type Coverage Yes

### Embed Badge

![Health badge](/badges/tobento-service-storage/health.svg)

```
[![Health](https://phpackages.com/badges/tobento-service-storage/health.svg)](https://phpackages.com/packages/tobento-service-storage)
```

###  Alternatives

[awssat/laravel-sync-migration

Laravel tool helps to sync migrations without refreshing the database

10823.4k](/packages/awssat-laravel-sync-migration)

PHPackages © 2026

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