Move some abstract controllers to benzine-database from benzine-controllers
This commit is contained in:
parent
ffb084aba2
commit
826c348594
6 changed files with 1065 additions and 4 deletions
236
src/Abstracts/Model.php
Executable file
236
src/Abstracts/Model.php
Executable file
|
|
@ -0,0 +1,236 @@
|
|||
<?php
|
||||
|
||||
namespace ⌬\Database\Abstracts;
|
||||
|
||||
use Camel\CaseTransformer;
|
||||
use Camel\Format;
|
||||
use ⌬\Database\Interfaces\ModelInterface;
|
||||
|
||||
abstract class Model implements ModelInterface
|
||||
{
|
||||
protected array $_primary_keys = [];
|
||||
protected array $_autoincrement_keys = [];
|
||||
|
||||
protected array $_original;
|
||||
|
||||
public function __construct(array $data = [])
|
||||
{
|
||||
if ($data) {
|
||||
$this->exchangeArray($data);
|
||||
}
|
||||
$this->__setUp();
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrideable __setUp function that will allow you to hijack
|
||||
* it and create any related objects that need to be recreated.
|
||||
*/
|
||||
public function __setUp(): void
|
||||
{
|
||||
}
|
||||
|
||||
public function __wakeup()
|
||||
{
|
||||
$this->__setUp();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function __toArray()
|
||||
{
|
||||
$array = [];
|
||||
|
||||
$transformer = new CaseTransformer(new Format\StudlyCaps(), new Format\StudlyCaps());
|
||||
|
||||
foreach ($this->getListOfProperties() as $property) {
|
||||
$getFunction = "get{$property}";
|
||||
$currentValue = $this->{$getFunction}();
|
||||
$array[$transformer->transform($property)] = $currentValue;
|
||||
}
|
||||
|
||||
return array_merge($array);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function __toRawArray()
|
||||
{
|
||||
$array = [];
|
||||
|
||||
$transformer = new CaseTransformer(new Format\StudlyCaps(), new Format\StudlyCaps());
|
||||
|
||||
foreach ($this->getListOfProperties() as $dbField => $property) {
|
||||
$currentValue = $this->{$property};
|
||||
$array[$dbField] = $currentValue;
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
public function __toPublicArray(): array
|
||||
{
|
||||
$publicArray = [];
|
||||
foreach ($this->getListOfProperties() as $property) {
|
||||
$publicArray[ucfirst($property)] = $this->{$property};
|
||||
}
|
||||
|
||||
return $publicArray;
|
||||
}
|
||||
|
||||
public function __fromPublicArray(array $publicArray): self
|
||||
{
|
||||
foreach ($this->getListOfProperties() as $property) {
|
||||
$this->{$property} = $publicArray[ucfirst($property)];
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function __serialize(): array
|
||||
{
|
||||
return $this->__toPublicArray();
|
||||
}
|
||||
|
||||
public function __unserialize(array $data): void
|
||||
{
|
||||
$this->__fromPublicArray($data);
|
||||
}
|
||||
|
||||
public function __pre_save()
|
||||
{
|
||||
// Stub function to be overridden.
|
||||
}
|
||||
|
||||
public function __post_save()
|
||||
{
|
||||
// Stub function to be overridden.
|
||||
}
|
||||
|
||||
public static function factory(array $data = [])
|
||||
{
|
||||
$class = get_called_class();
|
||||
|
||||
return new $class($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Interop\Container\ContainerInterface
|
||||
*/
|
||||
public function getDIContainer()
|
||||
{
|
||||
return App::Container();
|
||||
}
|
||||
|
||||
public function getPrimaryKeys(): array
|
||||
{
|
||||
$primaryKeyValues = [];
|
||||
foreach ($this->_primary_keys as $internalName => $dbName) {
|
||||
$getFunction = "get{$internalName}";
|
||||
$primaryKeyValues[$internalName] = $this->{$getFunction}();
|
||||
}
|
||||
|
||||
return $primaryKeyValues;
|
||||
}
|
||||
|
||||
public function getPrimaryKeys_dbColumns(): array
|
||||
{
|
||||
$primaryKeyValues = [];
|
||||
foreach ($this->_primary_keys as $internalName => $dbName) {
|
||||
$getFunction = "get{$internalName}";
|
||||
$primaryKeyValues[$dbName] = $this->{$getFunction}();
|
||||
}
|
||||
|
||||
return $primaryKeyValues;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return autoincrement key values in an associative array.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAutoIncrementKeys()
|
||||
{
|
||||
$autoIncrementKeyValues = [];
|
||||
foreach ($this->_autoincrement_keys as $autoincrement_key => $autoincrement_db_column) {
|
||||
$getFunction = "get{$autoincrement_key}";
|
||||
$autoIncrementKeyValues[$autoincrement_key] = $this->{$getFunction}();
|
||||
}
|
||||
|
||||
return $autoIncrementKeyValues;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the primary key isn't null.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasPrimaryKey()
|
||||
{
|
||||
$notNull = false;
|
||||
foreach ($this->getPrimaryKeys() as $primaryKey) {
|
||||
if (null != $primaryKey) {
|
||||
$notNull = true;
|
||||
}
|
||||
}
|
||||
|
||||
return $notNull;
|
||||
}
|
||||
|
||||
public function getListOfProperties(): array
|
||||
{
|
||||
// @todo make this into an interface entry
|
||||
throw new \Exception('getListOfProperties in Abstract Model should never be used.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the data has been modified inside this model.
|
||||
*/
|
||||
public function hasDirtyProperties(): bool
|
||||
{
|
||||
return count($this->getListOfDirtyProperties()) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of dirty properties.
|
||||
*/
|
||||
public function getListOfDirtyProperties(): array
|
||||
{
|
||||
$transformer = new CaseTransformer(new Format\CamelCase(), new Format\StudlyCaps());
|
||||
$dirtyProperties = [];
|
||||
foreach ($this->getListOfProperties() as $property) {
|
||||
$originalProperty = $transformer->transform($property);
|
||||
//echo "Writing into \$this->{$originalProperty}: getListOfDirtyProperties\n";
|
||||
if (!isset($this->_original[$originalProperty]) || $this->{$property} != $this->_original[$originalProperty]) {
|
||||
$dirtyProperties[$property] = [
|
||||
'before' => isset($this->_original[$originalProperty]) ? $this->_original[$originalProperty] : null,
|
||||
'after' => $this->{$property},
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $dirtyProperties;
|
||||
}
|
||||
|
||||
public function isDirty(): bool
|
||||
{
|
||||
$clean = true;
|
||||
foreach ($this->_original as $key => $originalValue) {
|
||||
foreach ($this->getListOfProperties() as $existingKey) {
|
||||
if (strtolower($key) == strtolower($existingKey)) {
|
||||
if ($this->{$existingKey} != $originalValue) {
|
||||
$clean = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return !$clean;
|
||||
}
|
||||
|
||||
protected function getProtectedMethods(): array
|
||||
{
|
||||
return ['getPrimaryKeys', 'getProtectedMethods', 'getDIContainer'];
|
||||
}
|
||||
}
|
||||
92
src/Abstracts/Service.php
Executable file
92
src/Abstracts/Service.php
Executable file
|
|
@ -0,0 +1,92 @@
|
|||
<?php
|
||||
|
||||
namespace ⌬\Database\Abstracts;
|
||||
|
||||
use Laminas\Db\ResultSet\ResultSet;
|
||||
use Laminas\Db\Sql\Expression;
|
||||
use Laminas\Db\Sql\Select;
|
||||
|
||||
abstract class Service
|
||||
{
|
||||
abstract public function getNewModelInstance();
|
||||
|
||||
abstract public function getTermPlural(): string;
|
||||
|
||||
abstract public function getTermSingular(): string;
|
||||
|
||||
abstract public function getNewTableGatewayInstance();
|
||||
|
||||
/**
|
||||
* @param null|array|\Closure[] $wheres
|
||||
* @param null|Expression|string $order
|
||||
*
|
||||
* @return Model[]
|
||||
*/
|
||||
public function getAll(
|
||||
int $limit = null,
|
||||
int $offset = null,
|
||||
array $wheres = null,
|
||||
$order = null,
|
||||
string $orderDirection = null
|
||||
) {
|
||||
/** @var TableGateway $tableGateway */
|
||||
$tableGateway = $this->getNewTableGatewayInstance();
|
||||
list($matches, $count) = $tableGateway->fetchAll(
|
||||
$limit,
|
||||
$offset,
|
||||
$wheres,
|
||||
$order,
|
||||
null !== $orderDirection ? $orderDirection : Select::ORDER_ASCENDING
|
||||
);
|
||||
$return = [];
|
||||
|
||||
if ($matches instanceof ResultSet) {
|
||||
foreach ($matches as $match) {
|
||||
$return[] = $match;
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null|string $distinctColumn
|
||||
* @param null|array|\Closure[] $wheres
|
||||
*
|
||||
* @return Model[]
|
||||
*/
|
||||
public function getDistinct(
|
||||
string $distinctColumn,
|
||||
array $wheres = null
|
||||
) {
|
||||
/** @var TableGateway $tableGateway */
|
||||
$tableGateway = $this->getNewTableGatewayInstance();
|
||||
list($matches, $count) = $tableGateway->fetchDistinct(
|
||||
$distinctColumn,
|
||||
$wheres
|
||||
);
|
||||
|
||||
$return = [];
|
||||
if ($matches instanceof ResultSet) {
|
||||
foreach ($matches as $match) {
|
||||
$return[] = $match;
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null|array|\Closure[] $wheres
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function countAll(
|
||||
array $wheres = null
|
||||
) {
|
||||
/** @var TableGateway $tableGateway */
|
||||
$tableGateway = $this->getNewTableGatewayInstance();
|
||||
|
||||
return $tableGateway->getCount($wheres);
|
||||
}
|
||||
}
|
||||
733
src/Abstracts/TableGateway.php
Executable file
733
src/Abstracts/TableGateway.php
Executable file
|
|
@ -0,0 +1,733 @@
|
|||
<?php
|
||||
|
||||
namespace ⌬\Database\Abstracts;
|
||||
|
||||
use Laminas\Db\Adapter\AdapterInterface;
|
||||
use Laminas\Db\Adapter\Exception\InvalidQueryException;
|
||||
use Laminas\Db\ResultSet\ResultSet;
|
||||
use Laminas\Db\Sql\Expression;
|
||||
use Laminas\Db\Sql\Predicate;
|
||||
use Laminas\Db\Sql\Predicate\PredicateInterface;
|
||||
use Laminas\Db\Sql\Select;
|
||||
use Laminas\Db\Sql\Where;
|
||||
use ⌬\Controllers\Filters\FilterCondition;
|
||||
use ⌬\Database\Exception\Exception;
|
||||
use ⌬\Database\Interfaces\ModelInterface;
|
||||
use ⌬\Database\LaminatorSql;
|
||||
|
||||
abstract class TableGateway extends \Laminas\Db\TableGateway\TableGateway
|
||||
{
|
||||
protected string $model;
|
||||
protected $table;
|
||||
|
||||
public function __construct($table, AdapterInterface $adapter, $features = null, $resultSetPrototype = null, $sql = null)
|
||||
{
|
||||
$this->adapter = $adapter;
|
||||
$this->table = $table;
|
||||
|
||||
if (!$sql) {
|
||||
$sql = new LaminatorSql($this->adapter, $this->table);
|
||||
}
|
||||
parent::__construct($table, $adapter, $features, $resultSetPrototype, $sql);
|
||||
}
|
||||
|
||||
public function __set($property, $value)
|
||||
{
|
||||
if (property_exists($this, $property)) {
|
||||
$this->{$property} = $value;
|
||||
}
|
||||
}
|
||||
|
||||
public function __get($property)
|
||||
{
|
||||
if (!property_exists($this, $property)) {
|
||||
throw new Exception(sprintf('No such property %s on class %s', $property, get_called_class()));
|
||||
}
|
||||
|
||||
return $this->{$property};
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null|array|\ArrayObject
|
||||
*/
|
||||
public function save(Model $model)
|
||||
{
|
||||
// @todo check $model->isDirty() to quick-reject a save operation on a non-dirty record
|
||||
$model->__pre_save();
|
||||
|
||||
$pk = $model->getPrimaryKeys_dbColumns();
|
||||
|
||||
$pkIsBlank = true;
|
||||
foreach ($pk as $key => $value) {
|
||||
if (!is_null($value)) {
|
||||
$pkIsBlank = false;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
/** @var Model $oldModel */
|
||||
$oldModel = $this->select($pk)->current();
|
||||
if ($pkIsBlank || !$oldModel) {
|
||||
$pk = $this->saveInsert($model);
|
||||
} else {
|
||||
$this->saveUpdate($model, $oldModel);
|
||||
}
|
||||
|
||||
$updatedModel = $this->getByPrimaryKey($pk);
|
||||
|
||||
// Update the primary key fields on the existant $model object, because we may still be referencing this.
|
||||
// While it feels a bit yucky to magically mutate the model object, it is expected behaviour.
|
||||
foreach ($model->getPrimaryKeys() as $key => $value) {
|
||||
$setter = "set{$key}";
|
||||
$getter = "get{$key}";
|
||||
$model->{$setter}($updatedModel->{$getter}());
|
||||
}
|
||||
|
||||
$model->__post_save();
|
||||
|
||||
return $updatedModel;
|
||||
} catch (InvalidQueryException $iqe) {
|
||||
throw new InvalidQueryException(
|
||||
'While trying to call '.get_class().'->save(): ... '.
|
||||
$iqe->getMessage()."\n\n".
|
||||
substr(var_export($model, true), 0, 1024)."\n\n",
|
||||
$iqe->getCode(),
|
||||
$iqe
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null|int
|
||||
*/
|
||||
public function saveInsert(Model $model)
|
||||
{
|
||||
$data = $model->__toRawArray();
|
||||
$this->insert($data);
|
||||
|
||||
if ($model->hasPrimaryKey()) {
|
||||
return $model->getPrimaryKeys_dbColumns();
|
||||
}
|
||||
$pk = [];
|
||||
foreach ($model->getPrimaryKeys_dbColumns() as $primaryKey => $dontCare) {
|
||||
$pk[$primaryKey] = $this->getLastInsertValue();
|
||||
}
|
||||
|
||||
return $pk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function saveUpdate(Model $model, Model $oldModel)
|
||||
{
|
||||
return $this->update(
|
||||
$model->__toRawArray(),
|
||||
$model->getPrimaryKeys_dbColumns(),
|
||||
$oldModel->__toRawArray()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @param null $id
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function insert($data, &$id = null)
|
||||
{
|
||||
return parent::insert($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @param null $where
|
||||
* @param array|Model $oldData
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function update($data, $where = null, $oldData = [])
|
||||
{
|
||||
$data = array_filter($data);
|
||||
//!\Kint::dump($data, $oldData, $where);exit;
|
||||
return parent::update($data, $where);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is only supposed to be used by getListAction.
|
||||
*
|
||||
* @param null|int $limit Number to limit to
|
||||
* @param null|int $offset Offset of limit statement. Is ignored if limit not set.
|
||||
* @param null|array $wheres array of conditions to filter by
|
||||
* @param null|Expression|string $order Column to order on
|
||||
* @param null|string $direction Direction to order on (SELECT::ORDER_ASCENDING|SELECT::ORDER_DESCENDING)
|
||||
*
|
||||
* @return array [ResultSet,int] Returns an array of resultSet,total_found_rows
|
||||
*/
|
||||
public function fetchAll(
|
||||
int $limit = null,
|
||||
int $offset = null,
|
||||
array $wheres = null,
|
||||
$order = null,
|
||||
string $direction = Select::ORDER_ASCENDING
|
||||
) {
|
||||
/** @var Select $select */
|
||||
$select = $this->getSql()->select();
|
||||
|
||||
if (null !== $limit && is_numeric($limit)) {
|
||||
$select->limit(intval($limit));
|
||||
if (null !== $offset && is_numeric($offset)) {
|
||||
$select->offset($offset);
|
||||
}
|
||||
}
|
||||
//\Kint::dump($limit, $offset, $wheres, $order, $direction);
|
||||
if (null != $wheres) {
|
||||
foreach ($wheres as $conditional) {
|
||||
if ($conditional instanceof \Closure) {
|
||||
$select->where($conditional);
|
||||
} else {
|
||||
$spec = function (Where $where) use ($conditional) {
|
||||
switch ($conditional['condition']) {
|
||||
case FilterCondition::CONDITION_EQUAL:
|
||||
$where->equalTo($conditional['column'], $conditional['value']);
|
||||
|
||||
break;
|
||||
case FilterCondition::CONDITION_NOT_EQUAL:
|
||||
$where->notEqualTo($conditional['column'], $conditional['value']);
|
||||
|
||||
break;
|
||||
case FilterCondition::CONDITION_GREATER_THAN:
|
||||
$where->greaterThan($conditional['column'], $conditional['value']);
|
||||
|
||||
break;
|
||||
case FilterCondition::CONDITION_GREATER_THAN_OR_EQUAL:
|
||||
$where->greaterThanOrEqualTo($conditional['column'], $conditional['value']);
|
||||
|
||||
break;
|
||||
case FilterCondition::CONDITION_LESS_THAN:
|
||||
$where->lessThan($conditional['column'], $conditional['value']);
|
||||
|
||||
break;
|
||||
case FilterCondition::CONDITION_LESS_THAN_OR_EQUAL:
|
||||
$where->lessThanOrEqualTo($conditional['column'], $conditional['value']);
|
||||
|
||||
break;
|
||||
case FilterCondition::CONDITION_LIKE:
|
||||
$where->like($conditional['column'], $conditional['value']);
|
||||
|
||||
break;
|
||||
case FilterCondition::CONDITION_NOT_LIKE:
|
||||
$where->notLike($conditional['column'], $conditional['value']);
|
||||
|
||||
break;
|
||||
case FilterCondition::CONDITION_IN:
|
||||
$where->in($conditional['column'], $conditional['value']);
|
||||
|
||||
break;
|
||||
case FilterCondition::CONDITION_NOT_IN:
|
||||
$where->notIn($conditional['column'], $conditional['value']);
|
||||
|
||||
break;
|
||||
default:
|
||||
// @todo better exception plz.
|
||||
throw new \Exception("Cannot work out what conditional '{$conditional['condition']}'' is supposed to do in Zend... Probably unimplemented?");
|
||||
}
|
||||
};
|
||||
$select->where($spec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (null !== $order) {
|
||||
if ($order instanceof Expression) {
|
||||
$select->order($order);
|
||||
} else {
|
||||
$select->order("{$order} {$direction}");
|
||||
}
|
||||
}
|
||||
|
||||
$resultSet = $this->selectWith($select);
|
||||
|
||||
$quantifierSelect = $select
|
||||
->reset(Select::LIMIT)
|
||||
->reset(Select::COLUMNS)
|
||||
->reset(Select::OFFSET)
|
||||
->reset(Select::ORDER)
|
||||
->reset(Select::COMBINE)
|
||||
->columns(['total' => new Expression('COUNT(*)')])
|
||||
;
|
||||
|
||||
// execute the select and extract the total
|
||||
$row = $this->getSql()
|
||||
->prepareStatementForSqlObject($quantifierSelect)
|
||||
->execute()
|
||||
->current()
|
||||
;
|
||||
$total = (int) $row['total'];
|
||||
|
||||
return [$resultSet, $total];
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is only supposed to be used by getListAction.
|
||||
*
|
||||
* @param string $distinctColumn column to be distinct on
|
||||
* @param array $wheres array of conditions to filter by
|
||||
*
|
||||
* @return array [ResultSet,int] Returns an array of resultSet,total_found_rows
|
||||
*/
|
||||
public function fetchDistinct(
|
||||
string $distinctColumn,
|
||||
array $wheres = null
|
||||
) {
|
||||
/** @var Select $select */
|
||||
$select = $this->getSql()->select();
|
||||
$select->quantifier(Select::QUANTIFIER_DISTINCT);
|
||||
$select->columns([$distinctColumn]);
|
||||
|
||||
//\Kint::dump($distinctColumn, $wheres);
|
||||
if (null != $wheres) {
|
||||
foreach ($wheres as $conditional) {
|
||||
if ($conditional instanceof \Closure) {
|
||||
$select->where($conditional);
|
||||
} else {
|
||||
$spec = function (Where $where) use ($conditional) {
|
||||
switch ($conditional['condition']) {
|
||||
case FilterCondition::CONDITION_EQUAL:
|
||||
$where->equalTo($conditional['column'], $conditional['value']);
|
||||
|
||||
break;
|
||||
case FilterCondition::CONDITION_GREATER_THAN:
|
||||
$where->greaterThan($conditional['column'], $conditional['value']);
|
||||
|
||||
break;
|
||||
case FilterCondition::CONDITION_GREATER_THAN_OR_EQUAL:
|
||||
$where->greaterThanOrEqualTo($conditional['column'], $conditional['value']);
|
||||
|
||||
break;
|
||||
case FilterCondition::CONDITION_LESS_THAN:
|
||||
$where->lessThan($conditional['column'], $conditional['value']);
|
||||
|
||||
break;
|
||||
case FilterCondition::CONDITION_LESS_THAN_OR_EQUAL:
|
||||
$where->lessThanOrEqualTo($conditional['column'], $conditional['value']);
|
||||
|
||||
break;
|
||||
case FilterCondition::CONDITION_LIKE:
|
||||
$where->like($conditional['column'], $conditional['value']);
|
||||
|
||||
break;
|
||||
default:
|
||||
// @todo better exception plz.
|
||||
throw new \Exception("Cannot work out what conditional {$conditional['condition']} is supposed to do in Zend... Probably unimplemented?");
|
||||
}
|
||||
};
|
||||
$select->where($spec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$resultSet = $this->selectWith($select);
|
||||
|
||||
$quantifierSelect = $select
|
||||
->reset(Select::LIMIT)
|
||||
->reset(Select::COLUMNS)
|
||||
->reset(Select::OFFSET)
|
||||
->reset(Select::ORDER)
|
||||
->reset(Select::COMBINE)
|
||||
->columns(['total' => new Expression('COUNT(*)')])
|
||||
;
|
||||
|
||||
// execute the select and extract the total
|
||||
$row = $this->getSql()
|
||||
->prepareStatementForSqlObject($quantifierSelect)
|
||||
->execute()
|
||||
->current()
|
||||
;
|
||||
$total = (int) $row['total'];
|
||||
|
||||
return [$resultSet, $total];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null|ModelInterface
|
||||
*/
|
||||
public function fetchRandom()
|
||||
{
|
||||
$resultSet = $this->select(function (Select $select) {
|
||||
$select->order(new Expression('RAND()'))->limit(1);
|
||||
});
|
||||
|
||||
if (0 == count($resultSet)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $resultSet->current();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|Select $where
|
||||
* @param array|string $order
|
||||
* @param int $offset
|
||||
*
|
||||
* @return null|array|\ArrayObject|Model
|
||||
*/
|
||||
public function fetchRow($where = null, $order = null, $offset = null)
|
||||
{
|
||||
if ($where instanceof Select) {
|
||||
$resultSet = $this->selectWith($where);
|
||||
} else {
|
||||
$resultSet = $this->select(function (Select $select) use ($where, $order, $offset) {
|
||||
if (!is_null($where)) {
|
||||
$select->where($where);
|
||||
}
|
||||
if (!is_null($order)) {
|
||||
$select->order($order);
|
||||
}
|
||||
if (!is_null($offset)) {
|
||||
$select->offset($offset);
|
||||
}
|
||||
$select->limit(1);
|
||||
});
|
||||
}
|
||||
|
||||
return (count($resultSet) > 0) ? $resultSet->current() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PredicateInterface[]|Where[] $where
|
||||
* @param mixed $wheres
|
||||
*/
|
||||
public function getCount($wheres = []): int
|
||||
{
|
||||
$select = $this->getSql()->select();
|
||||
$select->columns(['total' => new Expression('IFNULL(COUNT(*),0)')]);
|
||||
|
||||
if (is_array($wheres) && count($wheres) > 0) {
|
||||
foreach ($wheres as $where) {
|
||||
$select->where($where);
|
||||
}
|
||||
}
|
||||
|
||||
$row = $this->getSql()
|
||||
->prepareStatementForSqlObject($select)
|
||||
->execute()
|
||||
->current()
|
||||
;
|
||||
|
||||
return !is_null($row) ? $row['total'] : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PredicateInterface[]|Where[] $wheres
|
||||
*/
|
||||
public function getCountUnique(string $field, $wheres = []): int
|
||||
{
|
||||
$select = $this->getSql()->select();
|
||||
$select->columns(['total' => new Expression('DISTINCT '.$field)]);
|
||||
if (count($wheres) > 0) {
|
||||
foreach ($wheres as $where) {
|
||||
$select->where($where);
|
||||
}
|
||||
}
|
||||
|
||||
$row = $this->getSql()
|
||||
->prepareStatementForSqlObject($select)
|
||||
->execute()
|
||||
->current()
|
||||
;
|
||||
|
||||
return !is_null($row) ? $row['total'] : 0;
|
||||
}
|
||||
|
||||
public function getPrimaryKeys(): array
|
||||
{
|
||||
/** @var Model $oModel */
|
||||
$oModel = $this->getNewMockModelInstance();
|
||||
|
||||
return array_keys($oModel->getPrimaryKeys());
|
||||
}
|
||||
|
||||
public function getAutoIncrementKeys(): array
|
||||
{
|
||||
/** @var Model $oModel */
|
||||
$oModel = $this->getNewMockModelInstance();
|
||||
|
||||
return array_keys($oModel->getAutoIncrementKeys());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of all primary keys on the table keyed by the column.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getHighestPrimaryKey(): array
|
||||
{
|
||||
$highestPrimaryKeys = [];
|
||||
foreach ($this->getPrimaryKeys() as $primaryKey) {
|
||||
$Select = $this->getSql()->select();
|
||||
$Select->columns(['max' => new Expression("MAX({$primaryKey})")]);
|
||||
$row = $this->getSql()
|
||||
->prepareStatementForSqlObject($Select)
|
||||
->execute()
|
||||
->current()
|
||||
;
|
||||
|
||||
$highestPrimaryKey = !is_null($row) ? $row['max'] : 0;
|
||||
$highestPrimaryKeys[$primaryKey] = $highestPrimaryKey;
|
||||
}
|
||||
|
||||
return $highestPrimaryKeys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of all autoincrement keys on the table keyed by the column.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getHighestAutoincrementKey(): array
|
||||
{
|
||||
$highestAutoIncrementKeys = [];
|
||||
foreach ($this->getPrimaryKeys() as $autoIncrementKey) {
|
||||
$Select = $this->getSql()->select();
|
||||
$Select->columns(['max' => new Expression("MAX({$autoIncrementKey})")]);
|
||||
$row = $this->getSql()
|
||||
->prepareStatementForSqlObject($Select)
|
||||
->execute()
|
||||
->current()
|
||||
;
|
||||
|
||||
$highestAutoIncrementKey = !is_null($row) ? $row['max'] : 0;
|
||||
$highestAutoIncrementKeys[$autoIncrementKey] = $highestAutoIncrementKey;
|
||||
}
|
||||
|
||||
return $highestAutoIncrementKeys;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
*
|
||||
* @return null|Model
|
||||
*/
|
||||
public function getById($id)
|
||||
{
|
||||
return $this->getByField('id', $id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $field
|
||||
* @param $value
|
||||
* @param $orderBy string Field to sort by
|
||||
* @param $orderDirection string Direction to sort (Select::ORDER_ASCENDING || Select::ORDER_DESCENDING)
|
||||
*
|
||||
* @return null|array|\ArrayObject
|
||||
*/
|
||||
public function getByField($field, $value, $orderBy = null, $orderDirection = Select::ORDER_ASCENDING)
|
||||
{
|
||||
$select = $this->sql->select();
|
||||
|
||||
$select->where([$field => $value]);
|
||||
if ($orderBy) {
|
||||
if ($orderBy instanceof Expression) {
|
||||
$select->order($orderBy);
|
||||
} else {
|
||||
$select->order("{$orderBy} {$orderDirection}");
|
||||
}
|
||||
}
|
||||
$select->limit(1);
|
||||
|
||||
$resultSet = $this->selectWith($select);
|
||||
|
||||
$row = $resultSet->current();
|
||||
if (!$row) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $row;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
* @param $limit int
|
||||
* @param $orderBy string Field to sort by
|
||||
* @param $orderDirection string Direction to sort (Select::ORDER_ASCENDING || Select::ORDER_DESCENDING)
|
||||
*
|
||||
* @return null|array|\ArrayObject
|
||||
*/
|
||||
public function getManyByField(string $field, $value, int $limit = null, string $orderBy = null, string $orderDirection = Select::ORDER_ASCENDING): ?array
|
||||
{
|
||||
$select = $this->sql->select();
|
||||
|
||||
$select->where([$field => $value]);
|
||||
if ($orderBy) {
|
||||
if ($orderBy instanceof Expression) {
|
||||
$select->order($orderBy);
|
||||
} else {
|
||||
$select->order("{$orderBy} {$orderDirection}");
|
||||
}
|
||||
}
|
||||
|
||||
if ($limit) {
|
||||
$select->limit($limit);
|
||||
}
|
||||
|
||||
$resultSet = $this->selectWith($select);
|
||||
|
||||
$results = [];
|
||||
if (0 == $resultSet->count()) {
|
||||
return null;
|
||||
}
|
||||
for ($i = 0; $i < $resultSet->count(); ++$i) {
|
||||
$row = $resultSet->current();
|
||||
$results[] = $row;
|
||||
$resultSet->next();
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
public function countByField(string $field, $value): int
|
||||
{
|
||||
$select = $this->sql->select();
|
||||
$select->where([$field => $value]);
|
||||
$select->columns([
|
||||
new Expression('COUNT(*) as count'),
|
||||
]);
|
||||
$statement = $this->sql->prepareStatementForSqlObject($select);
|
||||
$result = $statement->execute();
|
||||
|
||||
$data = $result->current();
|
||||
|
||||
return $data['count'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null|array|\ArrayObject
|
||||
*/
|
||||
public function getByPrimaryKey(array $primaryKeys)
|
||||
{
|
||||
//\Kint::dump($primaryKeys);
|
||||
$row = $this->select($primaryKeys)->current();
|
||||
if (!$row) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $row;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get single matching object.
|
||||
*
|
||||
* @param array|\Closure|Predicate\PredicateInterface|string|Where $keyValue
|
||||
* @param null $orderBy
|
||||
* @param string $orderDirection
|
||||
*/
|
||||
public function getMatching($keyValue = [], $orderBy = null, $orderDirection = Select::ORDER_ASCENDING)
|
||||
{
|
||||
$select = $this->sql->select();
|
||||
$select->where($keyValue);
|
||||
if ($orderBy) {
|
||||
if ($orderBy instanceof Expression) {
|
||||
$select->order($orderBy);
|
||||
} else {
|
||||
$select->order("{$orderBy} {$orderDirection}");
|
||||
}
|
||||
}
|
||||
$select->limit(1);
|
||||
|
||||
$resultSet = $this->selectWith($select);
|
||||
|
||||
$row = $resultSet->current();
|
||||
if (!$row) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $row;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get many matching objects.
|
||||
*
|
||||
* @param array|\Closure|Predicate\PredicateInterface|string|Where $keyValue
|
||||
* @param null $orderBy
|
||||
* @param string $orderDirection
|
||||
* @param int $limit
|
||||
*
|
||||
* @return null|array|\ArrayObject
|
||||
*/
|
||||
public function getManyMatching($keyValue = [], $orderBy = null, $orderDirection = Select::ORDER_ASCENDING, int $limit = null): ?array
|
||||
{
|
||||
$select = $this->sql->select();
|
||||
$select->where($keyValue);
|
||||
if ($orderBy) {
|
||||
if ($orderBy instanceof Expression) {
|
||||
$select->order($orderBy);
|
||||
} else {
|
||||
$select->order("{$orderBy} {$orderDirection}");
|
||||
}
|
||||
}
|
||||
if ($limit) {
|
||||
$select->limit($limit);
|
||||
}
|
||||
$resultSet = $this->selectWith($select);
|
||||
|
||||
$results = [];
|
||||
if (0 == $resultSet->count()) {
|
||||
return null;
|
||||
}
|
||||
for ($i = 0; $i < $resultSet->count(); ++$i) {
|
||||
$row = $resultSet->current();
|
||||
$results[] = $row;
|
||||
$resultSet->next();
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Model
|
||||
*/
|
||||
public function getNewModelInstance(array $data = []): Model
|
||||
{
|
||||
$model = $this->model;
|
||||
|
||||
return new $model($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Model[]
|
||||
*/
|
||||
public function getBySelect(Select $select): array
|
||||
{
|
||||
$resultSet = $this->executeSelect($select);
|
||||
$return = [];
|
||||
foreach ($resultSet as $result) {
|
||||
$return[] = $result;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Model[]
|
||||
*/
|
||||
public function getBySelectRaw(Select $select): array
|
||||
{
|
||||
$resultSet = $this->executeSelect($select);
|
||||
$return = [];
|
||||
while ($result = $resultSet->getDataSource()->current()) {
|
||||
$return[] = $result;
|
||||
$resultSet->getDataSource()->next();
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
protected function getModelName(): string
|
||||
{
|
||||
$modelName = explode('\\', $this->model);
|
||||
$modelName = end($modelName);
|
||||
|
||||
return str_replace('Model', '', $modelName);
|
||||
}
|
||||
}
|
||||
|
|
@ -7,7 +7,7 @@ use {{ namespace }}\TableGateways;
|
|||
use {{ namespace }}\Services;
|
||||
use Psr\Container\ContainerExceptionInterface;
|
||||
use Psr\Container\NotFoundExceptionInterface;
|
||||
use ⌬\Controllers\Abstracts\Model as AbstractModel;
|
||||
use ⌬\Database\Abstracts\Model as AbstractModel;
|
||||
use ⌬\Database\Interfaces\ModelInterface as ModelInterface;
|
||||
use ⌬\⌬ as App;
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ use {{ namespace }}\Models;
|
|||
use {{ namespace }}\TableGateways;
|
||||
use Faker\Generator;
|
||||
use Laminas\Db\ResultSet\ResultSet;
|
||||
use ⌬\Controllers\Abstracts\Model;
|
||||
use ⌬\Controllers\Abstracts\TableGateway as AbstractTableGateway;
|
||||
use ⌬\Database\Abstracts\Model;
|
||||
use ⌬\Database\Abstracts\TableGateway as AbstractTableGateway;
|
||||
use ⌬\Database\Adapter;
|
||||
use ⌬\Database\Db;
|
||||
use ⌬\Database\Exception\Exception as DbException;
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use Laminas\Db\Sql\Expression;
|
|||
use Laminas\Db\Sql\Select;
|
||||
use Laminas\Db\Sql\Predicate;
|
||||
use Laminas\Db\Sql\Where;
|
||||
use ⌬\Controllers\Abstracts\Service as AbstractService;
|
||||
use ⌬\Database\Abstracts\Service as AbstractService;
|
||||
use ⌬\Database\Interfaces\ServiceInterface as ServiceInterface;
|
||||
|
||||
{% include '_overwrite_warning.twig' %}
|
||||
|
|
|
|||
Loading…
Reference in a new issue