https://github.com/tobento-ch/service-database
Creating and managing databases easily.
https://github.com/tobento-ch/service-database
Last synced: 3 months ago
JSON representation
Creating and managing databases easily.
- Host: GitHub
- URL: https://github.com/tobento-ch/service-database
- Owner: tobento-ch
- License: mit
- Created: 2021-11-28T16:19:13.000Z (over 3 years ago)
- Default Branch: 1.x
- Last Pushed: 2024-05-06T16:30:53.000Z (about 1 year ago)
- Last Synced: 2025-01-28T21:17:38.776Z (5 months ago)
- Language: PHP
- Size: 112 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Database Service
With the Database Service you can create and manage databases easily.
## Table of Contents
- [Getting started](#getting-started)
- [Requirements](#requirements)
- [Highlights](#highlights)
- [Documentation](#documentation)
- [Databases](#databases)
- [Create Databases](#create-databases)
- [Add Databases](#add-databases)
- [Get Database](#get-database)
- [Default Databases](#default-databases)
- [PDO Database](#pdo-database)
- [Create PDO Database](#create-pdo-database)
- [Pdo Database Factory](#pdo-database-factory)
- [Using PDO Database](#using-pdo-database)
- [Migration](#migration)
- [Table Schema](#table-schema)
- [Column Types](#column-types)
- [Rename And Drop](#rename-and-drop)
- [Column Parameters](#column-parameters)
- [Indexes](#indexes)
- [Foreign Keys](#foreign-keys)
- [Items and Seeding](#items-and-seeding)
- [Items](#items)
- [Item Factory](#item-factory)
- [Json File Items](#json-file-items)
- [Table Factory](#table-factory)
- [Column Factory](#column-factory)
- [Index Factory](#index-factory)
- [Processors](#processors)
- [Pdo MySql Processor](#pdo-mysql-processor)
- [Stack Processor](#stack-processor)
- [Storages](#storages)
- [Pdo MySql Storage](#pdo-mysql-storage)
- [Stack Storage](#stack-storage)
- [Custom Storage](#custom-storage)
- [Security](#security)
- [Migrator](#migrator)
- [Create Migration](#create-migration)
- [Create Migration Seeder](#create-migration-seeder)
- [Install And Uninstall Migration](#install-and-uninstall-migration)
- [Credits](#credits)
___# Getting started
Add the latest version of the Database service project running this command.
```
composer require tobento/service-database
```## Requirements
- PHP 8.0 or greater
## Highlights
- Framework-agnostic, will work with any project
- Decoupled design
- Managing Databases
- Simple PDO Database Wrapper
- Migration support with table schema builder and seeding items# Documentation
## Databases
### Create Databases
```php
use Tobento\Service\Database\Databases;
use Tobento\Service\Database\DatabasesInterface;$databases = new Databases();
var_dump($databases instanceof DatabasesInterface);
// bool(true)
```### Add Databases
**add**
```php
use Tobento\Service\Database\Databases;
use Tobento\Service\Database\PdoDatabase;
use Tobento\Service\Database\DatabaseInterface;
use PDO;$databases = new Databases();
$database = new PdoDatabase(
pdo: new PDO('sqlite::memory:'),
name: 'name',
);var_dump($database instanceof DatabaseInterface);
// bool(true)$databases->add($database);
```**register**
You may use the register method to only create database if requested.
```php
use Tobento\Service\Database\Databases;
use Tobento\Service\Database\PdoDatabase;
use Tobento\Service\Database\DatabaseInterface;
use PDO;$databases = new Databases();
$databases->register(
'name',
function(string $name): DatabaseInterface {
return new PdoDatabase(
new PDO('sqlite::memory:'),
$name
);
}
);
```### Get Database
If the database does not exist or could not get created it throws a DatabaseException.
```php
use Tobento\Service\Database\DatabaseInterface;
use Tobento\Service\Database\DatabaseException;$database = $databases->get('name');
var_dump($database instanceof DatabaseInterface);
// bool(true)$databases->get('unknown');
// throws DatabaseException
```You may use the **has** method to check if a database exists.
```php
var_dump($databases->has('name'));
// bool(false)
```### Default Databases
You may add default databases for your application design.
```php
use Tobento\Service\Database\Databases;
use Tobento\Service\Database\PdoDatabase;
use Tobento\Service\Database\DatabaseInterface;
use Tobento\Service\Database\DatabaseException;
use PDO;$databases = new Databases();
$databases->add(
new PdoDatabase(new PDO('sqlite::memory:'), 'sqlite')
);// add default
$databases->addDefault(name: 'primary', database: 'sqlite');// get default database for the specified name.
$primaryDatabase = $databases->default('primary');var_dump($primaryDatabase instanceof DatabaseInterface);
// bool(true)var_dump($databases->hasDefault('primary'));
// bool(true)var_dump($databases->getDefaults());
// array(1) { ["primary"]=> string(6) "sqlite" }$databases->default('unknown');
// throws DatabaseException
```## PDO Database
### Create PDO Database
```php
use Tobento\Service\Database\PdoDatabase;
use Tobento\Service\Database\DatabaseInterface;
use Tobento\Service\Database\PdoDatabaseInterface;
use PDO;$database = new PdoDatabase(
pdo: new PDO('sqlite::memory:'),
name: 'sqlite',
);var_dump($database instanceof DatabaseInterface);
// bool(true)var_dump($database instanceof PdoDatabaseInterface);
// bool(true)
```### Pdo Database Factory
You may use the factory to easily create a database.
**createDatabase**
```php
use Tobento\Service\Database\PdoDatabaseFactory;
use Tobento\Service\Database\DatabaseFactoryInterface;
use Tobento\Service\Database\PdoDatabaseInterface;
use Tobento\Service\Database\DatabaseInterface;
use Tobento\Service\Database\DatabaseException;
use PDO;$factory = new PdoDatabaseFactory();
var_dump($factory instanceof DatabaseFactoryInterface);
// bool(true)$database = $factory->createDatabase(
name: 'mysql',
config: [
'driver' => 'mysql',
'host' => 'localhost',
'port' => null,
'database' => 'db_name',
'charset' => 'utf8mb4',
'username' => 'root',
'password' => '',
'options' => [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false,
],
],
);
// throws DatabaseException on failurevar_dump($database instanceof PdoDatabaseInterface);
// bool(true)var_dump($database instanceof DatabaseInterface);
// bool(true)// with dsn parameter
$database = $factory->createDatabase(
name: 'sqlite',
config: [
'dsn' => 'sqlite::memory:',
'username' => '',
'password' => '',
'options' => [],
],
);
```**createPdo**
```php
use Tobento\Service\Database\PdoDatabaseFactory;
use Tobento\Service\Database\PdoFactoryInterface;
use Tobento\Service\Database\DatabaseException;
use PDO;$factory = new PdoDatabaseFactory();
var_dump($factory instanceof PdoFactoryInterface);
// bool(true)$pdo = $factory->createPdo(
name: 'sqlite',
config: [
'dsn' => 'sqlite::memory:',
'username' => '',
'password' => '',
'options' => [],
],
);
// throws DatabaseException on failurevar_dump($pdo instanceof PDO);
// bool(true)
```### Using PDO Database
Use the **execute** method to excute any prepared statements.
```php
use PDOStatement;$statement = $database->execute(
statement: 'ALTER TABLE products ADD color varchar(60)'
);var_dump($statement instanceof PDOStatement);
// bool(true)
```**select**
```php
$products = $database->execute(
statement: 'SELECT title FROM products WHERE color = ?',
bindings: ['blue']
)->fetchAll();// with named parameters, order free
$products = $database->execute(
'SELECT title FROM products WHERE color = :color',
['color' => 'blue']
)->fetchAll();
```**insert**
```php
$database->execute(
statement: 'INSERT INTO shop_products (name, color) VALUES (?, ?)',
bindings: ['Shirt', 'blue'],
);// you might return the number of rows affected:
$rowsAffected = $database->execute(
'INSERT INTO shop_products (name, color) VALUES (?, ?)',
['Shirt', 'blue']
)->rowCount();var_dump($rowsAffected);
// int(1)
```**update**
Execute a insert statement returning the number of rows affected.
```php
$rowsAffected = $database->execute(
statement: 'UPDATE products SET name = ? WHERE color = ?',
bindings: ['Shirt', 'blue']
)->rowCount();var_dump($rowsAffected);
// int(2)
```**delete**
Execute a delete statement returning the number of rows affected.
```php
$rowsAffected = $database->execute(
statement: 'DELETE FROM shop_products WHERE color = ?',
bindings: ['blue']
)->rowCount();var_dump($rowsAffected);
// int(2)
```**transaction**
You may use the transaction method to run a set of database 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.
```php
use Tobento\Service\Database\PdoDatabaseInterface;$database->transaction(function(PdoDatabaseInterface $db): void {
$db->execute(
'UPDATE products SET active = ? WHERE color = ?',
[true, 'red']
);
$db->execute(
'UPDATE products SET active = ? WHERE color = ?',
[false, 'bar']
);
});
```**commit**
```php
$database->begin();// your queries
$database->commit();
```**rollback**
```php
$database->begin();// your queries
$database->rollback();
```**supportsNestedTransactions**
```php
var_dump($database->supportsNestedTransactions());
// bool(true)
```**PDO**
```php
use PDO;var_dump($database->pdo() instanceof PDO);
// bool(true)
```## Migration
### Table Schema
Table schemas are used by [Processors](#processors) and [Storages](#storages) for migration processing.
```php
use Tobento\Service\Database\Schema\Table;$table = new Table(name: 'products');
$table->primary('id');
$table->string('name', 100)->nullable(false)->default('');
$table->bool('active', true);
```#### Column Types
**Available Types**
| Type | Parameters | Lengthable | Nullable | Defaultable | Unsignable | Description |
| --- | --- | --- | --- | --- | --- | --- |
| **primary** | name: 'column' | yes | no | no | yes | Usually mapped as int, auto-incrementing and added as primary index column. |
| **bigPrimary** | name: 'column' | yes | no | no | yes | Usually mapped as bigint, auto-incrementing and added as primary index column. |
| **bool** | name: 'column' | no | no | yes | no | Some databases will store it as tinyint (1/0). |
| **int** | name: 'column', length: 11 | yes | yes | yes | yes | - |
| **tinyInt** | name: 'column', length: 1 | yes | yes | yes | yes | - |
| **bigInt** | name: 'column', length: 20 | yes | yes | yes | yes | - |
| **char** | name: 'column', length: 255 | yes | yes | yes | no | - |
| **string** | name: 'column', length: 255 | yes | yes | yes | no | - |
| **text** | name: 'column' | no | yes | yes | no | - |
| **double** | name: 'column' | no | yes | yes | no | - |
| **float** | name: 'column' | no | yes | yes | no | - |
| **decimal** | name: 'column', precision: 10, scale:0 | no | yes | yes | no | - |
| **datetime** | name: 'column' | no | yes | yes | no | - |
| **date** | name: 'column' | no | yes | yes | no | - |
| **time** | name: 'column' | no | yes | yes | no | - |
| **timestamp** | name: 'column' | no | yes | yes | no | - |
| **json** | name: 'column' | no | yes | yes | no | - |**Lengthable**
To set a column length.
```php
$table->string('name')->length(21);
```**Nullable**
To set column as NOT NULL, use nullable method with false as parameter:
```php
$table->string('name')->nullable(false);
```**Defaultable**
To set a default value for the column.
```php
$table->bool('name')->default(true);
```**Unsignable**
To set column as UNSIGNED.
```php
$table->int('name')->unsigned(true);
```**primary / bigPrimary**
Primary and bigPrimary columns will only be set while creation.
#### Rename and Drop
**renameColumn**
```php
$table->renameColumn('column', 'new_column');
```**dropColumn**
```php
$table->dropColumn('column');
```**renameTable**
```php
$table->renameTable('new_name');
```**dropTable**
```php
$table->dropTable();
```**truncate**
```php
$table->truncate();
```#### Column Parameters
**charset**
You might set the charset of the column.
```php
$table->string('column')->parameter('charset', 'utf8mb4');
```**collation**
You might set the collation of the column.
```php
$table->string('column')->parameter('collation', 'utf8mb4_roman_ci');
```#### Indexes
**Simple index**
```php
$table->index('index_name')->column('name');
```**Compound index**
```php
$table->index('index_name')->column('name', 'another_name');
```**Simple unique index**
```php
$table->index('index_name')->column('name')->unique();
```**Compound unique index**
```php
$table->index('index_name')->column('name', 'another_name')->unique();
```**Primary index**
```php
$table->index()->column('name')->primary();
```**Rename index**
```php
$table->index('index_name')->rename('new_name');
```**Drop index**
```php
$table->index('index_name')->drop();
```#### Foreign Keys
No supported yet!
#### Items and Seeding
##### Items
```php
use Tobento\Service\Database\Schema\ItemsInterface;$items = $table->items(iterable: [
['name' => 'Foo', 'active' => true],
['name' => 'Bar', 'active' => true],
// ...
])
->chunk(length: 100)
->useTransaction(false) // default is true
->forceInsert(true); // default is falsevar_dump($items instanceof ItemsInterface);
// bool(true)
```**chunk**
You may play around with the chunk **length** parameter for speed improvements while having many items.
**useTransaction**
If set to **true**, it uses transaction while proccessing if the database supports it.
**forceInsert**
If set to **true**, it will always inserts the items, otherwise they will only be inserted if there there are not items yet.
##### 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.
```php
use Tobento\Service\Iterable\ItemFactoryIterator;
use Tobento\Service\Seeder\Str;
use Tobento\Service\Seeder\Arr;$table->items(new ItemFactoryIterator(
factory: function(): array {
return [
'name' => Str::string(10),
'color' => Arr::item(['green', 'red', 'blue']),
];
},
create: 1000000 // create 1 million items
))
->chunk(length: 10000)
->useTransaction(false) // default is true
->forceInsert(true); // default is false
```##### Json File Items
```php
use Tobento\Service\Iterable\JsonFileIterator;
use Tobento\Service\Iterable\ModifyIterator;$iterator = new JsonFileIterator(
file: 'private/src/countries.json',
);// you may use the modify iterator:
$iterator = new ModifyIterator(
iterable: $iterator,
modifier: function(array $item): array {
return [
'iso' => $item['iso'] ?? '',
'name' => $item['country'] ?? '',
];
}
);
$table->items($iterator)
->chunk(length: 100)
->useTransaction(true) // default is true
->forceInsert(false); // default is false
```### Table Factory
You may use the table factory to create a table.
```php
use Tobento\Service\Database\Schema\TableFactoryInterface;
use Tobento\Service\Database\Schema\TableFactory;
use Tobento\Service\Database\Schema\Table;$tableFactory = new TableFactory();
var_dump($tableFactory instanceof TableFactoryInterface);
// bool(true)$table = $tableFactory->createTable(name: 'users');
var_dump($table instanceof Table);
// bool(true)
```### Column Factory
You may use the column factory to create a column.
```php
use Tobento\Service\Database\Schema\ColumnFactoryInterface;
use Tobento\Service\Database\Schema\ColumnFactory;$columnFactory = new ColumnFactory();
var_dump($columnFactory instanceof ColumnFactoryInterface);
// bool(true)
```**createColumn**
```php
use Tobento\Service\Database\Schema\ColumnFactory;
use Tobento\Service\Database\Schema\ColumnInterface;
use Tobento\Service\Database\Schema\CreateColumnException;try {
$column = (new ColumnFactory())->createColumn(type: 'int', name: 'foo');
var_dump($column instanceof ColumnInterface);
// bool(true)
} catch(CreateColumnException $e) {
//
}
```Check out the supported [Column Types](#column-types) for its type name.
**createColumnFromArray**
```php
use Tobento\Service\Database\Schema\ColumnFactory;
use Tobento\Service\Database\Schema\ColumnInterface;
use Tobento\Service\Database\Schema\CreateColumnException;try {
$column = (new ColumnFactory())->createColumnFromArray([
'type' => 'int',
'name' => 'foo',
]);
var_dump($column instanceof ColumnInterface);
// bool(true)
} catch(CreateColumnException $e) {
//
}
```Lengthable, Nullable, Defaultable, Unsignable and Parameters column definitions:
```php
use Tobento\Service\Database\Schema\ColumnFactory;$column = (new ColumnFactory())->createColumnFromArray([
'type' => 'int',
'name' => 'foo',
'length' => 99,
'nullable' => false,
'default' => 'value',
'unsigned' => true,
'parameters' => [
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_roman_ci',
],
// Decimal column
'precision' => 8,
'scale' => 4,
]);
```### Index Factory
```php
use Tobento\Service\Database\Schema\IndexFactoryInterface;
use Tobento\Service\Database\Schema\IndexFactory;$indexFactory = new IndexFactory();
var_dump($indexFactory instanceof IndexFactoryInterface);
// bool(true)
```**createIndex**
```php
use Tobento\Service\Database\Schema\IndexFactory;
use Tobento\Service\Database\Schema\IndexInterface;
use Tobento\Service\Database\Schema\CreateIndexException;try {
$index = (new IndexFactory())->createIndex(name: 'foo');
var_dump($index instanceof IndexInterface);
// bool(true)
} catch(CreateIndexException $e) {
//
}
```**createIndexFromArray**
```php
use Tobento\Service\Database\Schema\IndexFactory;
use Tobento\Service\Database\Schema\IndexInterface;
use Tobento\Service\Database\Schema\CreateIndexException;try {
$index = (new IndexFactory())->createIndexFromArray([
'name' => 'foo',
]);
var_dump($index instanceof IndexInterface);
// bool(true)
} catch(CreateIndexException $e) {
//
}
```Other parameter definitions:
```php
use Tobento\Service\Database\Schema\IndexFactory;$index = (new IndexFactory())->createIndexFromArray([
'name' => 'foo',
'column' => 'name',
// or multiple
'column' => ['name', 'another_name'],
'unique' => true,
'primary' => true,
'rename' => 'newname',
'drop' => true,
]);
```### Processors
Processors are used to process the table on the specified database.
#### Pdo MySql Processor
The proccessor will automatically determine if to add or modify table columns and indexes.
```php
use Tobento\Service\Database\Processor\PdoMySqlProcessor;
use Tobento\Service\Database\Processor\ProcessorInterface;
use Tobento\Service\Database\Processor\ProcessException;
use Tobento\Service\Database\PdoDatabaseInterface;
use Tobento\Service\Database\Schema\Table;$processor = new PdoMySqlProcessor();
var_dump($processor instanceof ProcessorInterface);
// bool(true)try {
$processor->process(
$table, // Table
$database // PdoDatabaseInterface
);
} catch (ProcessException $e) {
// Handle exception.
}
```You may create a [Custom Storage](#custom-storage) for the proccssor. The default storage [Pdo MySql Storage](#pdo-mysql-storage) will query the database to create the current table as to determine modifications.
```php
use Tobento\Service\Database\Processor\PdoMySqlProcessor;$processor = new PdoMySqlProcessor(new CustomStorage());
```#### Stack Processor
You may use the "stack processor" to support multiple databases. Only the first processor which supports the specified database will process the action.
```php
use Tobento\Service\Database\Processor\Processors;
use Tobento\Service\Database\Processor\PdoMySqlProcessor;
use Tobento\Service\Database\Processor\ProcessorInterface;
use Tobento\Service\Database\Processor\ProcessException;$processors = new Processors(
new PdoMySqlProcessor(),
);var_dump($processor instanceof ProcessorInterface);
// bool(true)try {
$processors->process($table, $database);
} catch (ProcessException $e) {
//
}
```### Storages
Storages are used to fetch the current table or store the processed.
#### Pdo MySql Storage
**fetchTable**
The storage will query the database to create the current table.
```php
use Tobento\Service\Database\Processor\PdoMySqlStorage;
use Tobento\Service\Database\Processor\StorageInterface;
use Tobento\Service\Database\Processor\StorageFetchException;
use Tobento\Service\Database\PdoDatabaseInterface;
use Tobento\Service\Database\Schema\Table;$storage = new PdoMySqlStorage();
var_dump($storage instanceof StorageInterface);
// bool(true)try {
$table = $storage->fetchTable(
$database, // PdoDatabaseInterface
'table_name'
);
var_dump($table instanceof Table);
// bool(true) or NULL if table does not exist.} catch (StorageFetchException $e) {
// Handle exception.
}
```**storeTable**
No table data is stored as fetching will create the table.
```php
use Tobento\Service\Database\Processor\PdoMySqlStorage;
use Tobento\Service\Database\Processor\StorageInterface;
use Tobento\Service\Database\Processor\StorageStoreException;
use Tobento\Service\Database\PdoDatabaseInterface;
use Tobento\Service\Database\Schema\Table;$storage = new PdoMySqlStorage();
var_dump($storage instanceof StorageInterface);
// bool(true)try {
$storage->storeTable(
$database, // PdoDatabaseInterface
$table // Table
);} catch (StorageStoreException $e) {
// Handle exception.
}
```#### Stack Storage
You may use the "stack storage" to support multiple databases. Only the first storage which supports the specified database will process the action.
```php
use Tobento\Service\Database\Processor\Storages;
use Tobento\Service\Database\Processor\PdoMySqlStorage;
use Tobento\Service\Database\Processor\StorageInterface;
use Tobento\Service\Database\Processor\StorageStoreException;$storages = new Storages(
new PdoMySqlStorage(),
);var_dump($storages instanceof StorageInterface);
// bool(true)try {
$storages->storeTable($database, $table);
} catch (StorageStoreException $e) {
// Handle exception.
}
```#### Custom Storage
You may create custom storages for proccssors or as standalone usage.
```php
use Tobento\Service\Database\Processor\PdoMySqlProcessor;
use Tobento\Service\Database\Processor\StorageInterface;
use Tobento\Service\Database\Processor\StorageFetchException;
use Tobento\Service\Database\Processor\StorageStoreException;
use Tobento\Service\Database\Processor\ProcessException;
use Tobento\Service\Database\Schema\Table;
use Tobento\Service\Database\DatabaseInterface;class CustomStorage implements StorageInterface
{
/**
* Returns true if the processor supports the database, otherwise false.
*
* @param DatabaseInterface $database
* @return bool
*/
public function supportsDatabase(DatabaseInterface $database): bool
{
return true;
}
/**
* Returns the specified table if exist, otherwise null.
*
* @param DatabaseInterface $database
* @param string $name The table name
* @return null|Table
* @throws StorageFetchException
*/
public function fetchTable(DatabaseInterface $database, string $table): null|Table
{
// your logic.
return null;
}
/**
* Store the table.
*
* @param DatabaseInterface $database
* @param string $name
* @return void
* @throws StorageStoreException
*/
public function storeTable(DatabaseInterface $database, Table $table): void
{
// your logic.
}
}try {
$table = (new CustomStorage())->fetchTable($database, 'table_name');
} catch (ProcessException $e) {
// Handle exception.
}
```
### Security> :warning: **Avoid using user provided data for creating [Table Schema](#table-schema) without a proper whitelist!**
### Migrator
You might install and use the [Migration Service](https://github.com/tobento-ch/service-migration) for migration processing.
#### Create Migration
Create a migration class by extending the ```DatabaseMigration::class```.
**Using the ```registerTables``` method**
You may use the ```registerTables``` method to register the table for the install and uninstall process.
```php
use Tobento\Service\Database\Migration\DatabaseMigration;
use Tobento\Service\Database\Schema\Table;class DbMigrations extends DatabaseMigration
{
public function description(): string
{
return 'db migrations';
}/**
* Register tables used by the install and uninstall methods
* to create the actions from.
*
* @return void
*/
protected function registerTables(): void
{
$this->registerTable(
table: function(): Table {
$table = new Table(name: 'users');
$table->primary('id');
return $table;
},
database: $this->databases->default('pdo'),
name: 'Users',
description: 'Users desc',
);
$this->registerTable(
table: function(): Table {
$table = new Table(name: 'products');
$table->primary('id');
return $table;
},
database: $this->databases->default('pdo'),
);
}
}
```Check out the [Table Schema](#table-schema) for its documentation.
**Using the ```install``` and ```uninstall``` methods**
You may use the ```install``` and ```uninstall``` methods for specifing the actions by your own.
```php
use Tobento\Service\Database\Migration\DatabaseMigration;
use Tobento\Service\Database\Migration\DatabaseAction;
use Tobento\Service\Database\Migration\DatabaseDeleteAction;
use Tobento\Service\Database\Schema\Table;
use Tobento\Service\Migration\ActionsInterface;
use Tobento\Service\Migration\Actions;class DbMigrations extends DatabaseMigration
{
public function description(): string
{
return 'db migrations';
}/**
* Return the actions to be processed on install.
*
* @return ActionsInterface
*/
public function install(): ActionsInterface
{
return new Actions(
new DatabaseAction(
processor: $this->processor,
database: $this->databases->default('pdo'),
table: function(): Table {
$table = new Table(name: 'products');
$table->primary('id');
return $table;
},
name: 'Products',
description: 'Products table installed',
),
);
}
/**
* Return the actions to be processed on uninstall.
*
* @return ActionsInterface
*/
public function uninstall(): ActionsInterface
{
return $this->createDatabaseDeleteActionsFromInstall();
// or manually:
return new Actions(
new DatabaseDeleteAction(
processor: $this->processor,
database: $this->databases->default('pdo'),
table: new Table(name: 'products'),
name: 'Products',
description: 'Products table uninstalled',
),
);
}
}
```Check out the [Table Schema](#table-schema) for its documentation.
#### Create Migration Seeder
First, you will need to install the [Seeder Service](https://github.com/tobento-ch/service-seeder) and bind the ```SeedInterface::class``` implementation to your container in order to get injected on the ```DatabaseMigrationSeeder::class```.
Next, create a migration seeder class by extending the ```DatabaseMigrationSeeder::class```.
Then use the ```registerTables``` method to register the table for the install process.
```php
use Tobento\Service\Database\Migration\DatabaseMigrationSeeder;
use Tobento\Service\Database\Schema\Table;
use Tobento\Service\Iterable\ItemFactoryIterator;class DbMigrationsSeeder extends DatabaseMigrationSeeder
{
public function description(): string
{
return 'db migrations seeding';
}/**
* Register tables used by the install method
* to create the actions from.
* The uninstall method returns empty actions.
*
* @return void
*/
protected function registerTables(): void
{
$this->registerTable(
table: function(): Table {
$table = new Table(name: 'users');
// no need to specifiy columns again
// if you the table migrated before.
// seeding:
$table->items(new ItemFactoryIterator(
factory: function(): array {
return [
'name' => $this->seed->fullname(),
'email' => $this->seed->email(),
];
},
create: 10000
))
->chunk(length: 2000)
->useTransaction(false) // default is true
->forceInsert(true); // default is false
return $table;
},
database: $this->databases->default('pdo'),
);
}
}
```Check out the [Seeder Service](https://github.com/tobento-ch/service-seeder) for its documentation.
Check out the [Table Schema](#table-schema) for its documentation.
#### Install And Uninstall Migration
```php
$result = $migrator->install(DbMigrations::class);$result = $migrator->uninstall(DbMigrations::class);
```Check out the following migration service documentation to learn more about it.
* [Create Migrator](https://github.com/tobento-ch/service-migration#create-migrator)
* [Install Migration](https://github.com/tobento-ch/service-migration#install-migration)
* [Uninstall Migration](https://github.com/tobento-ch/service-migration#uninstall-migration)# Credits
- [Tobias Strub](https://www.tobento.ch)
- [All Contributors](../../contributors)