За последние 24 часа нас посетили 22892 программиста и 1223 робота. Сейчас ищут 743 программиста ...

База данных mySQL - как правильно подключиться и сделать запрос?

Тема в разделе "PHP и базы данных", создана пользователем miltorg, 22 июл 2019.

Статус темы:
Закрыта.
  1. miltorg

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

    С нами с:
    7 апр 2019
    Сообщения:
    375
    Симпатии:
    12
    Адрес:
    Калининград
    База данных mySQL - как правильно подключиться и сделать запрос?

    В начале я подключался через mysql_connect.
    Теперь - через new mysqli.
    Но некоторые говорят, что сейчас нужно подключаться через new PDO.

    Если честно - мне это всё не очень интересно. - Хотелось бы раз и на всегда понять, что более оптимально использовать применительно к очень недорогим хостингам?

    Спасибо.
    --- Добавлено ---
    Да. Совсем забыл. На входе - конечно форма. Нужно безопасно записать в базу и тут же всё прочитать.
    --- Добавлено ---
    PHP:
    1. <form>
    2. <input name="imja" value="">
    3. <input name="familija" value="">
    4. <input type="submit">
    5. </form>
     
  2. miltorg

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

    С нами с:
    7 апр 2019
    Сообщения:
    375
    Симпатии:
    12
    Адрес:
    Калининград
    PHP:
    1. <?
    2. $id=$_POST['id'];
    3. $imja=$_POST['imja'];
    4. $familija=$_POST['familija'];
    5.  
    6. // Нужна ли проверка на правильность ввода с точки зрения безопасности?
    7. // Я проверяю обычно просто правильность ввода
    8.  
    9. $mysqli = new mysqli("localhost", "user", "password", "database");
    10. $mysqli->query("UPDATE test SET imja='$imja', familija='$familija' where id=$id");
    11. $r = $mysqli->query("SELECT * FROM test where id=$id")->fetch_object();
    12. ?>
    13.  
    14. <form method="post">
    15.  
    16. <input name="imja" value="<?=$r->imja?>">
    17. <input name="familija" value="<?=$r->familija?>">
    18. <input name="id" type="hidden" value="<?=$r->id?>">
    19. <input type="submit">
    20. </form>
     
  3. Artur_hopf

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

    С нами с:
    7 май 2018
    Сообщения:
    2.266
    Симпатии:
    405
    Не то =)

    но с pdo это выглядело бы как то так.
    PHP:
    1. $dpo = new PDO('mysql:host=localhost;dbname=test', $user, $pass);
    2. $sql = "UPDATE test SET imja=?, familija=? WHERE id=?";
    3. $stmt = $dpo->prepare($sql);
    4. $stmt->execute([$imja, $familija, $id]);
    5. $sth= $pdo->prepare('SELECT * FROM test where id= ?');
    6. $sth->execute([$id]);
    7. $r = $sth->fetch(PDO::FETCH_OBJ);
    и да, я только учусь, ждус правильного ответа =)
     
    #3 Artur_hopf, 22 июл 2019
    Последнее редактирование: 22 июл 2019
  4. Valick

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

    С нами с:
    12 авг 2018
    Сообщения:
    1.911
    Симпатии:
    328
    Тогда зачем ты отнимаешь наше время?
     
  5. miltorg

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

    С нами с:
    7 апр 2019
    Сообщения:
    375
    Симпатии:
    12
    Адрес:
    Калининград
    Не интересны мне различные методы доступа к различным базам данных.
    Мне интересно - единственный, правильный, пацанский :) метод общения с базой данных на дешёвых хостингах.

    Вы правда не понимаете?
    --- Добавлено ---
    То есть по строкам - больше - хуже.
    По наглядности - хуже.

    По безопасности?
     
  6. Artur_hopf

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

    С нами с:
    7 май 2018
    Сообщения:
    2.266
    Симпатии:
    405
    Вот по безопасности ,коротко и ясно =)

    http://phpfaq.ru/safemysql
    --- Добавлено ---
    А если есть время читать , то тут разжевано, но я сам не дочитал =)
    http://phpfaq.ru/pdo
    --- Добавлено ---
    Ну и чтоб подвести итог, существует только ваш личный придуманный пацанский метод (это я про класс). Все остальное это чужой непонятный код =)
     
  7. mkramer

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

    С нами с:
    20 июн 2012
    Сообщения:
    8.555
    Симпатии:
    1.754
    @miltorg, если только с MySQL работаешь, то можно mysqli. PDO тоже не плохо, немного поопрятнее подготовленные параметры. Говорят, у mysqli какие-то преимущества по скорости, поскольку он написан только для одной СУБД, а PDO может работать с несколькими. Соответственно, универсальный код медленнее. Но не настолько, чтоб было заметно невооруженным глазом. Короче, однозначного ответа нету. Функции mysql_* устарели и удалены из современных версий PHP.

    Пихать в запросы сырые данные, как ты делаешь, нельзя. Либо экранирование, либо подготовленные запросы
    --- Добавлено ---
    Такого нету вообще.
    --- Добавлено ---
    Лично я предпочитаю что-то из фреймворков. КОгда проект слишком просто для тяжёлего фреймворка, использую https://github.com/auraphp/Aura.SqlQuery вместе с PDO, поскольку писать запросы руками мне не удобно (хоть я и могу при надобности), я люблю построитель запросов, поскольку они супергибкие, в них уже заложена возня с экранированием/подготовкой, и ещё много преимуществ.
     
  8. miltorg

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

    С нами с:
    7 апр 2019
    Сообщения:
    375
    Симпатии:
    12
    Адрес:
    Калининград
    Не понятно - где я это делаю - но суть не в этом. Вот тут:


    Пишут что PDO защищает на 100%
    Я очень удивился и собственно по этому сюда и написал
     
  9. miltorg

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

    С нами с:
    7 апр 2019
    Сообщения:
    375
    Симпатии:
    12
    Адрес:
    Калининград
    Как? Ну например как бы сделал я с примером выше:

    PHP:
    1. // Нужна ли проверка на правильность ввода с точки зрения безопасности?
    2. // Я проверяю обычно просто правильность ввода
    3.  
    4. if (preg_match('/\D/', $id)) $id=103;
    5. if (preg_match('/\W/u', $imja)) $imja='Vasja';
    6. if (preg_match('/\W/u', $familija)) $id='Pupkin';
     
  10. TeslaFeo

    TeslaFeo Старожил

    С нами с:
    9 мар 2016
    Сообщения:
    2.989
    Симпатии:
    759
    вот тут
    я думал ты опытный дядя

    я вот этим классом пользуюсь.
    вот так будет выглядеть:
    PHP:
    1. $db = new db("localhost", "user", "password", "database");
    2. $db->query("UPDATE `test` SET `imja`='".$db->escape($imja)."', `familia`='".$db->escape($familia)."' WHERE `id`=".(int)$id);
    3. $rows = $db->query("SELECT * FROM `test` WHERE `id`=".(int)$id)->rows;
     
  11. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.794
    Симпатии:
    650
    @TeslaFeo, у него опыт на качество не оч. влияет.

    @miltorg, уберите вывод в форму из обработчика. Его нужно делать после редиректа. При выводе нужно выполнять HTML-кодирование – тоже важный элемент защиты. Ну и плюс то, о чем в пред. посте написали.
    --- Добавлено ---
    Что касается осн. вопроса, выбирайте между двумя вариантами. mkramer написал, на что прежде всего следует обращать внимание. PDO – это универсальность в выборе БД (по большому счету нафиг не нужна), именованные параметры в подготовленных запросах (на любителя), ну и поддержка исключений.
     
    TeslaFeo нравится это.
  12. sushko

    sushko Новичок

    С нами с:
    17 июл 2019
    Сообщения:
    78
    Симпатии:
    8
    Я не знаю, что такое PDO (я новенький в PHP), но я не думаю, что PDO волшебным образом защитит от SQL injection. Я думаю, что ув. MouseZver имел в виду, что переданные пользователем данные надо передавать в запрос через параметры вместо того, чтобы генерить запрос на лету, тогда это будет безопасно.

    Пусть в Вашей форме (1-е сообщение в топике) я в качестве фамилии укажу:
    Код (Text):
    1. ';DELETE FROM test;
    Ну вот такая у меня фамилия. Тогда в Вашем варианте Вы выполните запрос
    Код (Text):
    1. UPDATE test SET imja='$imja', familija='';DELETE FROM test;
    В варианте же ув.MouseZver Вы выполняете совсем другой запрос:
    Код (Text):
    1. UPDATE test SET imja=?, familiya=? WHERE id=?
    , и что бы я ни написал вместо своей фамилии, Вашу базу данных это не сломает.

    Т.е. дело не в том, что PDO волшебно-безопасен, а в передачи пользовательских данных в параметрах к SQL-запросу против формирования запроса на лету.
     
  13. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.752
    Симпатии:
    1.322
    Адрес:
    Лень
    Подготовленный запрос посылается на сервер БД для готовности принятия данных. После подготовки приходит сигнал о готовности, либо ошибка. Если ок - только тогда посылаются отдельно данные с идентификатором запроса на сервер по подготовленному там алгоритму вставки в строку. Поэтому это и есть единственный, 100% способ по защите SQL инъекции первого порядка.

    PDO медленнее в среднем на 6% чем MySQLi. Зависит от запроса. Почему? эмуляция / исполнимость самого инструмента. Поэтому лично отдаю предпочтение обверткам.

    PHP:
    1. public function binding( array ...$binding )
    2.     {
    3.         $count = count ( $binding[0] );
    4.      
    5.         $for = ( array ) implode ( '', array_map ( function ( $arg )
    6.         {
    7.             if ( !in_array ( $type = gettype ( $arg ), [ 'integer', 'double', 'string' ] ) )
    8.             {
    9.                 throw new Error( 'Invalid type ' . $type );
    10.             }
    11.          
    12.             return $type[0];
    13.         },
    14.         $binding[0] ) );
    15.  
    16.         for ( $i = 0; $i < $count; $for[] = &${ 'bind_' . $i++ } ){}
    17.      
    18.         ( new \ReflectionMethod( 'mysqli_stmt', 'bind_param' ) ) -> invokeArgs( $this -> lerma -> statement, $for );
    19.  
    20.         foreach ( $binding AS $items )
    21.         {
    22.             $items = $this -> lerma -> executeHolders( $items );
    23.          
    24.             extract ( $items, EXTR_PREFIX_ALL, 'bind' );
    25.          
    26.             $this -> lerma -> statement -> execute();
    27.         }
    28.      
    29.      
    30.     }
    --- Добавлено ---
    По безопасности - лишь. В остальном это хорошая жвачка для новичком. Пока не столкнуться в необходимости расширенных стилей проверки/выводимости информации с БД.
    --- Добавлено ---
    PHP:
    1. $dpo = new PDO('mysql:host=localhost;dbname=test', $user, $pass);
    2.  
    3. $stmt = $dpo->prepare( 'UPDATE test SET imja=?, familija=? WHERE id=?' );
    4.  
    5. $items = [ [...], [...], [...], [...], [...] ];
    6.  
    7. foreach ( $items AS $item )
    8. {
    9.    $stmt->execute( $item );
    10. }
     
  14. Artur_hopf

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

    С нами с:
    7 май 2018
    Сообщения:
    2.266
    Симпатии:
    405
    По поводу быстродействия pdo. Чувак писал что подобный запрос с 50000 записей у него занял примерно 3 секунды
    PHP:
    1. <?php
    2. $data = array(
    3.   array('name' => 'John', 'age' => '25'),
    4.   array('name' => 'Wendy', 'age' => '32')
    5. );
    6.  
    7. $insertStatement = $pdo->prepare('insert into mytable (name, age) values (:name, :age)');
    8.  
    9. // start transaction
    10. $pdo->beginTransaction();
    11.  
    12. foreach($data as &$row) {
    13.   $insertStatement->execute($row);
    14. }
    15.  
    16. // end transaction
    17. $pdo->commit();
    18.  
    19. ?>
     
  15. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.752
    Симпатии:
    1.322
    Адрес:
    Лень
    --- Добавлено ---
    Тот чувак после не забыл провести тест с Mysqli ?
     
    sushko нравится это.
  16. sushko

    sushko Новичок

    С нами с:
    17 июл 2019
    Сообщения:
    78
    Симпатии:
    8
    Плюсадин. Единственная цифра "3 секунды на 5000 строк" не дает ничего. Я могу придумать ситуацию, когда добавление одной строки полчаса займет.
     
  17. TeslaFeo

    TeslaFeo Старожил

    С нами с:
    9 мар 2016
    Сообщения:
    2.989
    Симпатии:
    759
    3 сек для одного запроса это очень много
    а 50к записей не очень много
    --- Добавлено ---
    пожалуй, просто "не много")
     
  18. Artur_hopf

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

    С нами с:
    7 май 2018
    Сообщения:
    2.266
    Симпатии:
    405
    Я всегда считал что 3 секунды это быстро, пойду жену обрадую =))

    Я же не мерюсь тут ничем, просто пример показал =)
     
  19. miltorg

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

    С нами с:
    7 апр 2019
    Сообщения:
    375
    Симпатии:
    12
    Адрес:
    Калининград
    А почему мои комментарии про обработку как раз упустили?
     
  20. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.752
    Симпатии:
    1.322
    Адрес:
    Лень
    поэтому смешиваешь логику по безопасности с логикой по разрешенному алфавиту для логина/никнейма
     
  21. miltorg

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

    С нами с:
    7 апр 2019
    Сообщения:
    375
    Симпатии:
    12
    Адрес:
    Калининград
    нет не выполнится. Я провожу проверку на соответствие. См:

    PHP:
    1. if (preg_match('/\D/', $id)) $id=103;
    2. if (preg_match('/\W/u', $imja)) $imja='Vasja';
    3. if (preg_match('/\W/u', $familija)) $id='Pupkin';
     
  22. TeslaFeo

    TeslaFeo Старожил

    С нами с:
    9 мар 2016
    Сообщения:
    2.989
    Симпатии:
    759
    потому что нужно пользоваться встроенными инструментами, если они есть

    а к твоему способу у меня куча вопросов даже при том, что я регулярки знаю очень плохо
     
  23. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.752
    Симпатии:
    1.322
    Адрес:
    Лень
    \W [^\w] любой символ, кроме цифры, буквы или знака подчеркивания
    не помеха
     
  24. miltorg

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

    С нами с:
    7 апр 2019
    Сообщения:
    375
    Симпатии:
    12
    Адрес:
    Калининград
    Приведу свой полный код, а то народ или не видит или не хочет видеть

    PHP:
    1. <?
    2. $id=$_POST['id'];
    3. $imja=$_POST['imja'];
    4. $familija=$_POST['familija'];
    5.  
    6. if (preg_match('/\D/', $id)) $id=103;
    7. if (preg_match('/\W/u', $imja)) $imja='Vasja';
    8. if (preg_match('/\W/u', $familija)) $id='Pupkin';
    9.  
    10. $mysqli = new mysqli("localhost", "user", "password", "database");
    11. $mysqli->query("UPDATE test SET imja='$imja', familija='$familija' where id=$id");
    12. $r = $mysqli->query("SELECT * FROM test where id=$id")->fetch_object();
    13. ?>
    14. <form method="post">
    15. <input name="imja" value="<?=$r->imja?>">
    16. <input name="familija" value="<?=$r->familija?>">
    17. <input name="id" type="hidden" value="<?=$r->id?>">
    18. <input type="submit">
    19. </form>
    Сломайте. Попробуйте. + есть проверка соответствия, а не простое экранирование.
    --- Добавлено ---
    Сломайте. Попробуйте. Я буду очень признателен за обучение.
    А пока - это просто слова
     
    #24 miltorg, 22 июл 2019
    Последнее редактирование: 22 июл 2019
  25. TeslaFeo

    TeslaFeo Старожил

    С нами с:
    9 мар 2016
    Сообщения:
    2.989
    Симпатии:
    759
    ну если он прям вот так на продакшоне, то это полная дич
     
Статус темы:
Закрыта.