Этот коммит содержится в:
Igor V Belousov 2019-11-08 00:10:57 +03:00
родитель 549fd7eaa2
Коммит 145d30bf40

Просмотреть файл

@ -2,10 +2,11 @@
namespace MyApp\Core; namespace MyApp\Core;
use PDOException;
use ReflectionClass; use ReflectionClass;
use ReflectionProperty; use ReflectionProperty;
use PDO; use PDO;
use PDOException;
use Exception;
class Model class Model
{ {
@ -23,8 +24,10 @@ class Model
global $app; global $app;
$this->app = $app; $this->app = $app;
if ( ! is_array($tableMap)) { if (!is_array($tableMap)) {
$this->setInternalTableMap(); $this->setInternalTableMap();
} else {
$this->internalTableMap = $tableMap;
} }
if ('db' === $this->getModelType()) { if ('db' === $this->getModelType()) {
@ -32,27 +35,27 @@ class Model
} }
} }
/**
* Create PDO Object.
*
* @throws PDOException
*/
private function initDb(): void private function initDb(): void
{ {
if (is_null($this->app->db)) { if (is_null($this->app->db)) {
try { $this->app->db = new PDO(
$this->app->db = new PDO( 'mysql:host=mysql;dbname='
'mysql:host=mysql;dbname=' .$this->app->config->getDbName()
. $this->app->config->getDbName() .';port='
. ';port=' .$this->app->config->getDbPort(),
. $this->app->config->getDbPort(), $this->app->config->getDbUser(),
$this->app->config->getDbUser(), $this->app->config->getDbPassword(),
$this->app->config->getDbPassword(), array(
array( PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES UTF8',
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES UTF8', PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_OBJ,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_OBJ, PDO::ATTR_ERRMODE => true,
PDO::ATTR_ERRMODE => true, PDO::ATTR_PERSISTENT => true,
PDO::ATTR_PERSISTENT => true, ));
));
} catch (PDOException $e) {
echo 'Подключение не удалось: ' . $e->getMessage();
}
} }
} }
@ -64,7 +67,7 @@ class Model
$tableMap = ['type' => 'db']; $tableMap = ['type' => 'db'];
$refClass = new ReflectionClass(get_called_class()); $refClass = new ReflectionClass(get_called_class());
$tags = $app->parseTagsFromComment($refClass->getDocComment(), $tags = $app->parseTagsFromComment($refClass->getDocComment(),
'TableName'); 'TableName');
if ($tags) { if ($tags) {
if (array_key_exists('TableName', $tags)) { if (array_key_exists('TableName', $tags)) {
@ -93,17 +96,136 @@ class Model
$this->internalTableMap = array_key_exists('id', $this->internalTableMap = array_key_exists('id',
$tableMap) ? $tableMap : ['type' => 'other']; $tableMap) ? $tableMap : ['type' => 'other'];
} }
if ( ! is_array($this->internalTableMap)) { if (!is_array($this->internalTableMap)) {
$this->internalTableMap = ['type' => 'other']; $this->internalTableMap = ['type' => 'other'];
} }
} }
public static function find() /**
{ * Find records from table.
} *
* @param int[]|null $records An array of records to search
* @param string|null $column Column name for search. Default ColumnOption 'id'
* @param string|null $where Selecting results from the table
* by condition. Use property name of object
* Example "{groups} = :groups_id AND {groups} IS NULL"
* @param array $bind Array of a values for bindParam. Work if
* $where not null.
* Example [ ":groups_id" => 0 ]
* @param string $order
* @param string $limit
* @param string $mode Mode of select records. 'in' or 'like'.
* Default is 'in'.
*
* @return array|null
*
* @throws Exception
*/
public static function find(
array $records = null,
string $column = null,
string $where = null,
array $bind = [],
string $order = '',
string $limit = '',
string $mode = 'in'
): ?array {
$model_name = get_called_class();
/* @var Model $model */
$model = new $model_name();
public static function findOne() $internal_table_map = $model->internalTableMap;
{ if ('db' === $internal_table_map['type']) {
$select_fields = '`'.implode('`,`',
array_values($internal_table_map['fields'])).'`';
$order_sql = '';
if (!empty($order)) {
$order_sql = "ORDER BY $order";
}
$limit_sql = '';
if (!empty($limit)) {
$limit_sql = "LIMIT $limit ";
}
$where_sql = '';
$mode_sql = '';
if (is_null($where)) {
if (is_null($records) || !count($records)) {
throw new Exception('$records unspecified.');
}
if (is_null($column)) {
$column_name = "`{$internal_table_map['id']}`";
} else {
if (!array_key_exists($column,
$internal_table_map['fields'])) {
throw new Exception('$column not find in model');
}
$column_name = "`{$internal_table_map['fields'][$column]}`";
}
if ('in' === $mode) {
$mode_sql = $column_name.' IN (:mode_param_'.implode(',:mode_param_',
array_keys($records)).') ';
}
if ('like' === $mode) {
$mode_sql = "{$column_name} LIKE :mode_param_".implode(" OR {$column_name} LIKE :mode_param_",
array_keys($records));
}
if (empty($mode_sql)) {
throw new Exception('Bad $mode');
}
$query = $model->app->db->prepare("SELECT $select_fields FROM `{$internal_table_map['name']}` WHERE $mode_sql $order_sql $limit_sql;");
} else {
$query = $model->app->db->prepare("SELECT $select_fields FROM `{$internal_table_map['name']}` ;");
}
$num = 0;
$params = [];
if (!empty($mode_sql) && 'in' === $mode) {
foreach ($records as $key => $variable) {
$params[$num] = $variable;
$query->bindParam(':mode_param_'.$key, $params[$num]);
++$num;
}
}
if (!empty($mode_sql) && 'like' === $mode) {
foreach ($records as $key => $variable) {
$params[$num] = "%{$variable}%";
$query->bindParam(':mode_param_'.$key, $params[$num]);
++$num;
}
}
$query->execute();
$data = $query->fetchAll(PDO::FETCH_ASSOC);
if (!empty($data)) {
$out = [];
foreach ($data as $data_single) {
$out_model = new $model_name($internal_table_map);
(function () use ($data_single, $internal_table_map) {
foreach ($internal_table_map['fields'] as $name => $db_field) {
$this->{$name} = $data_single[$db_field];
}
})->call($out_model);
$out[] = $out_model;
}
unset($model);
return $out;
}
}
unset($model);
return null;
} }
/** /**