vasinsky
Новичок
ну соб-но вчера тема поднялась, просили показать какие навыки
класс не претендует на звание лучшего, и тем более я не навязываю использовать его в своих целях
убедительная просьба - не орать с пеной из-за рта о создании очередного велосипеда
этот топик появился в ходе беседы http://phpclub.ru/talk/threads/Получение-html-после-выполнения-клиентских-скриптов.77308/page-3#post-695845
написан на коленке, урывками по среди рабочего времени.
прошу указать на недачёты, не только в проектировании класса, но и возможно более гибкие алгоритмы для реализации поставленной задачи
данная реализация разбита на 2 класса - работа с типами и непосредственный парсинг sql строки
Последовательность плейсхолдеров в строке и последовательность в массиве с данными - не важна.
использование:
результат:
класс не претендует на звание лучшего, и тем более я не навязываю использовать его в своих целях
убедительная просьба - не орать с пеной из-за рта о создании очередного велосипеда
этот топик появился в ходе беседы http://phpclub.ru/talk/threads/Получение-html-после-выполнения-клиентских-скриптов.77308/page-3#post-695845
написан на коленке, урывками по среди рабочего времени.
прошу указать на недачёты, не только в проектировании класса, но и возможно более гибкие алгоритмы для реализации поставленной задачи
данная реализация разбита на 2 класса - работа с типами и непосредственный парсинг sql строки
Последовательность плейсхолдеров в строке и последовательность в массиве с данными - не важна.
PHP:
/**
* класс типизации входных данных
*/
class Types{
/**
* Описание констант плейсхолдеров
*/
const I = 'i:'; //int
const F = 'f:'; //float
const S = 's:'; //string
const B = 'b:'; //bool
const N = 'n:'; //null
/**
* array
* собирает обработанные входные данные
*/
protected $params;
public function __construct(){
}
/**
* Приводит данные к типу int
* @param int,float
* @return int
*/
private function _int($data){
return intval($data);
}
/**
* Приводит данные к типу float
* @param int,float
* @return float
*/
private function _float($data){
return round(floatval($data), 2);
}
/**
* Приводит данные к типу string + экранирует спец. символы
* @param int,float,string
* @return string
*/
private function _string($data){
//addsleshes здесь смотрится неуклюже
//более правильней, наверно - формировать $data с данными - если строка - то ->real_escape_string()
//и пихать real_escape_string сюда - не вижу смысла
return (string)addslashes($data);
}
/**
* Приводит данные к типу bool
* @param int,float,string
* @return bool
*/
private function _bool($data){
return (bool)$data;
}
/**
* подставляет null вместо значения
* я не понял зачем этот плейсхолдер нужен, когда null можно подставить в массив с данными
* @param void
* @return NULL as string
*/
protected function _null(){
return 'null';
}
/**
* Приводит к типу входные данные, согласно константам плейсхолдеров
*/
protected function setType($mark_plhdr, $data){
if($mark_plhdr == self::I)
$this->params[] = $this->_int($data);
elseif($mark_plhdr == self::F)
$this->params[] = $this->_float($data);
elseif($mark_plhdr == self::S)
$this->params[] = "'".$this->_string($data)."'";
elseif($mark_plhdr == self::B)
$this->params[] = $this->_bool($data);
elseif($mark_plhdr == self::N)
$this->params[] = $this->_null();
else
throw new Exception('Попытка использования неизвестного плейсхолдера: '.$mark_plhdr);
}
}
PHP:
/**
* класс обработки SQL запросов с использование плейсхолдеров
*/
class Stmt extends Types{
protected $marks = array();
public function __construct(){
parent::__construct();
}
/**
* Парсер плейсхолдеров в SQL запросе
* формирует свойства объекта, заполняет $this->marks - плейсхолдеры вместе с метками, $this->params - обработанными данными
* @param sql string (валидный sql запрос)
* @param data array (входные данные в виде ассоц массива, с ключами по меткам плейсхолдеров)
*/
private function parseSql($sql, $data){
if(!is_string($sql)){
throw new Exception('SQL запрос должен быть предоставлен в виде строки');
return false;
}
else{
preg_match_all("#([a-z]{1}\:)#s", $sql, $plhdr);
preg_match_all("#\:([a-z0-1]{1,})#s", $sql, $plhdr_data);
if(!$plhdr[1] or empty($plhdr[1]))
throw new Exception('Ошибка определения плейсходера(ов)');
elseif(count($plhdr[1]) != count($plhdr_data[1]))
throw new Exception('Ошибка определения пары: плейсхолдер - данные');
else{
foreach($plhdr[1] as $k=>$v){
$this->marks[] = $v.$plhdr_data[1][$k];
if(!isset($data[$plhdr_data[1][$k]]))
throw new Exception('Не указанно значение параметра : '.$plhdr_data[1][$k].', при использовании '.$v.$plhdr_data[1][$k]);
else
$this->setType($v, $data[$plhdr_data[1][$k]]);
}
}
}
}
/**
* конечный этап работы с плейсхолдерами в SQL
* @param sql string (валидный sql запрос)
* @param data array (входные данные в виде ассоц массива, с ключами по меткам плейсхолдеров)
* @return string
* пускай название с толку не сбивает - это сокращение от placeholder, его всегда можно сменить на более красивое
*/
public function plhdr($sql, $data){
$this->parseSql($sql, $data);
if(!empty($this->marks)){
foreach($this->marks as $k=>$m){
$sql = strtr($sql, array($m => $this->params[$k]));
}
return $sql;
}
//здесь впринципе можно поругаться - что запрос не был обработан и вернулся в исходном виде
return $sql;
}
}
PHP:
$stmt = new Stmt;
$data = array(
'price' => 10.1291231,
'count' => 25,
'text'=>"as'fsfas"
);
echo $stmt->plhdr("SELECT good_name, price, count FROM bla WHERE price BETWEEN (f:price AND f:price * i:count) AND count > i:count AND `text` = s:text" , $data);
Код:
SELECT good_name, price, count FROM bla WHERE price BETWEEN (10.13 AND 10.13 * 25) AND count > 25 AND `text` = 'as\'fsfas'
Последнее редактирование: