Встановлення за допомогою composer.
composer require rollun-com/rollun-datastore
Щоб почати користуватись бібліотекою, потрібно підключити наступні ConfigProvider
в файл конфігурації для
ServiceManager:
rollun\datastore\ConfigProvider
rollun\uploader\ConfigProvider
Також можна створити файл конфігурації (наприклад db.global.php
) в config\autoload
Приклад конфігурації для DB підключення (інші типи підключення описано нижче):
use Laminas\Db\Adapter\AdapterInterface;
return [
'dependencies' => [
'aliases' => [
'db' => AdapterInterface::class,
],
],
'dataStore' => [
// Назва сервісу
'dataStore' => [
'class' => \rollun\datastore\DataStore\DbTable::class,
'tableName' => 'orders',
'dbAdapter' => 'db', // service name, optional
'sqlQueryBuilder' => 'sqlQueryBuilder' // service name, optional
],
],
'db' => [
'driver' => getenv('DB_DRIVER') ?: 'Pdo_Mysql',
'database' => getenv('DB_NAME'),
'username' => getenv('DB_USER'),
'password' => getenv('DB_PASS'),
'hostname' => getenv('DB_HOST'),
'port' => getenv('DB_PORT') ?: 3306,
],
];
Згідно з прикладом вище, доступ до rollun\datastore\DataStore\DbTable
можна отримати за допомогою $container->get('dataStore');
Чтобы запустить тесты нужно:
- установить обязательные переменные указанные в
.env.dist
, установить файлы конфигурации (rollun\datastore\AssetInstaller
) для тестового окружения и подключитьConfigProvider
в конфигурационный файл. - Изменить название файла конфига в дирректории autoload.
composer lib install
и запустить встроенный php
сервер
php -S localhost:9000 -t public public/test.php
rollun-datastore
- это библиотека, которая предоставляет единый интерфейс взаимодействие с любым хранилищем данных
на основе Resource Query Language (RQL).
Существующие реализации:
- DbTable (для таблицы бд)
- CsvBase (для csv файлов)
- HttpClient (для внешнего ресурса через http)
- Memory (для RAM).
Интерфейс DataStoresInterface
определяет следующие основные методы для работы с абстрактным хранилищем
(Так же DataStoresInterface
интерфейс расширяет интерфейсы IteratorAggregate
и Countable
):
getIdentifier()
- возвращает имя поля, которое служитidentifier
(идентификатором) уникальной записи (по умолчанию этоid
);create($itemData, $rewriteIfExist = false)
- создает новую запись (еслиidentifier
, будет выброшен exception), возвращает созданную запись. Если запись существует и указан$rewriteIfExist = true
, запись будет пересоздана, в противном случае будет выброшено исключение. Возвращает созданную запись;update($itemData)
- обновляет существующею запись (если такая запись не существует или не указанidentifier
, будет выброшен exception), возвращает обновленную запись;delete($id)
- удаляет запись поidentifier
, возвращает удаленную запись;deleteAll()
- удаляет все запись, список идентификаторов удаленных записей;has($id)
- проверяет существует ли запись в хранилище, возвращаетtrue
/false
;read($id)
- возвращает запись поidentifier
;query(Query $query)
- возвращает массив записей которые совпадают, указаному в$query
, RQL выражении.
При переходе на версию rollun/rollun-datastore 6
интерфейс хранилище измениться на DataStoreInterface
(Вам не показалось, интерфейс имеет тоже название только без s
окончания). Метод deleteAll
будет удален и будут
добавлено несколько новых методов (Все выше перечисленные методы уже реализованы в DataStoreAbstract
и DbTable
):
multiCreate($records)
- создает несколько новых записей (если запись уже существует она не будет создаваться). Возвращает список идентификаторов успешно созданных записей;multiUpdate($records)
- обновляет несколько существующих записей (если запись не существует она не будет обновляться). Возвращает список идентификаторов успешно обновленных записей;rewrite($record)
- перезаписывает запись (создает запись, если она не существует или удаляет и создает запись если не существует). Возвращает перезаписанную запись;multiRewrite($records)
- перезаписывает несколько существующих записей. Возвращает список идентификаторов успешно обновленных записей;queriedUpdate($record, $query Query)
- обновляет записи в соответствии с RQL запросом. Возвращает список идентификаторов обновленных записей;queriedDelete($query Query)
- удаляет записи в соответствии с RQL запросом. Возвращает список идентификаторов удаленных записей.
Так же в новом интерфейсе скорее всего появиться (но еще не утвержден) новый метод getNext($id)
,
который возвращает следующую запись после записи с идентификатором $id
. Если передать $id = null
будет возвращена
первая запись, а если будет возвращен null
значит запись с $id
- последняя. Если запись с $id
не найдено будет
выброшено исключение.
Как уже было подмечено, для точной идентификации записи в хранилище используется identifier
. Предполагается что
идентификатор не автоинкрементный, по этому вызов метода create
и update
без указание идентификатора выбросит
exception (или в случае старых версии приведет к ошибке уровня E_USER_DEPRECATED
).
Реализации DataStoresInterface
, которые предоставляет библиотека:
DbTable
- для таблиц баз данных (по скольку зависимостьTableGateway
предоставляется zendframework/zend-db, то есть возможность использовать MySQL, PostgreSQL,Oracle, IBM DB2, Microsoft Sql Server, PDO и тд.);SerializedDbTable
- тот жеDbTable
, только умеющий сериализоваться;CsvBase
- для CSV файлов;HttpClient
- для внешних ресурсов черезhttp
(разумеется если этот ресурс умеет обрабатывать соответственные обращения);Memory
- хранилище в оперативной памяти;Cacheable
- декоратор вокругDataStoresInterface
, который представляет возможность кэширования данных.
Для того чтобы начать использовать DbTable хранилище нужен Zend\Db\TableGateway\TableGateway.
Пример:
<?php
use Zend\Db\Adapter\Adapter;
use Zend\Db\TableGateway\TableGateway;
use rollun\datastore\DataStore\DbTable;
$dbConfig = [
'driver' => 'Mysqli',
'database' => 'zend_db_example',
'username' => 'developer',
'password' => 'developer-password',
];
$adapter = new Adapter($dbConfig);
$tableGateway = new TableGateway('someTable', $adapter);
$dbTable = new DbTable($tableGateway);
$dbTable->create([
'id' => 1,
'name' => 'foo'
]);
var_dump($dbTable->read(1)); // ['id' => '1', 'name' => 'foo']
Для работы з CsvBase нужно указать путь к существующему файлу (или имя файла, который находиться в временной системной папке) и разделитель.
Пример:
<?php
use rollun\datastore\DataStore\CsvBase;
error_reporting(E_ALL ^ E_USER_DEPRECATED ^ E_DEPRECATED);
chdir(dirname(__DIR__));
require 'vendor/autoload.php';
$filename = tempnam(sys_get_temp_dir(), 'csv');
// Add header row
$file = fopen($filename, 'w');
fputcsv($file, ['id', 'name']);
fclose($file);
// Create datastore
$csvBase = new CsvBase($filename, ',');
// Create record
$csvBase->create([
'id' => '1',
'value' => 'name'
]);
var_dump($csvBase->read(1)); // ['id' => '1', 'name' => 'foo']
Для работы с HttpClient нужен Zend\Http\Client и URL.
<?php
use rollun\datastore\DataStore\HttpClient;
use Zend\Http\Client;
$client = new Client();
$url = 'http://example.com';
$httpClient = new HttpClient($client, $url);
$httpClient->multiCreate(
[
['id' => 1, 'name' => 'name 1'],
['id' => 2, 'name' => 'name 2']
]
);
var_dump($httpClient->read(1)); // ['id' => '1', 'name' => 'name 1']
Для работы с Memory нужно указать поля (если поля не будут указаны то будет выброшена ошибка уровня
E_USER_DEPRECATED
).
<?php
use rollun\datastore\DataStore\Memory;
$memory = new Memory(['id', 'name']);
$memory->create([
'id' => 1,
'name' => 'foo'
]);
var_dump($memory->read(1)); // ['id' => '1', 'name' => 'foo']
Cacheable
используется для того чтобы можно было хранить данные в кеше для более быстрого доступа и обновлять его.
Для этого Cacheable
нужно источник данных, который реализует единственный метод getAll()
интерфейса
DataSourceInterface
. Так же если источник данных поддерживает методы DataStoresInterface
для записи данных, можно
обновлять его.
Пример:
<?php
use rollun\datastore\DataStore\Memory;
use rollun\datastore\DataSource\DataSourceInterface;
use rollun\datastore\DataStore\Cacheable;
$data = [
['id' => 1, 'name' => 'foo1'],
['id' => 2, 'name' => 'foo2'],
['id' => 3, 'name' => 'foo3'],
['id' => 4, 'name' => 'foo4'],
];
$dataStore = new Memory(['id', 'name']);
$dataSource = new class($data) implements DataSourceInterface
{
/** @var \Traversable */
protected $data;
public function __construct($data) {
$this->data = $data;
}
public function getAll(): \Traversable {
return $this->data;
}
};
$cacheable = new Cacheable($dataSource, $dataStore);
var_dump($cacheable->count()); // 0
var_dump($cacheable->read(1)); // null
$cacheable->refresh();
var_dump($cacheable->count()); // 4
var_dump($cacheable->read(1)); // ['id' => 1, 'name' => 'foo1']
var_dump($cacheable->read(4)); // ['id' => 4, 'name' => 'foo4']
Хранилище не имеет никакого представления о типах данных которые он хранит, поэтому типизацией и хранением данных о
себе занимается аспект вокруг DataStoresInterface
, который поддерживает интерфейс SchemableInterface
и реализует метод getSchema
этого интерфейса. Для описания типа и форматтера для каждого столбца используется схема.
Схема это массив, ключ которого это название поля а значение - массив, в котором храниться в качестве ключей type
,
formatter
, а в качестве значений соответствующие классы.
Пример:
$schema = [
'id' => [
'type' => \Module\Type\TypeInt::class,
'formatter' => Module\Formatter\StringFormatter::class,
],
'name' => [
'type' => \Module\Type\TypeString::class,
'formatter' => Module\Formatter\StringFormatter::class,
],
]
Для введения типа используются объекты, которые реализуют интерфейс TypeInterface
.
Существующие типы:
TypeBoolean
TypeChar
TypeFloat
TypeInt
TypeString
Также для удобного использование типов предусмотрен DTO
(Data transfer object). Такой DTO удобно передавать в качестве данных для методов create
, update
.
DTO должен принимать и хранить в себе только объекты типа TypeInterface
и возвращать уже сами значения.
DTO не должен изменяться (тоесть ни каких сетеров).
Конструктор на вход должен принимать все необходимые значение в виде TypeInterface
.
Пример:
<?php
namespace Module\Dto;
use rollun\datastore\DataStore\BaseDto;
use rollun\datastore\DataStore\Type\TypeInt;
use rollun\datastore\DataStore\Type\TypeString;
class UserDto extends BaseDto
{
protected $id;
protected $name;
public function __construct(TypeInt $id, TypeString $name) {
$this->id = $id;
$this->name = $name;
}
public function getId()
{
$this->id->toTypeValue();
}
public function getName()
{
$this->name->toTypeValue();
}
}
// Examples
$id = new TypeInt('1');
$name = new TypeString('name');
$user = new UserDto($id, $name);
// The same as 'new UserDto($id, $name)'
$user = UserDto::createFromArray([
'id' => 1,
'name' => 'foo'
]);
echo $user->getId(); // 1 (int)
echo $user->getName(); // 'name' (string)
Зачастую в хранилище нужно передать отформатированные каким то образом данные полученные из DTO.
Для этого удобно использовать форматеры. Форматеры (formatter) реализуют интерфейс FormatterInterface
.
Существующие форматтеры:
BooleanFormatter
CharFormatter
FloatFormatter
IntFormatter
StringFormatter
Пример:
<?php
namespace Module\Formatter;
use rollun\datastore\DataStore\Formatter\FormatterInterface;
use Module\Dto\UserDto;
class StringFormatter implements FormatterInterface
{
public function format($value)
{
return (string)$value;
}
}
Как было указано, для HttpClient
нужно предоставить url, который будет корректно обрабатывать GET
, POST
, 'PUT
,
DELETE
, PATCH
в соответствии с RESTful API и уметь обрабатывать RQL. С этой задачей может справиться Data Store Middleware
.
Для этого нужно в качестве middleware обработчика route указать DataStoreApi
. Нужно чтобы route был типа
/api/datastore/{resourceName}[/{id}]
и иметь в сервис с именем resourceName
в реализации PSR ContainerInterface
вашего приложения.
Пример конфигураций route для zendframework/zend-expressive-skeleton:
- Посредством конфигурационного файла для zendframework/zend-expressive
<?php
use rollun\datastore\Middleware\DataStoreApi;
return [
'routes' => [
[
'name' => DataStoreApi::class,
'path' => '/api/datastore/{resourceName}[/{id}]',
'middleware' => DataStoreApi::class,
'allowed_methods' => ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'],
],
],
];
- Через объект
\Zend\Expressive\Application
<?php
use rollun\datastore\Middleware\DataStoreApi;
/** @var \Zend\Expressive\Application $app */
$app->route(
'/api/datastore/{resourceName}[/{id}]', // route pattern
DataStoreApi::class, // middleware
['GET', 'POST', 'PUT', 'DELETE', 'PATCH'],
DataStoreApi::class // route name
);
Заголовки запроса
If-Match
- заголовок который указывает на то что запись должна быть создана если не существует при обновлении и перезаписана если существует при создании записи для методовupdate
иcreate
соответственно (второй параметр для указанных методов:$createIfAbsent
и$rewriteIfExist
- соответственно). ЕслиIf-Match: *
тогда параметры$createIfAbsent
и$rewriteIfExist
будутtrue
, а если указано другое значение заголовка или заголовка вообще не существует эти парметры будут иметь значениеfalse
.With-Content-Range
- заголовок который указывает на то будет ли возвращен ответ с заголовкомContent-Range
.Из внутренностей: для того чтобы создать ответ с заголовком
Content-Range
нужно вызвать методcount
вdatastore
, поэтому дляdatastore
с генерируемыми данными могут возникнут проблемы.
Заголовки запроса
Datastore-Scheme
- заголовок в котором указанjson
закодирована схемаDatastore
, если он обернут вAspectType
.X_MULTI_CREATE
- заголовок, который свидетельствует поддержки multiCreateX_DATASTORE_IDENTIFIER
- заголовок в котором указан название ID колонкиDownload
- заголовок указывает на то, что мы хотим скачать файл. В значение следует указать тип файла. Например csv.
Псевдокод для скачивания данный по клику на кнопку:
$('#GetFile').on('click', function () {
$.ajax({
beforeSend: function (jqXHR, settings) {
jqXHR.setRequestHeader('Download', 'csv');
},
url: 'http://rollun.local/api/datastore/dataStore1',
method: 'GET',
xhrFields: {
responseType: 'blob'
},
success: function (data) {
var a = document.createElement('a');
var url = window.URL.createObjectURL(data);
a.href = url;
a.download = 'test.csv';
document.body.append(a);
a.click();
a.remove();
window.URL.revokeObjectURL(url);
}
});
});
Так же библиотека предоставляет возможность создавать и удалять таблицы бд используя TableMysqlManager
. Для это нужен
Zend\Db\Adapter\Adapter
. Создать таблицы можно и при инициализации объекта и при вызове методы createTable()
с
помощью конфигураций. Структура конфигураций представляет собой массив, где ключ - имя поля, а значение - массив со
следующими ключами:
-
TableManagerMysql::FIELD_TYPE
указывает на тип поля. Доступные значения и их константы разбитые на групы:TableManagerMysql::COLUMN_SIMPLE
:TableManagerMysql::TYPE_BIG_INTEGER
TableManagerMysql::TYPE_BOOLEAN
TableManagerMysql::TYPE_DATE
TableManagerMysql::TYPE_DATETIME
TableManagerMysql::TYPE_INTEGER
TableManagerMysql::TYPE_TIME
TableManagerMysql::TYPE_TIMESTAMP
TableManagerMysql::TYPE_BINARY
TableManagerMysql::COLUMN_LENGTH
:TableManagerMysql::TYPE_BLOB
TableManagerMysql::TYPE_CHAR
TableManagerMysql::TYPE_TEXT
TableManagerMysql::TYPE_VARBINARY
TableManagerMysql::TYPE_VARCHAR
TableManagerMysql::COLUMN_PRECISION
:TableManagerMysql::TYPE_DECIMAL
TableManagerMysql::TYPE_FLOAT
TableManagerMysql::TYPE_FLOATING
-
TableManagerMysql::FIELD_PARAMS
указывает на дополнительные свойства полей в виде массива. Доступные свойства - константы:- Для всех групп:
TableManagerMysql::PROPERTY_NULLABLE
TableManagerMysql::PROPERTY_DEFAULT
TableManagerMysql::PROPERTY_OPTIONS
ключ, значением которого сформирован с массива доступных опций:TableManagerMysql::OPTION_AUTOINCREMENT
TableManagerMysql::OPTION_UNSIGNED
TableManagerMysql::OPTION_ZEROFILL
TableManagerMysql::OPTION_IDENTITY
TableManagerMysql::OPTION_SERIAL
TableManagerMysql::OPTION_COMMENT
TableManagerMysql::OPTION_COLUMNFORMAT
TableManagerMysql::OPTION_FORMAT
TableManagerMysql::OPTION_STORAGE
TableManagerMysql::COLUMN_LENGTH
:TableManagerMysql::PROPERTY_LENGTH
TableManagerMysql::COLUMN_PRECISION
:TableManagerMysql::PROPERTY_DIGITS
TableManagerMysql::PROPERTY_DECIMAL
- Для всех групп:
-
TableManagerMysql::FOREIGN_KEY
описывает внешний ключ данного поля в виде массива из доступных констант:TableManagerMysql::OPTION_REFERENCE_TABLE
TableManagerMysql::OPTION_REFERENCE_COLUMN
TableManagerMysql::OPTION_ON_DELETE_RULE
TableManagerMysql::OPTION_ON_UPDATE_RULE
TableManagerMysql::OPTION_NAME
-
TableManagerMysql::UNIQUE_KEY
описывает уникальный ключ. В качестве значения принимается имя ключа.
Пример:
<?php
use rollun\datastore\TableGateway\TableManagerMysql;
use Zend\Db\Adapter\Adapter;
$tableConfig = [
'id' => [
TableManagerMysql::FIELD_TYPE => TableManagerMysql::TYPE_INTEGER,
TableManagerMysql::FIELD_PARAMS => [
TableManagerMysql::PROPERTY_OPTIONS => [
TableManagerMysql::OPTION_AUTOINCREMENT => true,
],
],
],
'name' => [
TableManagerMysql::FIELD_TYPE => TableManagerMysql::TYPE_VARCHAR,
TableManagerMysql::FIELD_PARAMS => [
TableManagerMysql::PROPERTY_LENGTH => 10,
TableManagerMysql::PROPERTY_NULLABLE => true,
TableManagerMysql::PROPERTY_DEFAULT => 'foo',
],
TableManagerMysql::UNIQUE_KEY => true,
],
];
$dbConfig = [
'driver' => 'Mysqli',
'database' => 'zend_db_example',
'username' => 'developer',
'password' => 'developer-password',
];
$adapter = new Adapter($dbConfig);
$tableManager = new TableManagerMysql($adapter);
$tableManager->createTable('tableName1', $tableConfig);
Для того чтобы создать таблицы и/или задать конфигурации для таблиц при инициализации объекта нужно задать
конфигурации таблиц под ключами TableManagerMysql::KEY_AUTOCREATE_TABLES
и TableManagerMysql::KEY_TABLES_CONFIGS
соответственно вторым параметром конструктора.
Пример:
<?php
use rollun\datastore\TableGateway\TableManagerMysql;
use Zend\Db\Adapter\Adapter;
$tablesConfigs = [
TableManagerMysql::KEY_AUTOCREATE_TABLES => [
'tableName2' => [
'id' => [
TableManagerMysql::FIELD_TYPE => TableManagerMysql::TYPE_INTEGER,
TableManagerMysql::FIELD_PARAMS => [
TableManagerMysql::PROPERTY_OPTIONS => [
TableManagerMysql::OPTION_AUTOINCREMENT => true,
],
],
TableManagerMysql::FOREIGN_KEY => [
TableManagerMysql::OPTION_REFERENCE_TABLE => 'tableName1',
TableManagerMysql::OPTION_REFERENCE_COLUMN => 'id',
TableManagerMysql::OPTION_ON_DELETE_RULE => 'cascade',
TableManagerMysql::OPTION_ON_UPDATE_RULE => null,
TableManagerMysql::OPTION_NAME => null,
],
],
'name' => [
TableManagerMysql::FIELD_TYPE => TableManagerMysql::TYPE_VARCHAR,
TableManagerMysql::FIELD_PARAMS => [
TableManagerMysql::PROPERTY_LENGTH => 10,
TableManagerMysql::PROPERTY_NULLABLE => true,
TableManagerMysql::PROPERTY_DEFAULT => 'foo',
],
],
],
],
TableManagerMysql::KEY_TABLES_CONFIGS => [
'tableName3' => [
'id' => [
TableManagerMysql::FIELD_TYPE => TableManagerMysql::TYPE_VARCHAR,
TableManagerMysql::FIELD_PARAMS => [
TableManagerMysql::PROPERTY_LENGTH => 10,
TableManagerMysql::PROPERTY_NULLABLE => true,
TableManagerMysql::PROPERTY_DEFAULT => 'foo',
],
],
],
],
];
$dbConfig = [
'driver' => 'Mysqli',
'database' => 'zend_db_example',
'username' => 'developer',
'password' => 'developer-password',
];
$adapter = new Adapter($dbConfig);
$tableManager = new TableManagerMysql($adapter, $tablesConfigs);
Cleaner
предоставляет гибкий способ удаление данных, которые прошли 'валидацию на удаление' с хранилища. Для этого
нужно реализовать единственный метод isValid()
интерфейса CleaningValidatorInterface
.
Пример:
<?php
use rollun\datastore\DataStore\Memory;
use rollun\datastore\Cleaner\Cleaner;
use rollun\utils\Cleaner\CleaningValidator\CleaningValidatorInterface;
use rollun\datastore\Rql\RqlQuery;
$dataStore = new Memory(['id', 'name']);
foreach (range(1, 3) as $id) {
$dataStore->create([
'id' => $id,
'name' => "foo{$id}",
]);
}
$cleaningValidator = new class implements CleaningValidatorInterface
{
public function isValid($value){
return $value['id'] > 1 && $value['name'] !== 'foo3';
}
};
$cleaner = new Cleaner($dataStore, $cleaningValidator);
$cleaner->cleanList();
var_dump($dataStore->count()); // 1
var_dump($dataStore->query(new RqlQuery())); // [['id' => '2', 'name' => 'foo2']]
Для загрузки данных в хранилище с итератора можно использовать Uploader
. Так же если этот итератор
поддерживает интерфейс \SeekableIterator
можно возобновлять загрузку данных с прошлой позиции.
DataStorePack
реализует итератор \SeekableIterator
для хранилища. Таким способом можно
перекачивать данные с одного хранилища в другой, с возможностью возобновить загрузку данных с прошлой считаной позиции.
Пример:
<?php
use rollun\datastore\DataStore\Memory;
use rollun\uploader\Uploader;
use rollun\uploader\Iterator\DataStorePack;
$dataStoreFrom = new Memory(['id', 'name']);
foreach (range(1, 4) as $id) {
$dataStoreFrom->create([
'id' => $id,
'name' => "foo{$id}"
]);
}
$dataStoreTo = new Memory(['id', 'name']);
$iterator = new DataStorePack($dataStoreFrom);
$uploader = new Uploader($iterator, $dataStoreTo);
var_dump($dataStoreTo->has(1)); // false
$uploader->upload(); // or $uploader();
var_dump($dataStoreTo->has(1)); // true
var_dump($dataStoreTo->read(1)); // ['id' => 1, 'name' => 'foo1']
var_dump($dataStoreTo->read(3)); // ['id' => 3, 'name' => 'foo3']
Библиотека предоставляет соответствующие фабрики к базовым реализациям DataStoresInterface
, которые можно задать для
zendframework/zend-servicemanager.
Все фабрики имеют единый ключ верхнего уровня dataStore
(DataStoreAbstractFactory::KEY_DATASTORE
).
Пример конфигурации:
[
'dataStore' => [
'serviceName1' => [
'class' => \rollun\datastore\DataStore\DbTable::class,
'tableName' => 'myTableName',
'dbAdapter' => 'db' // service name, optional
'sqlQueryBuilder' => 'sqlQueryBuilder' // service name, optional
],
'serviceName2' => [
// ...
],
]
]
Пример конфигурации:
[
'dataStore' => [
'serviceName1' => [
'class' => \rollun\datastore\DataStore\CsvBase::class,
'filename' => 'someFile',
'delimiter' => ',' // optional
],
'serviceName2' => [
// ...
],
]
]
Используя ключ
identifier
в опциях клиента, можно указать специфический id удаленного репозитория
Пример конфигурации:
[
'dataStore' => [
'serviceName1' => [
'class' => 'rollun\datastore\DataStore\HttpDatastoreClassName',
'url' => 'http://site.com/api/resource-name', // general url scheme: {scheme}://{host}[:{port}]/api/{sourceName}
'options' => [
'identifier' => 'custom_id_fields',
'timeout' => 30,
'adapter' => 'Zend\Http\Client\Adapter\Socket',
]
],
'serviceName2' => [
// ...
],
]
];
Пример конфигурации:
[
'dataStore' => [
'serviceName1' => [
'class' => 'rollun\datastore\DataStore\Memory',
'requiredColumns' => [, // optional
'column1',
'column2',
// ...
],
],
'serviceName2' => [
// ...
]
]
]
Пример конфигурации:
[
'dataStore' => [
'serviceName1' => [
'class' => \rollun\datastore\DataStore\Cacheable::class,
'dataSource' => 'testDataSourceDb',
'cacheable' => 'testDbTable'
],
'serviceName2' => [
// ...
]
]
]
Библиотека поддерживает aspect pattern и observer pattern(Zend EventManager), что дает возможность выполнять дополнительные действие до события или после.
Пример конфигурации для оборачивания датастора в аспект с eventManager:
[
'dataStore' => [
'aspectDataStore1' => [ // оборачивает dataStore1 в аспект
'class' => \rollun\datastore\DataStore\Aspect\AspectAbstract::class, // здесь указываем класс в котором будут методы аспекта, например preCreate
'dataStore' => 'dataStore1' // указывем dataStore
],
'aspectDataStore2' => [
'class' => \rollun\datastore\DataStore\Aspect\AspectWithEventManagerAbstract::class, // оборачиваем dataStore1 в аспект с event manager
'dataStore' => 'dataStore1',
'listeners' => [ // указывем слушатели
\App\Listener\DataStoreMasterListener::class, // указывем класс которые наследник \rollun\datastore\DataStore\Aspect\AbstractAspectListener
// или
'onPostCreate' => ['postCreateUpdateHandler'], // здесь нужно указать callable
]
],
'dataStore1' => [
'class' => \rollun\datastore\DataStore\DbTable::class,
'tableName' => 'datastore_1',
],
],
]
Пример слушателя:
<?php
declare(strict_types=1);
namespace App\Listener;
use rollun\datastore\DataStore\Aspect\AbstractAspectListener;
use rollun\datastore\DataStore\DbTable;
use rollun\dic\InsideConstruct;
use Zend\EventManager\Event;
/**
* Class DataStoreMasterListener
*
* @author Roman Ratsun <[email protected]>
*/
class DataStoreMasterListener extends AbstractAspectListener
{
/**
* @var DbTable
*/
private $dataStore;
/**
* DataStoreMasterListener constructor.
*
* @throws \ReflectionException
*/
public function __construct()
{
InsideConstruct::init(['dataStore' => 'dataStore2']);
}
/**
* @param Event $event
*/
public function onPostCreate(Event $event)
{
// реализация
}
/**
* @inheritDoc
*/
public function __sleep()
{
return [];
}
/**
* @inheritDoc
*/
public function __wakeup()
{
InsideConstruct::initWakeup(['dataStore' => 'dataStore2']);
}
}
Библиотека предоставляет объект (расширяет SplFileObject) для работы с файлами. Преимущества данного объекта в том, что здесь реализованы блокировки файлов, что существенно упростят работу. Пример использования:
<?php
use rollun\files\FileObject;
$fileObject = new FileObject('some-file.csv');
$fileObject->fwriteWithCheck('012345');
$fileObject->moveSubStr(3, 1);
$fileObject->fseek(0);
$actual = $fileObject->fread(100); // '0345'
Для более подробного изучения ознакомьтесь с юнит тестами.
Библиотека предоставляет объекты для работы с csv файлами. CsvFileObjectWithPrKey работает с файлами используя разные стратегии. По умолчанию используется стратегия бинарного поиска, что в разы ускоряет поиск нужной нам строки. Пример использования:
<?php
use rollun\files\Csv\CsvFileObjectWithPrKey;
$fileObject = new CsvFileObjectWithPrKey('some-file.csv');
$result = $fileObject->getRowById('1'); // array
Для более подробного изучения ознакомьтесь с юнит тестами.
До версии "6.6.1" есть баг в классе CsvBinaryStrategy (которы отвечает за бинарный поиск), из-за которой некорректно работал поиск (если запускать его больше одного раза) и добавление новых строк. Причина в том, что после поиска не обнулялось поле $uniqueIterations и влияло на результаты следующих поисков.