wikipoints/ground/classes/Model.php

315 lines
8.5 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/*
Пример работы:
class User extends Model
{
function __construct($fromArray = array())
{
$this->_tableName_ = 'Users';
parent::__construct($fromArray);
}
static function model()
{
return new self();
}
}
Просто новый пользователь:
new User();
Новый пользователь из массива данных:
new User(array('ID'=>12, 'Name'=>'John', 'Fname'=>'Doe'));
Берём пользователя по ID:
User::model()->getByPK(2);
Всех пользователей:
User::model()->getAll()
Или всех пользователей с параметрами:
User::model()->getAll(array('where'=>'`ID` > 5', 'order'=>'`Name` ASC'))
*/
abstract class Model
{
// Relations
const TO_ONE = 'TO_ONE';
const TO_MANY = 'TO_MANY';
private $_primaryKey_;
protected $_tableName_;
private $_id_;
private $_vals_ = array();
protected $_relations_ = array();
function __construct($fromArray = array())
{
$this->_primaryKey_ = $this->getPk();
if ($fromArray)
{
$this->setValues($fromArray);
}
}
/**
* TODO: Проверять, есть ли такие поля в БД.
* @param type $name
* @param type $value
*/
function __set($name, $value)
{
$this->_vals_[$name] = $value;
if ($name == $this->_primaryKey_)
{
$this->_id_ = $value;
}
}
function __get($name)
{
if (isset($this->_vals_[$name]))
{
return $this->_vals_[$name];
} else
{
if (isset($this->_relations_[$name]))
{
extract($this->_relations_[$name]);
$model = new $targetModel;
switch ($relationType)
{
case self::TO_ONE:
return $model::model()->getOne($targetField, $this->$localField);
break;
case self::TO_MANY:
return $model::model()->getAll(array('where' => "`$targetField` = '" . $this->$localField . "'"));
break;
default:
throw new Exception('Undefined relation type');
break;
}
}
}
return null;
}
/**
* Получаем Primary Key
* @return type
*/
private function getPk()
{
$res = App::DB()->query("SHOW KEYS FROM " . $this->_tableName_ . " WHERE Key_name = 'PRIMARY'")->fetch(PDO::FETCH_ASSOC);
return $res["Column_name"];
}
/**
* Устанавливает отношение с другой таблицей
* @param string $nameOfRelation - название отношения. В дальнейшем по этому имени будт происходить обращение.
* @param string $localField - локальные данные по которым происходит связывание.
* @param string $targetModel - имя внешней модели (с которой хотим связаться).
* @param string $targetField - имя поля в удалённой таблице.
* @param const $relationType - тип связи (к одному / ко многим).
* @return obkect/array
*/
public function setRelation($nameOfRelation, $localField, $targetModel, $targetField, $relationType)
{
return $this->_relations_[$nameOfRelation] = array(
'localField' => $localField,
'targetModel' => $targetModel,
'targetField' => $targetField,
'relationType' => $relationType,
);
}
/**
* Возвращает объект - запись в БД.
* @param int $id
* @return \Model
*/
function getByPK($id)
{
$this->_vals_ = App::DB()->query('SELECT * FROM ' . $this->_tableName_ . ' WHERE ' . $this->_primaryKey_ . ' = ' . $id)->fetch(PDO::FETCH_ASSOC);
$this->_id_ = $this->_vals_[$this->_primaryKey_];
return $this;
}
/**
* Возвращает массив с объектами, соответствующими записями в БД.
* @param array $params ['where'] просто строка с условиями: (`id` > 1) AND (`name` == 'TEST'); ['order'] строка с именем толбца и напрабления: `summ` DESC
* @return array с объектами
*/
function getAll($params = array())
{
$sql = 'SELECT * FROM `' . $this->_tableName_ . '`';
$sql .= isset($params['where'])&&$params['where'] ? ' WHERE ' . $params['where'] : '';
$sql .= isset($params['order'])&&$params['order'] ? ' ORDER BY ' . $params['order'] : '';
$sql .= isset($params['limit'])&&$params['limit'] ? ' LIMIT ' . $params['limit'] : '';
$res = App::DB()->query($sql);
$ready = array();
$calledClass = get_called_class();
while ($res && $row = $res->fetch(PDO::FETCH_ASSOC))
{
$ready[$row[$this->_primaryKey_]] = isset($params['asArray'])&&$params['asArray'] ? $row : new $calledClass($row);
}
return (isset($params['limit'])&&$params['limit']==1) ? array_shift($ready) : $ready;
}
/**
* Возвращает один элемент, соотбетствующий параметрам
* @param string $whereField - имя поля по которому производим поиск
* @param type $whereValue - искомое значение
* @return type
*/
function getOne($whereField, $whereValue)
{
return $this->getAll(array(
'where' => '`' . $whereField . '` = "' . $whereValue . '"',
'limit' => 1
));
}
/**
* Удаляет запись из БД.
* @param int $id
* @return boolean
*/
function delete($id)
{
return $id ? App::DB()->query('DELETE FROM `' . $this->_tableName_ . '` WHERE `' . $this->_primaryKey_ . '` = ' . $id) : false;
}
/**
* Добавляет новую запись в БД.
* @param array $values - ассоциативный массив соо значениями.
* @return object - id добавленной записи или false.
*/
function add2($values)
{
$values = $this->_vals_;
unset($values[$this->_primaryKey_]);
$q = array();
foreach ($values as $val)
{
$q[] = '?';
}
var_dump('INSERT INTO `' . $this->_tableName_ . '` (`' . implode('`, `', array_keys($values)) . '`) VALUES (' . implode(', ', array_values($q)) . ') ');die;
$res = App::DB()->prepare_query('INSERT INTO `' . $this->_tableName_ . '` (`' . implode('`, `', array_keys($values)) . '`) VALUES (' . implode(', ', array_values($q)) . ') ', self::arrayWithTypes($values));
if ($res)
{
throw new Exception('MySQL error #' . $res->errno . ' - ' . $res->error);
}
return $this->getByPK(App::DB()->insert_id);
}
function add($values)
{
$request = App::DB()->prepare('INSERT INTO ' . $this->_tableName_ . ' (' . implode(',', array_keys($values)) . ') values (:' . implode(', :', array_keys($values)) . ')');
if ( $request->execute((array) $values) )
{
return $this->getByPK(App::DB()->lastInsertId());
}
else
{
return false;
}
}
/**
* Устанавливает значения полей из массива. Нужно проверять, есть ли такие поля в таблице.
* @param array $values - ассоциативный массив со значениями.
*/
function setValues($values)
{
if (isset($values[$this->_primaryKey_]))
{
$this->_id_ = $values[$this->_primaryKey_];
}
$this->_vals_ = $values;
}
/**
* Сохраняет объект в БД.
* @return object/boolean
*/
function save2()
{
if (!$this->_id_ || !$this->_vals_)
{
if ($this->_vals_)
{
return $this->add($this->_vals_);
}
else
{
return FALSE;
}
}
$values = $this->_vals_;
unset($values[$this->_primaryKey_]);
$keys = array_keys($values);
$values = array_values($values);
$values[] = $this->_id_;
$res = App::DB()->prepare_query('UPDATE `' . $this->_tableName_ . '` SET `' . implode('`=?, `', array_values($keys)) . '`=? WHERE `' . $this->_primaryKey_ . '`=?', self::arrayWithTypes($values));
return $res ? $this : FALSE;
}
function save()
{
if (!$this->_id_ || !$this->_vals_)
{
if ($this->_vals_)
{
return $this->add($this->_vals_);
}
else
{
return FALSE;
}
}
$values = $this->_vals_;
unset($values[$this->_primaryKey_]);
$request = App::DB()->prepare('UPDATE ' . $this->_tableName_ . ' SET ' . implode('=?, ', array_keys($values)) . '=? WHERE '.$this->_primaryKey_.'='.$this->_id_);
$res = $request->execute(array_values($values));
return $res ? $this : FALSE;
}
/**
* Возвращает значения полей объекта в виде ассоциативного массива.
* @return array
*/
function getValues()
{
return $this->_vals_;
}
function removeId()
{
$this->_vals_[$this->_primaryKey_] = $this->_id_ = NULL;
}
}