267 lines
No EOL
8.9 KiB
PHP
267 lines
No EOL
8.9 KiB
PHP
<?php
|
||
|
||
require_once 'core/primitive.php';
|
||
|
||
/**
|
||
* Использовать интерфейсы чтобы определить какие действия можно совершать с обьектом и таким образом
|
||
* Строить набор действий Action и отображений View для обьекта
|
||
* Т.к отображение данных может быть не только на таблицу баз данных
|
||
* И возможно реализованны все интерфейсы
|
||
*/
|
||
interface IDataList
|
||
{
|
||
function findAll (Collection $request, $id = null);
|
||
function findById ($id);
|
||
function getCount (Collection $request, $id);
|
||
}
|
||
|
||
interface IDataSave
|
||
{
|
||
function saveTo ($o);
|
||
function updateTo ($o);
|
||
}
|
||
|
||
/**
|
||
* Отображение таблицы базы данных в обьекты
|
||
* Mapper -> DataMapper implements IDataList, IDataSave, IDataSort, IDataDelete ...
|
||
*
|
||
* @package core
|
||
*/
|
||
class DataMapper implements IDataList
|
||
{
|
||
/* Хранить метаданные в статическом свойстве класса для ототбражения ?!, + Скрипт для генерации метаданных!!
|
||
*/
|
||
public $factory;
|
||
public $className; /* Класс на который будет отображаться строчка таблицы */
|
||
public $filter = ""; /* */
|
||
public $schema = array (); /* Соответствие между свойством обьекта и столбцом, добавить тип для записей !! */
|
||
public $database; /* Таблица */
|
||
public $index; /* Индексный столбец */
|
||
public $db; /* Соединение с базой данных */
|
||
public $reference = array (null, null);
|
||
|
||
public function __construct ()
|
||
{
|
||
}
|
||
|
||
public function setRange ($stmt, $page, $size)
|
||
{
|
||
$stmt->setLimit ($size);
|
||
$stmt->setOffset (($page-1) * $size);
|
||
}
|
||
|
||
public function listSQL (array $list)
|
||
{
|
||
return implode ($list, ",");
|
||
}
|
||
|
||
/**
|
||
* Поиск строки в таблице по идентификатору
|
||
* @param $id Значение идентификатора
|
||
* @return Обьект класса $className
|
||
*/
|
||
public function findById ($id)
|
||
{
|
||
// Строки запроса преобразовать в методы (getSQLSelect ...)
|
||
// Query::from($this->database)->where ($this->index, "=", $id)->select();
|
||
$stmt = $this->db->prepareStatement ("SELECT * FROM ".$this->database." WHERE ".$this->index." = ?");
|
||
$stmt->setInt (1, $id);
|
||
$rs = $stmt->executeQuery ();
|
||
$rs->next ();
|
||
return $this->mapOne ($rs);
|
||
}
|
||
|
||
/**
|
||
* Преобразует parseResult в обьект
|
||
*/
|
||
public /* private */ function mapOne ($rs)
|
||
{
|
||
$result = new $this->className ();
|
||
foreach ($this->schema as $key => $value) {
|
||
list($value) = $value;
|
||
$result->$value->setRes($rs, $key);
|
||
}
|
||
return $result;
|
||
}
|
||
|
||
public /* private */ function mapAll ($rs)
|
||
{
|
||
$result = array ();
|
||
// Преобразование SQL в обьект
|
||
while ($rs->next ()) {
|
||
$result[] = $this->mapOne ($rs);
|
||
}
|
||
return $result;
|
||
}
|
||
|
||
private function clean ($value) {
|
||
return strtolower(trim(iconv('utf-8', 'cp1251', $value)));
|
||
}
|
||
|
||
/**
|
||
* Преобразует параметры формы в SQL запрос WHERE
|
||
* @param array $params
|
||
* @param array $schema
|
||
* @return string
|
||
*/
|
||
public function requestToSQL (Collection $request, array $schema)
|
||
{
|
||
$result = array ();
|
||
foreach ($schema as $key => $value) {
|
||
$param = $request->get ($key);
|
||
if ($param) {
|
||
array_push ($result, "lower (".$value.") LIKE '".$this->clean ($param)."%'");
|
||
}
|
||
}
|
||
if (empty ($result)) return null;
|
||
return implode ($result, " AND ");
|
||
}
|
||
|
||
/**
|
||
* Удаление строк из таблицы с заданными индексами
|
||
* @param $list array Массив идентефикаторов
|
||
*/
|
||
public function deleteList (array $list)
|
||
{
|
||
// Query::from($this->database)->where($this->index, "in", $list)->delete();
|
||
$sql = "DELETE FROM " . $this->database . " WHERE " . $this->index . " IN (" . $this->listSQL ($list) . ")";
|
||
return $this->db->executeQuery ($sql);
|
||
}
|
||
|
||
public static function findKey (array $schema, $sort)
|
||
{
|
||
foreach ($schema as $key => $item) {
|
||
list($item) = $item;
|
||
if ($item == $sort) {
|
||
return $key;
|
||
}
|
||
}
|
||
return $sort;
|
||
}
|
||
|
||
public function getOrder (Collection $request)
|
||
{
|
||
$order = "";
|
||
$sort = $request->get('key');
|
||
$desc = ($request->get('desc') == 0)? 'DESC' : 'ASC';
|
||
if ($sort) {
|
||
$sort = self::findKey ($this->schema, $sort);
|
||
$order = " ORDER BY $sort $desc";
|
||
}
|
||
return $order;
|
||
}
|
||
|
||
/**
|
||
* Извлекает список записей из базы данных
|
||
*/
|
||
public function findAll (Collection $request, $id = null)
|
||
{
|
||
$name0 = $this->database;
|
||
$foreign = $this->reference[1];
|
||
// Переписать используя Query !!!
|
||
if ($foreign && $id) {
|
||
$filter = ($this->filter)?$filter = " AND ".$this->filter: "";
|
||
$sql = "SELECT t1.* FROM $name0 as t1 WHERE t1.$foreign = $id " . $filter.self::getOrder($request);
|
||
} else {
|
||
$filter = ($this->filter)?$filter = " WHERE " . $this->filter: "";
|
||
$sql = "SELECT * FROM $name0 " . $filter . self::getOrder($request);
|
||
}
|
||
$stmt = $this->db->prepareStatement ($sql);
|
||
|
||
$page = $request->get('page');
|
||
$limit = $request->get('size');
|
||
if ($page && $limit) {
|
||
$this->setRange($stmt, $page, $limit);
|
||
}
|
||
|
||
return $this->mapAll($stmt->executeQuery());
|
||
}
|
||
|
||
public function getCount (Collection $request, $id)
|
||
{
|
||
$name0 = $this->database;
|
||
$foreign = $this->reference[1];
|
||
// Переписать используя Query !!!
|
||
if ($foreign && $id) {
|
||
$filter = ($this->filter)?$filter = " AND " . $this->filter: "";
|
||
$sql = "SELECT count(t1.*) as length FROM $name0 as t1 WHERE t1.$foreign = $id " . $filter;
|
||
} else {
|
||
$filter = ($this->filter)?$filter = " WHERE " . $this->filter: "";
|
||
$sql = "SELECT count(*) as length FROM $name0 " . $filter;
|
||
}
|
||
$rs = $this->db->executeQuery($sql);
|
||
$rs->next();
|
||
return $rs->getInt('length');
|
||
}
|
||
|
||
/**
|
||
* Добавление записи в базу данных
|
||
* @param $o Обьект для записи в базу данных
|
||
*/
|
||
public function saveTo (Model $o)
|
||
{
|
||
$keys = array ();
|
||
$values = array ();
|
||
foreach ($this->schema as $key => $value) {
|
||
list($value) = $value;
|
||
if ($key != $this->index) {
|
||
$keys[] = $key;
|
||
$values[] = "'".$o->$value."'";
|
||
}
|
||
}
|
||
$stmt = $this->db->prepareStatement ("INSERT INTO ".$this->database." (".implode ($keys, ",").") VALUES (".implode ($values, ",").")");
|
||
$stmt->executeQuery ();
|
||
}
|
||
|
||
/**
|
||
* Обновляет запись в базе данных
|
||
* @param $o Обьект для обновления
|
||
*/
|
||
public function updateTo (Model $o)
|
||
{
|
||
$keys_values = array ();
|
||
foreach ($this->schema as $key => $value) {
|
||
list($value) = $value;
|
||
if ($key != $this->index && !($o->$value instanceof FKey)) {
|
||
$keys_values[] = $key." = '".$o->$value."'";
|
||
}
|
||
}
|
||
// Для всех должен быть идентефикатор id
|
||
$stmt = $this->db->prepareStatement ("UPDATE ".$this->database." SET ".implode($keys_values, ",")." WHERE ".$this->index." = ".$o->id);
|
||
$stmt->executeQuery ();
|
||
}
|
||
|
||
function saveDB (Model $o)
|
||
{
|
||
if ($o->id) {
|
||
$this->updateTo($o);
|
||
} else {
|
||
$this->saveTo($o);
|
||
}
|
||
}
|
||
|
||
function getModel($name)
|
||
{
|
||
require_once 'core/Mapper/Factory.php';
|
||
if (!$this->factory) {
|
||
$this->factory = new ModelFactory($this->db);
|
||
}
|
||
return $this->factory->getModel($name);
|
||
}
|
||
}
|
||
|
||
/**
|
||
*
|
||
*/
|
||
class Model
|
||
{
|
||
public function __construct ()
|
||
{
|
||
foreach (get_class_vars (get_class ($this)) as $key => $value) {
|
||
$this->$key = new Primitive ();
|
||
}
|
||
}
|
||
// __get, __set методы. В метаданных хранится тип свойств, проверять при присваивании!!
|
||
}
|
||
|
||
?>
|