- Added a new MsSQL adapter

- Some bugfixes were made within annotations.
- Added a new Object Instanciator which allows to manipulate and define how an object from an entity must be instanciated with given value.
This commit is contained in:
Dave Mc Nicoll 2020-01-29 16:11:16 -05:00
parent 9df7e65dcf
commit 5bd60129ea
22 changed files with 547 additions and 103 deletions

View File

@ -7,4 +7,5 @@ use Ulmus\Common\PdoObject;
interface AdapterInterface {
public function connect() : PdoObject;
public function buildDataSourceName() : string;
public function setup(array $configuration) : void;
}

188
src/Adapter/MsSQL.php Normal file
View File

@ -0,0 +1,188 @@
<?php
namespace Ulmus\Adapter;
use Ulmus\Common\PdoObject;
use Ulmus\Exception\AdapterConfigurationException;
class MsSQL implements AdapterInterface {
public int $port;
public int $transactionIsolation;
public int $connectionPooling = 0;
public bool $encrypt;
public bool $multipleActiveResultSets;
public bool $traceOn;
public string $app;
public string $server;
public string $database;
public string $username;
public string $password;
public string $traceFile;
public string $failoverPartner;
public string $wsid;
public function __construct(
?string $server = null,
?string $database = null,
?string $username = null,
?string $password = null,
?int $port = null
) {
if ($server) {
$this->server = $server;
}
if ($database) {
$this->database = $database;
}
if ($port) {
$this->port = $port;
}
if ($username) {
$this->username = $username;
}
if ($password) {
$this->password = $password;
}
}
public function connect() : PdoObject
{
try {
$pdo = new PdoObject($this->buildDataSourceName(), $this->username, $this->password);
$pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_ASSOC);
$pdo->setAttribute(\PDO::SQLSRV_ATTR_ENCODING, \PDO::SQLSRV_ENCODING_UTF8);
}
catch(PDOException $ex){
throw $ex;
}
return $pdo;
}
public function buildDataSourceName() : string
{
$parts[] = "Server={$this->server}" . ( isset($this->port) ? ",{$this->port}" : "" );
$parts[] = "Database={$this->database}";
$parts[] = "ConnectionPooling={$this->connectionPooling}";
if ( $this->app ?? false ) {
$parts[] = "APP={$this->app}";
}
if ( $this->encrypt ?? false ) {
$parts[] = "Encrypt=1";
}
if ( $this->failoverPartner ?? false ) {
$parts[] = "Failover_Partner={$this->failoverPartner}";
}
if ( $this->loginTimeout ?? false ) {
$parts[] = "LoginTimeout={$this->loginTimeout}";
}
if ( $this->multipleActiveResultSets ?? false ) {
$parts[] = "MultipleActiveResultSets=1";
}
if ( $this->quotedId ?? false ) {
$parts[] = "QuotedId=1";
}
if ( $this->traceFile ?? false ) {
$parts[] = "TraceFile={$this->traceFile}";
}
if ( $this->traceOn ?? false ) {
$parts[] = "TraceOn=1";
}
if ( $this->transactionIsolation ?? false ) {
$parts[] = "TransactionIsolation={$this->transactionIsolation}";
}
if ( $this->trustServerCertificate ?? false ) {
$parts[] = "TrustServerCertificate=1";
}
if ( $this->WSID ?? false ) {
$parts[] = "WSID={$this->wsid}";
}
return "sqlsrv:" . implode(';', $parts);
}
public function setup(array $configuration) : void
{
$configuration = array_change_key_case($configuration, \CASE_LOWER);
if ( false === ( $this->server = $configuration['server'] ?? false ) ) {
throw new AdapterConfigurationException("Your `server` setting is missing. It is a mandatory parameter for this driver.");
}
elseif ( false === ( $this->database = $configuration['database'] ?? false ) ) {
throw new AdapterConfigurationException("Your `database` setting is missing. The adapter won't connect without it.");
}
elseif ( false === ( $this->username = $configuration['username'] ?? false ) ) {
throw new AdapterConfigurationException("Your `username` is missing from your configuration array");
}
elseif ( false === ( $this->password = $configuration['password'] ?? false ) ) {
throw new AdapterConfigurationException("Your `password` is missing from your configuration array");
}
if ( false !== ( $configuration['app'] ?? false ) ) {
$this->app = $configuration['app'];
}
if ( false !== ( $configuration['port'] ?? false ) ) {
$this->port = $configuration['port'];
}
if ( false !== ( $configuration['failover_partner'] ?? false ) ) {
$this->failoverPartner = $configuration['failover_partner'];
}
if ( false !== ( $configuration['wsid'] ?? false ) ) {
$this->wsid = $configuration['wsid'];
}
if ( false !== ( $configuration['transaction_isolation'] ?? false ) ) {
$this->transactionIsolation = $configuration['transaction_isolation'];
}
if ( false !== ( $configuration['connection_pooling'] ?? false ) ) {
$this->connectionPooling = $configuration['connection_pooling'];
}
if ( false !== ( $configuration['encrypt'] ?? false ) ) {
$this->encrypt = $configuration['encrypt'];
}
if ( false !== ( $configuration['multiple_active_result_sets'] ?? false ) ) {
$this->multipleActiveResultSets = $configuration['multiple_active_result_sets'];
}
if ( false !== ( $configuration['trace_on'] ?? false ) ) {
$this->traceOn = $configuration['trace_on'];
}
}
}

View File

@ -4,13 +4,22 @@ namespace Ulmus\Adapter;
use Ulmus\Common\PdoObject;
use Ulmus\Exception\AdapterConfigurationException;
class MySQL implements AdapterInterface {
public string $hostname;
public string $database;
public string $username;
public string $password;
public string $charset;
public string $unixSocket;
public int $port;
public function __construct(
@ -49,20 +58,34 @@ class MySQL implements AdapterInterface {
public function connect() : PdoObject
{
try {
$obj = new PdoObject($this->buildDataSourceName(), $this->username, $this->password);
$pdo = new PdoObject($this->buildDataSourceName(), $this->username, $this->password);
$pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
$pdo->setAttribute(\PDO::ATTR_AUTOCOMMIT, false);
$pdo->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_ASSOC);
$pdo->setAttribute(\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
}
catch(PDOException $ex){
throw $ex;
}
return $obj;
return $pdo;
}
public function buildDataSourceName() : string
{
$parts[] = "host={$this->hostname}";
if ( false !== ($this->unixSocket ?? false) ) {
}
else {
$parts[] = "host={$this->hostname}";
if ( false !== ( $this->port ?? false ) ) {
$parts[] = "port={$this->port}";
}
}
$parts[] = "dbname={$this->database}";
$parts[] = "port={$this->port}";
if ( $this->socket ?? false ) {
$parts[] = "socket={$this->socket}";
@ -74,4 +97,34 @@ class MySQL implements AdapterInterface {
return "mysql:" . implode(';', $parts);
}
public function setup(array $configuration) : void
{
$configuration = array_change_key_case($configuration, \CASE_LOWER);
# Either Unix Socket is used, or Host / Port
if ( false !== ( $this->unixSocket = $connection['unix_socket'] ?? false ) ) {
if ( false === ( $this->hostname = $connection['host'] ?? false ) ) {
throw new AdapterConfigurationException("Your `host` name is missing from your configuration array");
}
if ( false !== ( $configuration['port'] ?? false ) ) {
$this->port = $configuration['port'];
}
}
if ( false === ( $this->database = $connection['database'] ?? false ) ) {
throw new AdapterConfigurationException("Your `database` name is missing from your configuration array");
}
elseif ( false === ( $this->username = $connection['username'] ?? false ) ) {
throw new AdapterConfigurationException("Your `username` is missing from your configuration array");
}
elseif ( false === ( $this->password = $connection['password'] ?? false ) ) {
throw new AdapterConfigurationException("Your `password` is missing from your configuration array");
}
if ( false !== ( $configuration['charset'] ?? false ) ) {
$this->charset = $configuration['charset'];
}
}
}

View File

@ -58,7 +58,7 @@ class AnnotationReader
try {
$tags[] = [
'tag' => substr($line, 0, $open - 1),
'arguments' => eval("namespace $namespace; return [ $arguments ];"),
'arguments' => eval("namespace $namespace; return [ $arguments ];" ),
];
}
catch(\Throwable $error) {

View File

@ -6,6 +6,8 @@ class Table implements \Ulmus\Annotation\Annotation {
public string $name;
public string $schema;
public function __construct($name = null)
{
if ( $name !== null ) {

View File

@ -16,16 +16,14 @@ class Field implements \Ulmus\Annotation\Annotation {
public bool $nullable = false;
public function __construct(string $type = null, int $length = null)
public function __construct(? string $type = null, ? int $length = null)
{
switch(true) {
case $type !== null:
$this->type = $type;
break;
case $length !== null:
$this->length = $length;
break;
if ( $type !== null ) {
$this->type = $type;
}
if ( $length !== null ) {
$this->length = $length;
}
}
}

View File

@ -9,15 +9,13 @@ class OrderBy implements \Ulmus\Annotation\Annotation {
public string $order = "ASC";
public function __construct(string $field = null, string $order = null)
{
switch(true) {
case $field !== null:
$this->field = $field;
break;
case $order !== null:
$this->order = $order;
break;
{
if ( $field !== null ) {
$this->field = $field;
}
if ( $order !== null ) {
$this->order = $order;
}
}
}

View File

@ -17,13 +17,19 @@ class Relation implements \Ulmus\Annotation\Annotation {
public string $bridgeKey;
public string $bridgeForeignKey;
public string $entity;
public function __construct(string $type = null)
{
switch(true) {
case $type !== null:
$this->type = $type;
break;
if ( $type !== null ) {
$this->type = $type;
}
}
public function entity() {
$e = $this->entity;
return new $e();
}
}

View File

@ -2,14 +2,31 @@
namespace Ulmus\Annotation\Property;
use Ulmus\Query;
class Where implements \Ulmus\Annotation\Annotation {
public array $comparisons = [];
public function __construct(...$comparisons)
public string $field;
public $value;
public string $operator;
public function __construct(? string $field = null, $value = null, ? string $operator = null)
{
if ( $comparisons ) {
$this->comparisons = $comparisons;
if ( $field !== null ) {
$this->field = $field;
}
if ( $value !== null ) {
$this->value = $value;
}
if ( $operator !== null ) {
$this->operator = $operator;
}
else {
$this->operator = Query\Where::OPERATOR_EQUAL;
}
}
}

View File

@ -27,7 +27,7 @@ class EntityField
# Must use REFLECTION before throwing this value.
# Should first check if it's a relation field, and if it is,
# it's real key must be returned (PK usually)
return $useAlias ? "{$this->alias}.`{$this->name}`" : $this->name;
return $useAlias ? "{$this->alias}.\"{$this->name}\"" : "\"{$this->name}\"";
}
public static function isScalarType($type) : bool
@ -46,7 +46,8 @@ class EntityField
public static function isObjectType($type) : bool
{
return strpos($type, "\\") !== false;
# @ Should be fixed with isBuiltIn() instead, it won't be correct based only on name
# return strpos($type, "\\") !== false;
}
public function __toString() : string

View File

@ -4,7 +4,8 @@ namespace Ulmus\Common;
use Ulmus\Annotation\Annotation,
Ulmus\Annotation\Classes\Table,
Ulmus\Annotation\Property\Field;
Ulmus\Annotation\Property\Field,
Ulmus\Annotation\Property\Relation;
class EntityResolver {
@ -78,6 +79,49 @@ class EntityResolver {
return $fieldList;
}
public function relation(string $name) : ? array
{
try{
if ( null !== ( $this->properties[$name] ?? null ) ) {
foreach($this->properties[$name]['tags'] ?? [] as $tag) {
if ( $tag['object'] instanceof Relation ) {
return $this->properties[$name];
}
}
}
return [];
}
catch(\Throwable $e) {
if ( $throwException) {
throw new \InvalidArgumentException("Can't find entity relation's column named `$name` from entity {$this->entityClass}");
}
}
return null;
}
public function searchFieldAnnotation(string $field, Annotation $annotationType) : ? Annotation
{
$found = $this->searchFieldAnnotationList($field, $annotationType);
return $found ? $found[0] : null;
}
public function searchFieldAnnotationList(string $field, Annotation $annotationType) : array
{
$list = [];
if ( null !== ( $this->properties[$field] ?? null ) ) {
foreach($this->properties[$field]['tags'] ?? [] as $tag) {
if ( $tag['object'] instanceof $annotationType ) {
$list[] = $tag['object'];
}
}
}
return $list;
}
public function tableName() : string
{
if ( null === $table = $this->getAnnotationFromClassname( Table::class ) ) {
@ -91,6 +135,19 @@ class EntityResolver {
return $table->name;
}
public function schemaName() : ? string
{
if ( null === $table = $this->getAnnotationFromClassname( Table::class ) ) {
throw new \LogicException("Your entity {$this->entityClass} seems to be missing a @Table() annotation");
}
if ( $table->name === "" ) {
throw new \ArgumentCountError("Your entity {$this->entityClass} seems to be missing a `schema` argument for your @Table() annotation");
}
return $table->schema ?? null;
}
public function primaryKeys() : array
{

View File

@ -100,6 +100,7 @@ class ObjectReflection {
if ( $property->hasType() ) {
$current['type'] = $property->getType()->getName();
$current['builtin'] = $property->getType()->isBuiltIn();
$current['nullable'] = $property->getType()->allowsNull();
}

View File

@ -8,10 +8,13 @@ class PdoObject extends PDO {
public function select(string $sql, array $parameters = []) : PDOStatement
{
#dump($sql, $parameters);
try {
if ( false !== ( $statement = $this->prepare($sql) ) ) {
$statement = $this->execute($statement, $parameters, true);
$statement = $this->execute($statement, $parameters, false);
$statement->setFetchMode(\PDO::FETCH_ASSOC);
return $statement;
}
} catch (\PDOException $e) { throw $e; }
@ -19,7 +22,6 @@ class PdoObject extends PDO {
public function runQuery(string $sql, array $parameters = []) : PDOStatement
{
# var_dump($sql, $parameters);die();
try {
if ( false !== ( $statement = $this->prepare($sql) ) ) {
return $this->execute($statement, $parameters, true);
@ -35,9 +37,9 @@ class PdoObject extends PDO {
}
if ( empty($parameters) ? $statement->execute() : $statement->execute($parameters) ) {
# if ( $commit ) {
if ( $commit ) {
$this->commit();
# }
}
return $statement;
}

View File

@ -19,6 +19,7 @@ class ConnectionAdapter
public function __construct(string $name = "default", array $configuration = [])
{
$this->name = $name;
$this->configuration = $configuration;
if ( $name === "default" ) {
@ -26,62 +27,45 @@ class ConnectionAdapter
}
}
public function resolveConfiguration()
public function resolveConfiguration() : void
{
$connection = $this->configuration['connections'][$this->name] ?? [];
if ( $adapterName = $connection['adapter'] ?? false ) {
if ( false !== ( $adapterName = $connection['adapter'] ?? false ) ) {
$this->adapter = $this->instanciateAdapter($adapterName);
}
else {
throw new \InvalidArgumentException("Adapter not found within your configuration array.");
}
if ( false === $this->adapter->hostname = $connection['host'] ?? false ) {
throw new \InvalidArgumentException("Your `host` name is missing from your configuration array");
}
if ( false === $this->adapter->port = $connection['port'] ?? false ) {
throw new \InvalidArgumentException("Your `port` number is missing from your configuration array");
}
if ( false === $this->adapter->database = $connection['database'] ?? false ) {
throw new \InvalidArgumentException("Your `database` name is missing from your configuration array");
}
if ( false === $this->adapter->username = $connection['username'] ?? false ) {
throw new \InvalidArgumentException("Your `username` is missing from your configuration array");
}
if ( false === $this->adapter->password = $connection['password'] ?? false ) {
throw new \InvalidArgumentException("Your `password` is missing from your configuration array");
}
$this->adapter->setup($connection);
}
/**
* Connect the adapter
* @return self
*/
public function connect()
public function connect() : self
{
$this->pdo = $this->adapter->connect();
$this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
$this->pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
$this->pdo->setAttribute(\PDO::ATTR_AUTOCOMMIT, false);
$this->pdo->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_ASSOC);
$this->pdo->setAttribute(\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
return $this;
}
public function adapter() : AdapterInterface
{
return $this->adapter;
}
/**
* Instanciate an adapter which interact with the data source
* @param string $name An Ulmus adapter or full class name implementing AdapterInterface
* @return AdapterInterface
*/
protected function instanciateAdapter($name)
protected function instanciateAdapter($name) : AdapterInterface
{
$class = substr($name, 0, 2) === "\\" ? $name : "\\Ulmus\\Adapter\\$name";
return new $class();
}
}

View File

@ -0,0 +1,33 @@
<?php
namespace Ulmus\Entity;
class ObjectInstanciator {
protected array $objectCallbackDefinition;
public function instanciate(string $type, array $arguments) : object
{
if ( isset($this->objectCallbackDefinition[$type]) ) {
return $this->objectCallbackDefinition[$type](...$arguments);
}
else {
return new $type(...$arguments);
}
}
public function registerObject(string $type, Callable $callback) : void
{
$this->objectCallbackDefinition[$type] = $callback;
}
public function unregisterObject(string $type) : void
{
unset($this->objectCallbackDefinition[$type]);
}
public function isObjectRegistered(string $type) : bool
{
return isset($this->objectCallbackDefinition[$type]);
}
}

View File

@ -4,9 +4,7 @@ namespace Ulmus;
use Generator;
#class EntityCollection implements \Countable, \ArrayAccess
class EntityCollection extends \ArrayObject {
# use Common\ArrayObjectTrait;
public function filters(Callable $callback) : Generator
{
@ -20,4 +18,15 @@ class EntityCollection extends \ArrayObject {
}
}
}
public function buildArray(string $keyColumn, string $valueColumn) : array
{
$list = [];
foreach($this as $key => $item) {
$list[$item->$keyColumn] = $item->$valueColumn;
}
return $list;
}
}

View File

@ -12,16 +12,73 @@ use Ulmus\Annotation\Property\Field\{ Id, ForeignKey, CreatedAt, UpdatedAt, };
trait EntityTrait {
/**
* @Ignore
*/
protected bool $strictEntityFieldsDeclaration = true;
/**
* @Ignore
*/
protected array $unmatchedEntityDatasetFields = [];
/**
* @Ignore
*/
public function __get(string $name)
{
$entityResolver= $this->resolveEntity();
# Resolve relations here if one is called
if ( null !== ( $relation = $entityResolver->searchFieldAnnotation($name, new Relation() ) ) ) {
$order = $entityResolver->searchFieldAnnotationList($name, new OrderBy() );
$where = $entityResolver->searchFieldAnnotationList($name, new Where() );
$baseEntity = $relation->entity();
$repository = $baseEntity->repository();
foreach($where as $condition) {
$repository->where($condition->field, $condition->value, $condition->operator);
}
foreach($order as $item) {
$repository->orderBy($item->field, $item->order);
}
$field = $relation->key;
if ( method_exists($this, $filterMethod = "filterRelation$name") ) {
$this->$filterMethod($repository);
}
switch($relation->type) {
case 'oneToMany':
$repository->where( $baseEntity->field($relation->foreignKey), 866); # <<<<<<<<< CHANGE $THIS->ID WITH PROPER NOMENCLATURE
return $this->$name = $repository->loadAll();
case 'oneToOne':
$repository->where( $baseEntity->field($relation->foreignKey), $this->$field );
$result = $repository->loadAll();
if ( count($result) === 0 ) {
return $baseEntity;
}
return $this->$name = $result[0];
}
return;
}
}
/**
* @Ignore
*/
public function entityFillFromDataset($dataset) : self
{
$fields = Ulmus::resolveEntity(static::class);
$fields = $this->resolveEntity();
foreach($dataset as $key => $value) {
$key = strtolower($key);
@ -43,20 +100,28 @@ trait EntityTrait {
elseif ( EntityField::isScalarType($field['type']) ) {
$this->{$field['name']} = $value;
}
elseif ( EntityField::isObjectType($field['type']) ) {
$this->{$field['name']} = new $field['type']();
elseif ( ! $field['builtin'] ) {
$this->{$field['name']} = Ulmus::instanciateObject($field['type'], [ $value ]);
}
}
return $this;
}
/**
* @Ignore
*/
public function resolveEntity() : EntityResolver
{
return Ulmus::resolveEntity(static::class);
}
/**
* @Ignore
*/
public static function repository() : Repository
public static function repository(string $alias = Repository::DEFAULT_ALIAS) : Repository
{
return Ulmus::repository(static::class);
return Ulmus::repository(static::class, $alias, Ulmus::$defaultAdapter);
}
/**

View File

@ -0,0 +1,5 @@
<?php
namespace Ulmus\Exception;
class AdapterConfigurationException extends \Exception {}

View File

@ -2,12 +2,21 @@
namespace Ulmus\Query;
use Ulmus\QueryBuilder;
class From extends Fragment {
public int $order = -80;
protected $tables = [];
public QueryBuilder $queryBuilder;
public function __construct(QueryBuilder $queryBuilder)
{
$this->queryBuilder = $queryBuilder;
}
public function set(array $tables) : self
{
$this->tables = $tables;
@ -35,7 +44,7 @@ class From extends Fragment {
$list = [];
foreach((array) $this->tables as $alias => $table) {
$list[] = ! is_numeric($alias) ? "`$table` $alias" : "`$table`";
$list[] = ! is_numeric($alias) ? "$table $alias" : $table;
}
return implode(", ", $list);

View File

@ -2,10 +2,8 @@
namespace Ulmus;
class QueryBuilder
{
public Query\Where $where;
/**
@ -14,20 +12,14 @@ class QueryBuilder
public array $parameters = [];
public string $conditionOperator = Query\Where::CONDITION_AND;
public string $entityClass;
protected int $parameterIndex = 0;
protected array $queryStack = [];
public function __construct($entityClass = "") {
$this->entityClass = $entityClass;
}
public function select($field) : self
{
if ( $select = $this->has(Query\Select::class) ) {
if ( false !== ( $select = $this->has(Query\Select::class) ) ) {
$select->add($field);
}
else {
@ -52,17 +44,23 @@ class QueryBuilder
return $this;
}
public function from($table, $alias = null, $database = null) : self
public function from(string $table, ? string $alias = null, ? string $database = null, ? string $schema = null) : self
{
$table = "\"$table\"";
if ( $database ) {
$table = "`$database`.".$table;
$table = "\"$database\".$table";
}
if ( $schema ) {
$table = "\"$schema\".$table";
}
if ( $from = $this->has(Query\From::class) ) {
if ( false !== ( $from = $this->has(Query\From::class) ) ) {
$from->add($alias ? [ $alias => $table ] : $table);
}
else {
$from = new Query\From();
$from = new Query\From($this);
$this->push($from);
$from->set($alias ? [ $alias => $table ] : $table);
}
@ -94,7 +92,7 @@ class QueryBuilder
if ( $this->where ?? false ) {
$where = $this->where;
}
elseif ( false === $where = $this->has(Query\Where::class) ) {
elseif ( false === ( $where = $this->has(Query\Where::class) ) ) {
$this->where = $where = new Query\Where($this);
$this->push($where);
}

View File

@ -22,7 +22,7 @@ class Repository
$this->entityClass = $entity;
$this->alias = $alias;
$this->adapter = $adapter;
$this->queryBuilder = new QueryBuilder();
$this->queryBuilder = new QueryBuilder( $adapter->adapter() );
$this->entityResolver = Ulmus::resolveEntity($entity);
}
@ -38,7 +38,6 @@ class Repository
public function loadFromPk($value, $primaryKey = "id") : EntityCollection
{
# var_dump("<pre>", $primaryKey);die();
return $this->where($primaryKey, $value)->loadOne();
}
@ -70,21 +69,21 @@ class Repository
public function select($fields) : self
{
$this->queryBuilder->select($fields);
return $this;
}
public function delete() : self
{
$this->queryBuilder->delete($this->alias);
return $this;
}
public function from($table) : self
public function from(string $table, string $alias, ? string $schema) : self
{
foreach((array) $table as $alias => $table) {
$this->queryBuilder->from($table, is_numeric($alias) ? null : $alias);
}
$this->queryBuilder->from($table, $alias, null, $schema);
return $this;
}
@ -96,6 +95,7 @@ class Repository
public function open(string $condition = Query\Where::CONDITION_AND) : self
{
$this->queryBuilder->open($condition);
return $this;
}
@ -107,12 +107,14 @@ class Repository
public function close() : self
{
$this->queryBuilder->close();
return $this;
}
public function where($field, $value, string $operator = Query\Where::OPERATOR_EQUAL) : self
{
$this->queryBuilder->where($field, $value, $operator, Query\Where::CONDITION_AND);
return $this;
}
@ -124,18 +126,21 @@ class Repository
public function or($field, $value, string $operator = Query\Where::OPERATOR_EQUAL) : self
{
$this->queryBuilder->where($field, $value, $operator, Query\Where::CONDITION_OR);
return $this;
}
public function notWhere(array $condition) : self
{
$this->queryBuilder->where($field, $value, $operator, Query\Where::CONDITION_AND, true);
return $this;
}
public function orNot($field, $value, string $operator = Query\Where::OPERATOR_EQUAL) : self
{
$this->queryBuilder->notWhere($condition, Query\Where::CONDITION_OR, true);
return $this;
}
@ -152,18 +157,21 @@ class Repository
public function in($field, $value, string $operator = Query\Where::OPERATOR_EQUAL) : self
{
$this->queryBuilder->where($field, $value, $operator);
return $this;
}
public function orIn($field, $value, string $operator = Query\Where::OPERATOR_EQUAL) : self
{
$this->queryBuilder->where($field, $value, $operator, Query\Where::CONDITION_OR);
return $this;
}
public function notIn($field, $value) : self
{
$this->queryBuilder->where($field, $value, Query\Where::OPERATOR_NOT_EQUAL);
return $this;
}
@ -175,12 +183,14 @@ class Repository
public function like($field, $value) : self
{
$this->queryBuilder->where($field, $value, Query\Where::OPERATOR_LIKE, Query\Where::CONDITION_AND);
return $this;
}
public function notLike($field, $value) : self
{
$this->queryBuilder->where($field, $value, Query\Where::OPERATOR_LIKE, Query\Where::CONDITION_AND, true);
return $this;
}
@ -263,7 +273,7 @@ class Repository
}
if ( ! $this->queryBuilder->has(Query\From::class) ) {
$this->from([ $this->alias => $this->entityResolver->tableName() ]);
$this->from($this->entityResolver->tableName(), $this->alias, $this->entityResolver->schemaName());
}
return $this;
@ -276,7 +286,7 @@ class Repository
}
if ( ! $this->queryBuilder->has(Query\From::class) ) {
$this->from([ $this->alias => $this->entityResolver->tableName() ]);
$this->from($this->entityResolver->tableName(), $this->alias, $this->entityResolver->schemaName());
}
return $this;

View File

@ -12,6 +12,8 @@ abstract class Ulmus
public static ConnectionAdapter $defaultAdapter;
public static Entity\ObjectInstanciator $objectInstanciator;
public static array $resolved = [];
public static function iterateQueryBuilder(QueryBuilder $queryBuilder, ?ConnectionAdapter $adapter = null) : Generator
@ -50,6 +52,11 @@ abstract class Ulmus
return new static::$queryBuilderClass(...$arguments);
}
public static function instanciateObject(string $type, array $arguments) : object
{
return ( static::$objectInstanciator ?? static::$objectInstanciator = new Entity\ObjectInstanciator() )->instanciate($type, $arguments);
}
protected static function fetchQueryBuilder(QueryBuilder $queryBuilder, ?ConnectionAdapter $adapter = null) : array
{
return ( $adapter ?: static::$defaultAdapter )->pdo->select($queryBuilder->render(), $queryBuilder->parameters ?? [])->fetchAll();