За последние 24 часа нас посетили 22185 программистов и 1153 робота. Сейчас ищут 384 программиста ...

Практика использование ООП

Тема в разделе "PHP для новичков", создана пользователем Dimon2x, 26 ноя 2017.

  1. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.199
    Симпатии:
    184
    PHP:
    1.  $sql = "SELECT login FROM $table";
    это наверно лучше в трейт запихнуть?
     
  2. nospiou

    nospiou Старожил

    С нами с:
    4 фев 2018
    Сообщения:
    3.400
    Симпатии:
    510
  3. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.554
    Симпатии:
    1.754
    @Dimon2x, ну типа того. Правда смысла в твоём коде 0. Вообще, очень тяжело привести короткий пример полиморфизма, поскольку он требуется обычно для достаточно сложных задач. Вот ты фреймворки ковыряешь, давай посмотрим на примере Yii2 и его Data Widgets и Data Provider. Data Widgets отображают данные, которые надо откуда-то сначала получить. Для того, чтобы получить данные используется Data Providers, ArrayDataProvider берёт данные из массивов (при этом, умеет пагинацию, умеет сортировку и т.п.), https://www.yiiframework.com/doc/api/2.0/yii-data-sqldataprovider - через прямой SQL запрос к базе, ActiveDataProvider - использует объекты запросов и ActiveRecord.

    При этом для Data Widgets всё равно, откуда DataProvider берёт данные, ему важно, чтоб он их ему отдавал. Вот это и полиморфизм. Я могу на этапе выполнения решить, какой ему передать DataProvider в зависимости от ситуации
     
    Dimon2x нравится это.
  4. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.199
    Симпатии:
    184
    @nospiou не про базу, а про полиморфизм в целом
     
  5. nospiou

    nospiou Старожил

    С нами с:
    4 фев 2018
    Сообщения:
    3.400
    Симпатии:
    510
  6. Алекс8

    Алекс8 Активный пользователь

    С нами с:
    18 май 2017
    Сообщения:
    1.730
    Симпатии:
    359
    класс который работает с объектами работающими с базой данных))
    PHP:
    1. <?php
    2.  
    3. /*
    4. * To change this license header, choose License Headers in Project Properties.
    5. * To change this template file, choose Tools | Templates
    6. * and open the template in the editor.
    7. */
    8.  
    9. namespace natCMF\core;
    10.  
    11.  
    12. /**
    13. * Description of Db
    14. *
    15. * @author 27087
    16. */
    17. class Db {
    18.  
    19.     /**
    20.      * Храним экземпляр текущего класса
    21.      * @var object Db
    22.      */
    23.     static private $_instance = null;
    24.  
    25.     /**
    26.      * Храним объект работы с БД - имплементированный от интерфейса
    27.      * DbInterface
    28.      * @var object - implement DbInterface. На данный момент это может быть
    29.      * DbMysqli или DbSqlite3
    30.      */
    31.     private $_db = null;
    32.  
    33.     /**
    34.      * Создаем подключенте БД
    35.      * @return object Db - возвращает экземпляр себя хранимый в _instance
    36.      */
    37.     static public function getInstance() {
    38.         if (is_null(self::$_instance)) {
    39.             self::$_instance = new self;
    40.  
    41.             //Достали параметры подключения к БД
    42.             $dbParams = Config::get('dbParams');
    43.            
    44.             //Возможные БД
    45.             $possibleDb = Config::get('possibleDb');
    46.            
    47.             //Создаем объект
    48.             $dbDriver = $possibleDb[$dbParams['dbType']];
    49.             self::$_instance->_db = new $dbDriver($dbParams);
    50.  
    51.            
    52.         }
    53.  
    54.         return self::$_instance;
    55.     }
    56.  
    57.     /**
    58.      * Запрос к БД
    59.      * @param string $query
    60.      * @param array $values
    61.      * @return object
    62.      */
    63.     static function query($query, $values = []) {
    64.         return self::getInstance()->_db->query($query, $values);
    65.     }
    66.  
    67.     /**
    68.      * Возвращает количество строк полученых в результате запроса к БД
    69.      * @param type $result
    70.      * @return int
    71.      */
    72.     static function numRows($result) {
    73.         return self::getInstance()->_db->numRows($result);
    74.     }
    75.    
    76.    
    77.     static function lastInsertId($result) {
    78.         return self::getInstance()->_db->lastInsertId($result);
    79.     }
    80.  
    81.     /**
    82.      * Очищает объект БД
    83.      * @param type $result
    84.      * @return boolean
    85.      */
    86.     static function freeResult(&$result) {
    87.         return self::getInstance()->_db->freeResult($result);
    88.     }
    89.  
    90.     /**
    91.      * Перебирая объект $result возвращает строки в виде ассоциативного
    92.      * массива
    93.      * @param type $result
    94.      * @return array
    95.      */
    96.     static function fetchAssoc($result) {
    97.         return self::getInstance()->_db->fetchAssoc($result);
    98.     }
    99.  
    100.     /**
    101.      * Перебирая объект $result возвращает строки в виде индексированного
    102.      * массива
    103.      * @param type $result
    104.      * @return array
    105.      */
    106.     static function fetchRow($result) {
    107.         return self::getInstance()->_db->fetchRow($result);
    108.     }
    109.  
    110.     /**
    111.      * Получаем информацию о модели/таблице
    112.      * @param type $table
    113.      * @return array
    114.      */
    115.     static function tableInfo($table) {
    116.         return self::getInstance()->_db->tableInfo($table);
    117.     }
    118.  
    119.     /**
    120.      * Возвращает количество запросов сделанных к базе
    121.      * @return int
    122.      */
    123.     static function getCountQuery() {
    124.         return self::getInstance()->_db->getCountQuery();
    125.     }
    126.  
    127. }
    --- Добавлено ---
    интерфейс
    PHP:
    1. <?php
    2.  
    3. /*
    4. * To change this license header, choose License Headers in Project Properties.
    5. * To change this template file, choose Tools | Templates
    6. * and open the template in the editor.
    7. */
    8.  
    9. namespace natCMF\core\sql;
    10.  
    11. /**
    12. * Description of DbInterface
    13. *
    14. * @author 27087
    15. */
    16. interface DbInterface {
    17.    
    18.     public function __construct($dbParams);
    19.    
    20.     public function query( $query,  $values = []);
    21.    
    22.     public function numRows($result);
    23.    
    24.     public function freeResult(&$result);
    25.    
    26.     public function fetchAssoc($result);
    27.    
    28.     public function fetchRow($result);
    29.    
    30.     public function tableInfo($table);
    31.    
    32.     public function getCountQuery();
    33.    
    34. }
    --- Добавлено ---
    Класс для работы с mysqli
    Код (Text):
    1.  
    2. namespace natCMF\core\sql;
    3.  
    4. use natCMF\core\sql\DbInterface;
    5.  
    6. /**
    7. * Description of DbMysqli
    8. *
    9. * @author 27087
    10. */
    11. class DbMysqli implements DbInterface {
    12.  
    13.     private $db = null;
    14.     private $dbPrefix = null;
    15.     private $colTypeLink = [
    16.         'varchar' => 'string',
    17.         'text' => 'string',
    18.         'int' => 'int',
    19.         'float' => 'float',
    20.     ];
    21.     private $_count = 0;
    22.  
    23.     public function __construct($dbParams) {
    24.         $this->dbPrefix = $dbParams['dbPrefix'];
    25.         $db = new \mysqli($dbParams['dbHost'], $dbParams['dbUser'], $dbParams['dbPass'], $dbParams['dbName']);
    26.  
    27.         $db->set_charset('utf8mb4');
    28.         $db->character_set_name();
    29.         $db->query("SET CHARACTER SET utf8mb4");
    30.         if (empty($db->errno)) {
    31.             $this->db = $db;
    32.         }
    33.     }
    34.  
    35.     /**
    36.      *
    37.      * @param string $query - запрос
    38.      * с плейсхолдерами int|float|string|array_int|array_string
    39.      * id={int:id} AND id_member IN(array_ind:ids)
    40.      * @param array $values массив с даными для плейсходеров
    41.      * [ id=>1, ids=>[1,2,3,4,5] ]
    42.      * @return object mysqli_result
    43.      */
    44.     public function query(string $query, array $values = []) {
    45.  
    46.         //Считаем запросы к БД
    47.         $this->_count++;
    48.  
    49.         /* Типы плейсхолдеров */
    50.         $pattern = '~{(int|float|string|array_int|array_string):(\S+?)}~';
    51.  
    52.         /* Выбираем из строки запрос возможные плейсходеры */
    53.         $matches = [];
    54.         preg_match_all($pattern, $query, $matches, PREG_SET_ORDER);
    55.  
    56.         /* Инициализируем массив с данными плейсхолтера */
    57.         $prepareData = [];
    58.         /* и массив с типами плейсхолдера mysqli
    59.          *   i - соответствующая переменная имеет тип integer
    60.          *   d - соответствующая переменная имеет тип double
    61.          *   s - соответствующая переменная имеет тип string
    62.          *   b - соответствующая переменная является большим двоичным объектом (blob) и будет пересылаться пакетами
    63.          */
    64.         $typesPlaceholders = '';
    65.  
    66.         /* Обходим найденные плейсхолдеры */
    67.         foreach ($matches as $ph) {
    68.             /* Временный плейсхоллер нужен для типов плейсхолдеров array_XXX
    69.               знак вопроса ? для самого запроса */
    70.             $tmpPlaceholers = '';
    71.  
    72.             switch ($ph['1']) {
    73.                 case 'int':
    74.                     $typesPlaceholders .= 'i';
    75.                     $prepareData[] = (int) $values[$ph['2']];
    76.                     $tmpPlaceholers = '?';
    77.                     break;
    78.  
    79.                 case 'array_int':
    80.                     $tmpPlaceholers = '';
    81.                     foreach ($values[$ph['2']] as $intVal) {
    82.                         $typesPlaceholders .= 'i';
    83.                         $prepareData[] = (int) $intVal;
    84.                         $tmpPlaceholers .= '?,';
    85.                     }
    86.                     $tmpPlaceholers = trim($tmpPlaceholers, ',');
    87.                     break;
    88.  
    89.                 case 'string':
    90.                     $typesPlaceholders .= 's';
    91.                     $prepareData[] = (string) $values[$ph['2']];
    92.                     $tmpPlaceholers = '?';
    93.                     break;
    94.  
    95.                 case 'array_string':
    96.                     break;
    97.  
    98.                 default:
    99.  
    100.                     die('Неверный тип даннных ' . $ph['1']);
    101.                     break;
    102.             }
    103.             /* Заменили плейсхолдер на нужное количество знаков вопросов */
    104.             $query = str_replace($ph['0'], $tmpPlaceholers, $query);
    105.         }
    106.         /* Заменили плейсхолдер префикса таблицы на сам префикс */
    107.         $query = str_replace('{db_prefix}', $this->dbPrefix, $query);
    108.         /* Собрали массив для вызова метода */
    109.         $params['db_types'] = $typesPlaceholders;
    110.         foreach ($prepareData as $key => $val) {
    111.             $params['db_' . $key] = &$prepareData[$key];
    112.         }
    113.  
    114.  
    115.  
    116.         /* Готовим запрос и выполняем */
    117.         $stmt = $this->db->stmt_init();
    118.         $stmt->prepare($query);
    119.  
    120.         if ($stmt->error) {
    121.             var_dump($query);
    122.             var_dump($stmt->error);
    123.         }
    124.  
    125.         if (!empty($params['db_types'])) {
    126.             call_user_func_array([$stmt, 'bind_param'], $params);
    127.         }
    128.  
    129.         $stmt->execute();
    130.  
    131.         //Если INSERT то возвращаем то что показал stmp
    132.         if (!empty($stmt->insert_id)) {
    133.             $result = new \stdClass();
    134.             foreach ($stmt as $key => $value) {
    135.                 $result->$key = $stmt->$key;
    136.             }
    137.         }
    138.         //Если запрос был SELECT, UPDATE, DELETE - тогда берем результат
    139.         else {
    140.             $result = $stmt->get_result();
    141.         }
    142.         $stmt->close();
    143.         return $result;
    144.     }
    145.  
    146.     /**
    147.      * Количество записей в результате запроса
    148.      * @param object \mysqli_result $result
    149.      * @return int
    150.      */
    151.     public function numRows($result) {
    152.         return $result->num_rows;
    153.     }
    154.  
    155.     /**
    156.      * Очищаем mysqli_result
    157.      * @param $result - object \mysqli_result
    158.      * @return boolean
    159.      */
    160.     public function freeResult(&$result) {
    161.         return $result->free_result();
    162.     }
    163.  
    164.     /**
    165.      * Получаем ассоциативный массив с mysqli_result и передвигаем указатель на
    166.      * следующий элемент
    167.      * @param $result - object \mysqli_result
    168.      * @return array - массив с результаом
    169.      */
    170.     public function fetchAssoc($result) {
    171.         return $result->fetch_assoc();
    172.     }
    173.  
    174.     /**
    175.      *
    176.      * @param $result - object \mysqli_result
    177.      * @return type
    178.      */
    179.     public function fetchRow($result) {
    180.         return $result->fetch_row();
    181.     }
    182.  
    183.     /**
    184.      *
    185.      * @param type $table
    186.      * @return type
    187.      */
    188.     public function tableInfo($table) {
    189.  
    190.         return $this->tableInfoAdaptation($rows);
    191.     }
    192.  
    193.     /**
    194.      *
    195.      * @param type $result
    196.      * @return type
    197.      */
    198.     private function tableInfoAdaptation($result) {
    199.         return $linksType;
    200.     }
    201.  
    202.     /**
    203.      * Возвращаем количество запросов к БД
    204.      * @return int
    205.      */
    206.     public function getCountQuery() {
    207.         return $this->_count;
    208.     }
    209.  
    210. }
     
    Dimon2x нравится это.
  7. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.750
    Симпатии:
    1.322
    Адрес:
    Лень
    нет, неа, найн.... бинд парам в калле не правильно.
    А если мы произведем insert с множественными вставками строк ?
    --- Добавлено ---
    PHP:
    1. <?php
    2.  
    3. error_reporting ( E_ALL );
    4.  
    5. $m = new mysqli( 'localhost', 'root', '', 'git', 3306 );
    6.  
    7. $stmt = $m -> prepare( 'SELECT * FROM lerma WHERE id IN( ?, ? )');
    8.  
    9. $executes = [138,139];#, [141,142] ];
    10.  
    11. /* ... */
    12.  
    13. $executes = ( is_array ( $executes[0] ) ? $executes : [ $executes ] );
    14.  
    15. $count = count ( $executes[0] );
    16.  
    17. $for = (array)implode ( '', array_map ( function ( $arg )
    18. {
    19.     if ( !in_array ( $type = gettype ( $arg ), [ 'integer', 'double', 'string' ] ) )
    20.     {
    21.         throw new Error( 'Invalid type ' . $type );
    22.     }
    23.  
    24.     return $type[0];
    25. },
    26. $executes[0] ) );
    27.  
    28. for ( $i = 0; $i < $count; $i++ )
    29. {  
    30.     $for[] = &${ 'bind_' . $i };
    31. }
    32.  
    33. $ReflectionMethod = new ReflectionMethod( 'mysqli_stmt', 'bind_param' );
    34.  
    35. $ReflectionMethod -> invokeArgs( $stmt, $for );
    36.  
    37. foreach ( $executes AS $items )
    38. {
    39.     #$items = executeHolders( $items );
    40.  
    41.     extract ( $items, EXTR_PREFIX_ALL, 'bind' );
    42.  
    43.     $stmt -> execute();
    44. }
    45.  
    46. /* ... */
    47.  
    48. $get = $stmt -> get_result();
    49.  
    50. print_r ( $get -> fetch_all( MYSQLI_ASSOC ) );
    --- Добавлено ---
    На счет плейсхолдеров, научил
    PHP:
    1. SELECT * FROM lerma WHERE id = :id
    PHP:
    1. <?php
    2.  
    3. namespace Aero\Low\Lerma;
    4.  
    5. trait Placeholders
    6. {
    7.     protected $pattern = '/(\?|:[a-z]{1,})/';    # Поиск плейсхолдеров в запросе
    8.    protected $matches;                            # Placeholders
    9.  
    10.     /*
    11.         - Поиск ':', замена placeholders на '?'
    12.     */
    13.     public function replaceHolders( $sql ): string
    14.     {
    15.         $this -> matches = [];
    16.      
    17.         $sql = ( is_array ( $sql ) ? sprintf ( ...$sql ) : $sql );
    18.      
    19.         if ( strpos ( $sql, ':' ) !== false )
    20.         {
    21.             preg_match_all ( $this -> pattern, $sql, $matches );
    22.          
    23.             $this -> matches = $matches[1];
    24.          
    25.             $sql = strtr ( $sql, array_fill_keys ( $this -> matches, '?' ) );
    26.         }
    27.      
    28.         return $sql;
    29.     }
    30.  
    31.     /*
    32.         - Реформирование данных в массиве по найденным placeholders
    33.     */
    34.     public function executeHolders( array $execute ): array
    35.     {
    36.         $new = [];
    37.      
    38.         foreach ( $this -> matches as $plaseholder )
    39.         {
    40.             if ( $plaseholder === '?' )
    41.             {
    42.                 $new[] = array_shift ( $execute );
    43.             }
    44.             else
    45.             {
    46.                 if ( isset ( $new[$plaseholder] ) )
    47.                 {
    48.                     $new[] = $new[$plaseholder];
    49.                 }
    50.                 else
    51.                 {          
    52.                     $new[$plaseholder] = $execute[$plaseholder] ?? null;
    53.                  
    54.                     unset ( $execute[$plaseholder] );
    55.                 }
    56.             }
    57.         }
    58.      
    59.         return $new ?? $execute;
    60.     }
    61. }
    --- Добавлено ---
    перед query / prepare юзается метод replaceHolders

    executeHolders в первом коде за комментирован
     
  8. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.554
    Симпатии:
    1.754
    @Dimon2x, ты вообще рекомендованную литературу читаешь? https://www.ozon.ru/context/detail/id/33506422/ - раскопай вот эту книгу, разбери. Читай доки к используемым фреймворкам (а то по коду, что ты выкладываешь, часто видно, что не читал).
     
  9. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.199
    Симпатии:
    184
    @mkramer вроде бы новое издание готовится
     
  10. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.554
    Симпатии:
    1.754
    Большая часть не претерпит изменений, так что можешь читать любое. Потом просто посмотреть в мануале php, что в нём появилось нового. Если поймёшь книжку, разберёшься и с этим.