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
php
use ImaticBundleDataBundleDataCommandCommand;
- $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\CommandExecutorAwareInterface
to avoid circular reference exception in DI. It can also optionally useImatic\Bundle\DataBundle\Data\Command\CommandExecutorAwareTrait
trait. - 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
<?php
use ImaticBundleDataBundleDataCommandCommandInterface; use ImaticBundleDataBundleDataCommandHandlerInterface;
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); }
}
}
yaml
- services:
- CleanupObsoleteFilesHandler:
- tags:
- { name: 'imatic_data.handler' }
- An instance can be optionally returned from handler's
handle
method. - 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
success
anderror
to conveniently create successful or unsuccessful result. - In addition to parameters above, you can use method
set
to set additional data of the result (number of removed files, names of removed files, etc.). Data set usingset
are meant for some additional processing and can be retrieved by callingget
on the result object.
php
<?php
$successResult = CommandResult::success('10 obsolete recording files were removed.');
php
<?php
$errorResult = CommandResult::error('Error happened. Please contact system administrator.');
- Has 1 method
execute
which executes given command and returns result. - Contains information about executed command
- Returns command result
php
<?php
$commandExecutor = $container->get('ImaticBundleDataBundleDataCommandCommandExecutor'); $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
<?php
use ImaticBundleDataBundleDataCommandCommand; use ImaticBundleDataBundleDataDriverDoctrineDBALCommandCreateHandler;
- $createUserCommand = new Command(
CreateHandler::class, [ 'table' => 'user', 'data' => [ 'email' => 'newuser@example.com', 'user' => 'newuser', ], ]
);
$commandExecutor = $container->get('ImaticBundleDataBundleDataCommandCommandExecutor'); $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
<?php
use ImaticBundleDataBundleDataCommandCommand; use ImaticBundleDataBundleDataDriverDoctrineDBALCommandEditHandler;
- $updateUserCommand = new Command(
EditHandler::class, [ 'id' => ['id' => 1], 'table' => 'user', 'data' => [ 'email' => 'updatedemail@example.com', ], ]
);
$commandExecutor = $container->get('ImaticBundleDataBundleDataCommandCommandExecutor'); $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
username
to beuser
php
<?php
use ImaticBundleDataBundleDataCommandCommand; use ImaticBundleDataBundleDataDriverDoctrineDBALCommandCreateOrEditHandler;
- $createOrUpdateUserCommand = new Command(
CreateOrEditHandler::class, [ 'columnValues' => [ 'email' => 'user@example.com', ], 'table' => 'user', 'data' => [ 'email' => 'user@example.com', 'username' => 'user', ], ]
);
$commandExecutor = $container->get('ImaticBundleDataBundleDataCommandCommandExecutor'); $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
<?php
use ImaticBundleDataBundleDataCommandCommand; use ImaticBundleDataBundleDataDriverDoctrineDBALCommandDeleteHandler;
- $deleteUserCommand = new Command(
DeleteHandler::class, [ 'id' => ['id' => 3], 'table' => 'user', ]
);
$commandExecutor = $container->get('ImaticBundleDataBundleDataCommandCommandExecutor'); $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_at
which 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
<?php
use ImaticBundleDataBundleDataCommandCommand; use ImaticBundleDataBundleDataDriverDoctrineDBALCommandSoftDeleteHandler;
- $softDeleteUserCommand = new Command(
SoftDeleteHandler::class, [ 'id' => ['id' => 4], 'table' => 'user', ]
);
$commandExecutor = $container->get('ImaticBundleDataBundleDataCommandCommandExecutor'); $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
<?php
use ImaticBundleDataBundleDataCommandCommand; use ImaticBundleDataBundleDataDriverDoctrineORMCommandCreateHandler;
$newUser = new User(); $newUser->setEmail('new@example.com'); $newUser->setUsername('newuser');
- $createUserCommand = new Command(
CreateHandler::class, [ 'class' => User::class, 'data' => $newUser, ]
);
$commandExecutor = $container->get('ImaticBundleDataBundleDataCommandCommandExecutor'); $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
<?php
use ImaticBundleDataBundleDataCommandCommand; use ImaticBundleDataBundleDataDriverDoctrineORMCommandEditHandler;
$updatedUser = findUserById(3); $updatedUser->setUsername('updatedusername');
- $updateUserCommand = new Command(
EditHandler::class, [ 'class' => User::class, 'data' => $updatedUser, ]
);
$commandExecutor = $container->get('ImaticBundleDataBundleDataCommandCommandExecutor'); $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
data
andquery_object
parameters 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
<?php
use ImaticBundleDataBundleDataCommandCommand; use ImaticBundleDataBundleDataDriverDoctrineORMCommandDeleteHandler;
$user = findUserById(5);
- $deleteUserCommand = new Command(
DeleteHandler::class, [ 'class' => User::class, 'data' => $user, ]
);
$commandExecutor = $container->get('ImaticBundleDataBundleDataCommandCommandExecutor'); $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
$commandParameters
argument will be replaced by these).data
parameter 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.
yaml
- app.delete_inactive_users:
class: ImaticBundleDataBundleDataDriverDoctrineORMCommandBatchHandler arguments: - '@ImaticBundleDataBundleDataDriverDoctrineORMCommandRecordIterator' - '@ImaticBundleDataBundleDataDriverDoctrineORMCommandDeleteHandler' - { 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
<?php
use ImaticBundleDataBundleDataCommandCommand;
$commandExecutor = $container->get('ImaticBundleDataBundleDataCommandCommandExecutor'); $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;
}
]
));