Advertisement
riff

Placeholders

Oct 25th, 2013
89
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 5.25 KB | None | 0 0
  1. <?php
  2.  
  3. namespace mint\sys\classes;
  4. use mysqli;
  5. use Exception;
  6.  
  7. /**
  8.  * @property int insert_id
  9.  */
  10. class Query
  11. {
  12.     /** @var \mysqli_result */
  13.     public $handle;
  14.  
  15.     public function __construct($query)
  16.     {
  17.         $this->handle = $query;
  18.     }
  19.  
  20.     public function __get($name)
  21.     {
  22.         switch ($name) {
  23.             case 'insert_id':
  24.                 return DB::$handle->insert_id;
  25.             default:
  26.                 return false;
  27.         }
  28.     }
  29.  
  30.     /**
  31.      * Выполняет запрос к БД и получает одну запись
  32.      *
  33.      * @return \stdClass|bool
  34.      * @see DB::next()
  35.     */
  36.     public function get()
  37.     {
  38.         if (!$this->handle) return false;
  39.         return $this->handle->fetch_object();
  40.     }
  41.  
  42.     /**
  43.      * Выполняет запрос к БД и загружает все записи
  44.      *
  45.      * @param callable|null $fn
  46.      * @return array|boolean
  47.      */
  48.     public function getAll($fn = null)
  49.     {
  50.         if ($this->handle) {
  51.             $rows = array();
  52.             while ($row = $this->handle->fetch_object())
  53.                 is_callable($fn)
  54.                     ? $fn($row)
  55.                     : $rows[] = $row;
  56.             return is_callable($fn) ? true : $rows;
  57.         }
  58.         else
  59.             return false;
  60.     }
  61. }
  62.  
  63. class DB
  64. {
  65.     /**
  66.      * @var mysqli
  67.      */
  68.     static public $handle = false;
  69.     /**
  70.      * @static
  71.      * @param  $params array
  72.      * @return bool
  73.      */
  74.     static public function connect($params)
  75.     {
  76.         if (self::$handle = new mysqli('localhost', $params['login'], $params['password']))
  77.         {
  78.             self::$handle->select_db($params['db_name']);
  79.             self::$handle->set_charset('UTF8');
  80.             return true;
  81.         }
  82.         return false;
  83.     }
  84.  
  85.     /**
  86.      * Возвращает строку в стиле mysql
  87.      *
  88.      * @param string $value
  89.      * @param boolean $q
  90.      * @return string
  91.      */
  92.     public static function str($value, $q = true)
  93.     {
  94.         if ($value === null)
  95.             return 'null';
  96.         else
  97.             return ($q ? '"' : '').self::$handle->real_escape_string($value).($q ? '"' : '');
  98.     }
  99.  
  100.     public static function sql($query, $args)
  101.     {
  102.         $pattern = '~(\?(?:tbl|t|col|c|set|str|s|int|i|list_int|list|li|l|p)?(?::[a-zA-Z_][a-zA-Z0-9_]*)?)~';
  103.         $array   = preg_split($pattern, $query, null, PREG_SPLIT_DELIM_CAPTURE);
  104.         $out     = '';
  105.  
  106.         if (key($args) === 0)
  107.         {
  108.             $mode = 'numeric';
  109.  
  110.             $anum  = count($args);
  111.             $pnum  = floor(count($array) / 2);
  112.             if ( $pnum != $anum )
  113.             {
  114.                 throw new Exception("Number of args ($anum) doesn't match number of placeholders ($pnum) in [$query]");
  115.             }
  116.         }
  117.         else {
  118.             $mode = 'named';
  119.         }
  120.  
  121.         static $escape;
  122.         if (!$escape) {
  123.             $escape = array(
  124.                 'tbl' => function($data) {
  125.                     return "`$data`";
  126.                 },
  127.                 'col' => function($data) {
  128.                     return "`$data`";
  129.                 },
  130.                 'p' => function($data) {
  131.                     return is_null($data) ? '' : $data;
  132.                 },
  133.                 'str' => function($data) {
  134.                     return is_null($data) ? 'null' : DB::str($data);
  135.                 },
  136.                 'int' => function($data) {
  137.                     if (is_null($data)) {
  138.                         return 'null';
  139.                     }
  140.  
  141.                     $data = str_replace(',', '.', $data);
  142.                     if (!is_numeric($data)) {
  143.                         throw new Exception("Integer (?i) placeholder expects numeric value, ".gettype($data)." given");
  144.                     }
  145.                     else {
  146.                         return number_format($data, 0, '.', ''); // may lose precision on big numbers
  147.                     }
  148.                 },
  149.                 'set' => function($data) use(&$escape)
  150.                 {
  151.                     $fv = array();
  152.                     foreach ($data as $key=>$value) {
  153.                         if ($value === '') $value = '""';
  154.                         elseif (is_null($value)) $value = 'null';
  155.                         elseif (is_bool($value)) $value = $value ? 1 : 0;
  156.                         elseif (is_numeric($value)) $value = number_format($value, 0, '.', '');
  157.                         elseif (is_array($value)) {
  158.                             $flag = key($value);
  159.                             $value = $escape[$flag]($value[$flag]);
  160.                         }
  161.                         else $value = DB::str($value);
  162.                         $fv[] = "`$key`=$value";
  163.                     }
  164.                     return implode(',', $fv);
  165.                 },
  166.                 'list' => function($data) use(&$escape)
  167.                 {
  168.                     foreach ($data as $key=>$value)
  169.                     {
  170.                         $data[$key] = $escape['str']($value);
  171.                     }
  172.                     return implode(',', $data);
  173.                 },
  174.                 'list_int' => function($data) use(&$escape)
  175.                 {
  176.                     foreach ($data as $key=>$value)
  177.                     {
  178.                         $data[$key] = $escape['int']($value);
  179.                     }
  180.                     return implode(',', $data);
  181.                 },
  182.             );
  183.             $escape['t'] = $escape['tbl'];
  184.             $escape['c'] = $escape['col'];
  185.             $escape['s'] = $escape['str'];
  186.             $escape['i'] = $escape['int'];
  187.             $escape['l'] = $escape['list'];
  188.             $escape['li'] = $escape['list_int'];
  189.         }
  190.  
  191.         foreach ($array as $i => $part)
  192.         {
  193.             if ( ($i % 2) == 0 )
  194.             {
  195.                 $out .= $part;
  196.                 continue;
  197.             }
  198.  
  199.             if ($mode === 'numeric')
  200.             {
  201.                 $type  = $part;
  202.                 $value = array_shift($args);
  203.             }
  204.             else
  205.             {
  206.                 list($type, $key) = explode(':', $part);
  207.  
  208.                 if (array_key_exists($key, $args))
  209.                 {
  210.                     $value = $args[$key];
  211.                 }
  212.                 else {
  213.                     throw new Exception("No key found for the named placeholder [$key] in the data array");
  214.                 }
  215.             }
  216.  
  217.             $type  = trim($type, '?');
  218.             $out .= $escape[$type ? : 'str']($value);
  219.         }
  220.         return $out;
  221.     }
  222.  
  223.     /**
  224.      * Выполняет запрос к БД.
  225.      *
  226.      * @param string $sql
  227.      * @param array|null $args
  228.      * @return bool|Query
  229.      */
  230.     public static function query($sql, $args = null)
  231.     {
  232.         if ($args) {
  233.             $sql = self::sql($sql, $args);
  234.         }
  235.         if ($query = self::$handle->query($sql))
  236.         {
  237.             $query = new Query($query);
  238.         }
  239.         else {
  240.             trigger_error(self::$handle->error, E_USER_WARNING);
  241.         }
  242.  
  243.         return $query;
  244.     }
  245. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement