Commands use 3 main interfaces
- Imatic\Bundle\DataBundle\Data\Command\CommandInterface
- used to describe arbitrary operation
- default implementation is Command
- Imatic\Bundle\DataBundle\Data\Command\CommandExecutorInterface
- used to execute commands
- default implementation is CommandExecutor
- Imatic\Bundle\DataBundle\Data\Command\HandlerInterface
- used to handle commands (do the work)
- accepts 2 arguments
$handlerName- ID of the command handler service$parameters- parameters used by command handler
Command is passed to the command executor which executes command handler based
on $handlerName argument
use Imatic\Bundle\DataBundle\Data\Command\Command;
$removeObsoleteRecordingsCommand = new Command(
'CleanupObsoleteFilesHandler',
[
'fileType' => 'recordings',
'olderThan' => new \DateTime('-1 month'),
]
);- Has 1 method
handle, which accepts command, processes it and returns a result. - Needs to be registered in container in order to be called by command executor
- service needs to be tagged with tag
imatic_data.handler(done automatically when autoconfiguration is enabled) - handler is then available under its service id.
- service needs to be tagged with tag
- In case handler needs a command executor to be able to execute other commands,
it can implement
Imatic\Bundle\DataBundle\Data\Command\CommandExecutorAwareInterfaceto avoid circular reference exception in DI. It can also optionally useImatic\Bundle\DataBundle\Data\Command\CommandExecutorAwareTraittrait. - Result can be one of
void- command was handled successfullyboolean- if
true- command was handled successfully - if
false- there was error during processing of the command
- if
Imatic\Bundle\DataBundle\Data\Command\CommandResultInterface- See it's default implementation CommandResult for more details.
<?php
use Imatic\Bundle\DataBundle\Data\Command\CommandInterface;
use Imatic\Bundle\DataBundle\Data\Command\HandlerInterface;
CleanupObsoleteFilesHandler implements HandlerInterface
{
public function handle(CommandInterface $command)
{
$fileType = $command->getParameter('fileType');
$olderThan = $command->getParameter('olderThan');
$oldRecordingFiles = findFilesByTypeOlderThan($fileType, $olderThan);
foreach ($oldRecordingFiles as $file) {
removeFile($file);
}
}
}services:
CleanupObsoleteFilesHandler:
tags:
- { name: 'imatic_data.handler' }- An instance can be optionally returned from handler's
handlemethod. - accepts 3 arguments
$success- boolean if handler processed command successfully$messages- array of messages (messages can be shown to user, logged somewhere...)Exception $exception- exception thrown when executing handler
- Implements 2 static factory methods
successanderrorto conveniently create successful or unsuccessful result. - In addition to parameters above, you can use method
setto set additional data of the result (number of removed files, names of removed files, etc.). Data set usingsetare meant for some additional processing and can be retrieved by callinggeton the result object.
<?php
$successResult = CommandResult::success('10 obsolete recording files were removed.');<?php
$errorResult = CommandResult::error('Error happened. Please contact system administrator.');- Has 1 method
executewhich executes given command and returns result. - Contains information about executed command
- Returns command result
<?php
$commandExecutor = $container->get('Imatic\Bundle\DataBundle\Data\Command\CommandExecutor');
$result = $commandExecutor->execute($removeObsoleteRecordingsCommand);This bundle comes with several preimplemented handlers so that you don't have to implement command handlers for common operations.
- Used to create new rows in db table.
- Handler assumes that name of the column containing the key is
id(if not explicitly passed, it's auto generated). - Parameters:
table- name of the table we want to insert data intodata- data we want to insert into table. It's associative array where keys are column names and values are the actual data for the columns.
- Result:
result- contains id of the record
<?php
use Imatic\Bundle\DataBundle\Data\Command\Command;
use Imatic\Bundle\DataBundle\Data\Driver\DoctrineDBAL\Command\CreateHandler;
$createUserCommand = new Command(
CreateHandler::class,
[
'table' => 'user',
'data' => [
'email' => 'newuser@example.com',
'user' => 'newuser',
],
]
);
$commandExecutor = $container->get('Imatic\Bundle\DataBundle\Data\Command\CommandExecutor');
$result = $commandExecutor->execute($createUserCommand);
if ($result->isSuccessful()) {
echo sprintf('Id of the inserted user: %d', $result->get('result'));
} else {
echo 'Error happened during executing the command.';
}- Used to update existing rows in db table.
- Parameters:
id- id of the row we want to update. It's associative array where keys are column names and values are their values.table- name of the table we want to update data indata- data we want to update in table. It's associative array where keys are column names and values are the actual data for the columns.
- Result:
- this handler doesn't return any result
<?php
use Imatic\Bundle\DataBundle\Data\Command\Command;
use Imatic\Bundle\DataBundle\Data\Driver\DoctrineDBAL\Command\EditHandler;
$updateUserCommand = new Command(
EditHandler::class,
[
'id' => ['id' => 1],
'table' => 'user',
'data' => [
'email' => 'updatedemail@example.com',
],
]
);
$commandExecutor = $container->get('Imatic\Bundle\DataBundle\Data\Command\CommandExecutor');
$result = $commandExecutor->execute($updateUserCommand);
if ($result->isSuccessful()) {
echo 'Email was successfully updated';
} else {
echo 'Error happened during updating of the email';
}- Used to create new row in case one doesn't already exist (based on specified criteria) or edit existing one.
- Handler assumes that name of the column with primary key is
id. - Parameters:
columnValues- columns used to search existing recordtable- table to search/update/insert records intodata- data to update in the new or existing row
- Result:
- based on if data were created or updated, result is same as the one for generic create and update handlers
- In the end we want to have user in our database with following columns
email- user@example.comusername- user
- In case, user with given email doesn't exist, we want to create him
- In case, user with given email does exist, we want his
usernameto beuser
<?php
use Imatic\Bundle\DataBundle\Data\Command\Command;
use Imatic\Bundle\DataBundle\Data\Driver\DoctrineDBAL\Command\CreateOrEditHandler;
$createOrUpdateUserCommand = new Command(
CreateOrEditHandler::class,
[
'columnValues' => [
'email' => 'user@example.com',
],
'table' => 'user',
'data' => [
'email' => 'user@example.com',
'username' => 'user',
],
]
);
$commandExecutor = $container->get('Imatic\Bundle\DataBundle\Data\Command\CommandExecutor');
$result = $commandExecutor->execute($createOrUpdateUserCommand);
if ($result->isSuccessful()) {
echo 'User was successfully updated';
} else {
echo 'Error happened during updating of the user';
}- Used to delete row from db
- Parameters:
id- id of the row we want to delete. It's associative array where keys are column names and values are their values.table- name of the table we want to delete the row in
- Result:
- this handler doesn't return any result
<?php
use Imatic\Bundle\DataBundle\Data\Command\Command;
use Imatic\Bundle\DataBundle\Data\Driver\DoctrineDBAL\Command\DeleteHandler;
$deleteUserCommand = new Command(
DeleteHandler::class,
[
'id' => ['id' => 3],
'table' => 'user',
]
);
$commandExecutor = $container->get('Imatic\Bundle\DataBundle\Data\Command\CommandExecutor');
$result = $commandExecutor->execute($deleteUserCommand);
if ($result->isSuccessful()) {
echo 'User was successfully deleted';
} else {
echo 'Error happened during deleting of the user';
}- Used to mark row in table as deleted.
- Handler assumes that:
- column in which primary key is stored is named
id - table has column
deleted_atwhich stores time at which row was marked as deleted
- column in which primary key is stored is named
- Parameters:
id- id of the row we want to mark as deletedtable- table the row is in
- Result:
- this handler doesn't return any result
<?php
use Imatic\Bundle\DataBundle\Data\Command\Command;
use Imatic\Bundle\DataBundle\Data\Driver\DoctrineDBAL\Command\SoftDeleteHandler;
$softDeleteUserCommand = new Command(
SoftDeleteHandler::class,
[
'id' => ['id' => 4],
'table' => 'user',
]
);
$commandExecutor = $container->get('Imatic\Bundle\DataBundle\Data\Command\CommandExecutor');
$result = $commandExecutor->execute($softDeleteUserCommand);
if ($result->isSuccessful()) {
echo 'User was successfully deleted';
} else {
echo 'Error happened during deleting of the user';
}- Used to store new object in db.
- Parameters:
class- class of the object we want to store into dbdata- object of the class we want to store into db
- Result:
- this handler doesn't return any result
<?php
use Imatic\Bundle\DataBundle\Data\Command\Command;
use Imatic\Bundle\DataBundle\Data\Driver\DoctrineORM\Command\CreateHandler;
$newUser = new User();
$newUser->setEmail('new@example.com');
$newUser->setUsername('newuser');
$createUserCommand = new Command(
CreateHandler::class,
[
'class' => User::class,
'data' => $newUser,
]
);
$commandExecutor = $container->get('Imatic\Bundle\DataBundle\Data\Command\CommandExecutor');
$result = $commandExecutor->execute($createUserCommand);
if ($result->isSuccessful()) {
echo 'User was successfully created';
} else {
echo 'Error happened during creating of the user';
}- Used to update db with edited data.
- Parameters:
class- class of the object we want to store into dbdata- object of the class we want to store into db
- Result:
- this handler doesn't return any result
<?php
use Imatic\Bundle\DataBundle\Data\Command\Command;
use Imatic\Bundle\DataBundle\Data\Driver\DoctrineORM\Command\EditHandler;
$updatedUser = findUserById(3);
$updatedUser->setUsername('updatedusername');
$updateUserCommand = new Command(
EditHandler::class,
[
'class' => User::class,
'data' => $updatedUser,
]
);
$commandExecutor = $container->get('Imatic\Bundle\DataBundle\Data\Command\CommandExecutor');
$result = $commandExecutor->execute($updateUserCommand);
if ($result->isSuccessful()) {
echo 'User was successfully updated';
} else {
echo 'Error happened during updating of the user';
}- Used to delete existing object from db.
- At least one of
dataandquery_objectparameters have to be specified. - Parameters:
class- class of the object we want to store into dbdata- object of the class we want to remove from dbquery_object- query object returning the object of the class
- Result:
- this handler doesn't return any result
<?php
use Imatic\Bundle\DataBundle\Data\Command\Command;
use Imatic\Bundle\DataBundle\Data\Driver\DoctrineORM\Command\DeleteHandler;
$user = findUserById(5);
$deleteUserCommand = new Command(
DeleteHandler::class,
[
'class' => User::class,
'data' => $user,
]
);
$commandExecutor = $container->get('Imatic\Bundle\DataBundle\Data\Command\CommandExecutor');
$result = $commandExecutor->execute($deleteUserCommand);
if ($result->isSuccessful()) {
echo 'User was successfully deleted';
} else {
echo 'Error happened during deleting of the user';
}- Used to execute given command for each object returned by executing query builder.
- Arguments:
RecordIterator- service:
Imatic\Bundle\DataBundle\Data\Driver\DoctrineORM\Command\RecordIterator(used to iterate through records with use of pagination)
- service:
$commandName- ID of the command handler service to execute for each record
$commandParameters- parameters for the command
- Parameters:
batch_query- query object which will be executed by the handler. Results will be passed into the command one by one.
batch_command_parameters(optional)- additional parameters for the command (parameters specified already in
$commandParametersargument will be replaced by these).dataparameter containing current object is first added to the list of parameters.
- additional parameters for the command (parameters specified already in
batch_command_parameters_callback(optional)- callback taking current parameters as argument and returning final array of parameters passed to the command
- We already have command for deleting objects
DeleteHandler. That command removes only single object though.
First we register BatchHandler which will execute DeleteHandler command for each object returned by a query
object.
app.delete_inactive_users:
class: Imatic\Bundle\DataBundle\Data\Driver\DoctrineORM\Command\BatchHandler
arguments:
- '@Imatic\Bundle\DataBundle\Data\Driver\DoctrineORM\Command\RecordIterator'
- '@Imatic\Bundle\DataBundle\Data\Driver\DoctrineORM\Command\DeleteHandler'
- { class: User }
tags:
- { name: 'imatic.data_handler' }Then we can execute the command. As batch command passes the user object to the child command in data parameter,
but our delete handler expects the user object in object parameter, we have to convert parameters using
batch_command_parameters_callback.
<?php
use Imatic\Bundle\DataBundle\Data\Command\Command;
$commandExecutor = $container->get('Imatic\Bundle\DataBundle\Data\Command\CommandExecutor');
$commandExecutor->execute(new Command(
'app.delete_inactive_users',
[
'batch_query' => new InactiveUsersQuery(),
'batch_command_parameters_callback' => function (array $commandParameters) {
$commandParameters['object'] = $commandParameters['data'];
return $commandParameters;
}
]
));