В нашем случае мы разделяем использование mysqli и PDO для таких вещей, как подготовленные операторы и поддержка транзакций. В одних проектах используется один, в других - другой. Существует небольшая реальная вероятность того, что мы когда-нибудь перейдем на другую СУБД.
Я предпочитаю PDO по той единственной причине, что он позволяет использовать именованные параметры для подготовленных операторов, а, насколько мне известно, mysqli этого не делает.
Есть ли какие-либо другие плюсы и минусы выбора одного из них в качестве стандарта, поскольку мы объединяем наши проекты для использования только одного подхода?






Перемещение приложения из одной базы данных в другую не очень распространено, но рано или поздно вы можете обнаружить, что работаете над другим проектом, используя другую СУБД. Если вы дома с PDO, тогда вам будет по крайней мере на одну вещь меньше учиться.
Кроме того, я нахожу PDO API более интуитивно понятным и более объектно-ориентированным. mysqli кажется, что это просто процедурный API, который был объективирован, если вы понимаете, о чем я. Короче говоря, мне легче работать с PDO, но это, конечно, субъективно.
Лично я использую PDO, но думаю, что это в основном вопрос предпочтений.
PDO имеет некоторые функции, которые помогают против SQL-инъекций (подготовленные заявления), но если вы будете осторожны с вашим SQL, вы также можете добиться этого с помощью mysqli.
Переход на другую базу данных - не столько повод для использования PDO. Пока вы не используете «специальные функции SQL», вы можете переключаться с одной БД на другую. Однако, как только вы используете, например, «SELECT ... LIMIT 1», вы не сможете перейти в MS-SQL, где это «SELECT TOP 1 ...». Так что это в любом случае проблематично.
MySQLi подготовил заявления.
Я начал использовать PDO, потому что, на мой взгляд, поддержка операторов лучше. Я использую уровень доступа к данным в стиле ActiveRecord, и гораздо проще реализовать динамически генерируемые операторы. Связывание параметров MySQLi должно выполняться за один вызов функции / метода, поэтому, если вы не знаете до времени выполнения, сколько параметров вы хотите привязать, вы вынуждены использовать call_user_func_array() (я считаю, что это правильное имя функции) для выбирает. И забудьте о простой динамической привязке результата.
Больше всего мне нравится PDO, потому что это очень разумный уровень абстракции. Его легко использовать в полностью абстрактных системах, где вы не хотите писать SQL, но он также упрощает использование более оптимизированной системы с чистыми запросами или их сочетание.
Возможна привязка результатов с динамически генерируемыми запросами, мы делаем это в наших приложениях. Однако это огромная боль.
PDO - это стандарт, это то, что ожидает использовать большинство разработчиков. mysqli был, по сути, индивидуальным решением конкретной проблемы, но он имеет все проблемы других специфичных для СУБД библиотек. PDO - это то место, куда будет направлен весь тяжелый труд и умное мышление.
Следует помнить об одном.
Mysqli не поддерживает функцию fetch_assoc (), которая возвращала бы столбцы с ключами, представляющими имена столбцов. Конечно, для этого можно написать свою собственную функцию, это даже не очень долго, но мне было трудно написать ее В самом деле (для неверующих: если вам это кажется легким, попробуйте как-нибудь самостоятельно и не делайте этого) т жульничать :))
Вы пробовали мануал? php.net/manual/en/mysqli-result.fetch-assoc.php
Реализовал более давно, но да, я проверил руководство. Работает ли с подготовленными операторами? Я сомневаюсь...
На самом деле, у него есть, как ни странно, частичная поддержка. Вы можете получать массивы в обычных запросах, но не в параметризованных запросах: -!
Почему бы не удалить заведомо неправильный ответ?
@MajidFouladpour - Ответ не очевидно неправильно. Просто отсутствует какой-то контекст. Mysqli полностью поддерживает поиск ассоциативного массива нет.
Одна вещь, которая есть у PDO, чего мне не нравится в MySQLi, - это способность PDO возвращать результат как объект указанного типа класса (например, $pdo->fetchObject('MyClass')). MySQLi fetch_object() вернет только объект stdClass.
Фактически, вы можете указать класс вручную: «объект mysqli_result :: fetch_object ([string $ class_name [, array $ params]])». stdClass используется только в том случае, если вы ничего не указываете.
Вот еще кое-что, о чем следует помнить: на данный момент (PHP 5.2) библиотека PDO - багги. Там полно странных ошибок. Например: перед сохранением PDOStatement в переменной значение переменной должно быть unset(), чтобы избежать множества ошибок. Большинство из них было исправлено в PHP 5.3, и они будут выпущены в начале 2009 года в PHP 5.3, в котором, вероятно, будет много других ошибок. Вам следует сосредоточиться на использовании PDO для PHP 6.1, если вы хотите стабильный выпуск, и на использовании PDO для PHP 5.3, если вы хотите помочь сообществу.
Я думаю, что преимущества, которые предлагает PDO, заслуживают понимания и работы над ошибками. Сам PHP полон очень отягчающих ошибок, некоторые из которых мы даже не можем эффективно устранить, и, тем не менее, он предлагает множество преимуществ, которые заставляют нас использовать его вместо других вариантов.
Гм, странно, я никогда не сталкивался с ошибками с PDO. И я им много пользуюсь.
В Mysqli тоже есть ошибки. Во всем софте есть ошибки.
Что ж, вы можете поспорить с объектно-ориентированным аспектом, подготовленными утверждениями, тем фактом, что он становится стандартом и т. д. Но я знаю, что в большинстве случаев убедить кого-то лучше работает с помощью убойной функции. Итак, вот оно:
Действительно хорошая вещь с PDO - это то, что вы можете извлекать данные, автоматически вставляя их в объект. Если вы не хотите использовать ORM (потому что это просто быстрый сценарий), но вам нравится сопоставление объектов, это ДЕЙСТВИТЕЛЬНО круто:
class Student {
public $id;
public $first_name;
public $last_name
public function getFullName() {
return $this->first_name.' '.$this->last_name
}
}
try
{
$dbh = new PDO("mysql:host=$hostname;dbname=school", $username, $password)
$stmt = $dbh->query("SELECT * FROM students");
/* MAGIC HAPPENS HERE */
$stmt->setFetchMode(PDO::FETCH_INTO, new Student);
foreach($stmt as $student)
{
echo $student->getFullName().'<br />';
}
$dbh = null;
}
catch(PDOException $e)
{
echo $e->getMessage();
}
ORM: объектно-реляционное отображение en.wikipedia.org/wiki/Object-relational_mapping
Это хороший пост, но он определенно мог бы быть более понятным. Где животные входят в фрагмент с классом Person и таблицей лиц?
есть ли разница между вышеупомянутым и $mysqliResult->fetch_object("student");?
Глупая особенность. Если у объекта должны быть публичные поля - это против инкапсуляции. И ключевое слово new, используемое внутри метода - плохая практика.
@ e-satis нет, я использую PHP. Публичные поля нарушают инкапсуляцию, поэтому AS A BEST PRACTICE это просто ... lol :) Google не использует публичные поля, только методы доступа: google-styleguide.googlecode.com/svn/trunk/….
@ e-satis, попробуйте прочитать эту книгу (я уверен, что вы можете найти ее на своем родном языке, я нашел) amazon.com/Objects-Patterns-Practice-Matt-Zandstra/dp/… - там вы можете найти очень хорошее объяснение, какова основная цель инкапсуляции, почему публичные поля не должны быть используется и почему интерфейсы так важны. Я знаю, в данный момент вы думаете, что я ваш противник - не принимайте это так близко к сердцу, просто прочтите эту книгу, и, я надеюсь, вы меня поймете.
@ e-satis: Извините за вмешательство, но геттеры и сеттеры необходимы, если вы хотите контролировать, что происходит при изменении переменных. В противном случае вы просто не можете гарантировать внутреннее состояние вашего объекта (это особенно проблема, если у вас есть другой объект внутри). Это полностью не зависит от языка. @OZ_: Успокойся. Личная критика только заставит кого-то защищаться.
Мне нравится, когда люди говорят, что публичные поля - это зло. Здесь мы используем базу данных; когда мы не захотим иметь возможность редактировать поля базы данных и получать доступ к тем же полям? Ну давай же...
@monadic: Согласен. Инкапсуляция, конечно, является допустимым аргументом при работе с основными компонентами или сложными объектами и т. д., Однако как представление записей, которые в противном случае были бы связаны с чтением и записью. массивы, это приемлемо. Кроме того, это упрощает проверку типов, поскольку записи перемещаются по системе.
@Mattygabe: к сожалению, слишком много разработчиков, которые только начинают, не осознают, что есть проблемы с образцом кода, и будут копировать его, а не понимать. Если часть примера кода не следует копировать, код следует сопровождать примечанием об этом.
@outis Я надеюсь, что я не в меньшинстве, но я не считаю, что ответы следует оценивать с точки зрения их безопасности по отношению к новым разработчикам. Звучит жестко, но это правда. Цель ответа на SO - не просто предоставить код копирования и вставки, но также обеспечить понимание. Задача ответчика не заключается в том, чтобы убедиться, что каждая дыра в безопасности или недостаток шаблона покрыты примером, потому что давайте посмотрим правде в глаза, приложение, в которое копируется код, по своей сути отличается от любого другого приложения, использующего тот же код.
@Mattygabe: пожалуйста, поймите, я не спорю ни за отрицательное голосование, ни за то, чтобы были охвачены все аспекты примера кода, просто нужна небольшая заметка, когда образец кода содержит что-то, что (в производственном коде) обычно является ошибкой, или где читателям следует быть осторожными. Я полностью согласен, что ответы на SO должны содержать объяснения, а не полные решения, поэтому образец кода следует считать иллюстративным. Вот почему должно быть примечание, так как некоторые читатели не будут воспринимать код в качестве иллюстративных примеров, а будут копировать его целиком.
... Что касается различий между проектами, то здесь тоже есть сходства. Здесь различия не важны; общие ошибки заключаются в сходстве.
@outis Понятно, и я никогда не думал, что вы обязательно выступаете за отрицательный голос. Я просто утверждал, что к любым примерам на SO следует относиться с универсальной оговоркой «разработчик, будьте осторожны». Самая большая причина, по которой я испытываю чувства к этому конкретному примеру, заключается в том, что в этом примере показана особенность PDO, которая не обязательно хорошо известна и не является лучшим способом выполнения оператора select MySQL с PDO, поэтому в примере цель никоим образом не состоит в том, чтобы показать лучший способ выполнения выборки. Но мы согласны почти во всем, так что разногласия незначительны.
Я не тестировал это, но, IMO, очень вероятно, что аргумент инкапсуляции в значительной степени спорный, потому что PHP 5+ допускает аксессоры в виде волшебных методов __get() и __set(). Так что, к счастью, весь аргумент «Я не могу гарантировать целостность состояния моего объекта сейчас» выпадает из окна ...
В смысле скорости выполнения MySQLi выигрывает, но если у вас нет хорошей оболочки, использующей MySQLi, его функции, работающие с подготовленными операторами, ужасны.
У меня все еще есть баги, но если кому-то это нужно, вот.
Короче говоря, если вы ищете увеличения скорости, то MySQLi; если хотите простоты использования, то PDO.
в смысле скорости, не могли бы вы дать тесты?
Джонатен Робсон провел достойное сравнение скорости этих двух на jonathanrobson.me/2010/06/mysqli-vs-pdo-benchmarks. Резюме: inserts - почти равно, selects - mysqli на ~ 2,5% быстрее для неподготовленных операторов / ~ на 6,7% быстрее для подготовленных операторов. Учитывая, насколько малы потери производительности, возможности и гибкость использования PDO обычно перевешивают снижение производительности.
@Adam Спасибо за ссылку на мой блог!
@ daemonfire300 Это правда, в тестах нет необходимости. PDO является оболочкой для библиотеки mysqli. Я, вероятно, поразил бы поклонника, если бы кто-то смог доказать, что PDO быстрее, чем mysqli. :-D
@jnrbsn вы согласны с Адамом в том, что он сказал?
@Basit Да, я согласен со всем, что он сказал. Плюсы PDO определенно перевешивают минусы. Я больше не использую MySQLi.
В моем тестовый скрипт каждый метод проверяется 10000 раз и выводится разница общего времени для каждого метода. Вы должны это сделать в своей собственной конфигурации, я уверен, что результаты будут другими!
Вот мои результаты:
SELECT NULL" -> PGO() быстрее на ~ 0,35 секунды.SHOW TABLE STATUS" -> mysqli() быстрее на ~ 2,3 секунды.SELECT * FROM users" -> mysqli() быстрее на ~ 33 секунды.Примечание: при использовании -> fetch_row () для mysqli имена столбцов не добавляются в массив, я не нашел способа сделать это в PGO. Но даже если я использую -> fetch_array (), mysqli будет немного медленнее, но все же быстрее, чем PGO (за исключением SELECT NULL).
Что такое ПГО? И быстрее на 33 секунды ?! Мне очень трудно в это поверить ...
Еще одно заметное (хорошее) отличие PDO заключается в том, что метод PDO::quote() автоматически добавляет заключительные кавычки, тогда как mysqli::real_escape_string() (и подобные) этого не делают:
PDO::quote() places quotes around the input string (if required) and escapes special characters within the input string, using a quoting style appropriate to the underlying driver.
PDO значительно упростит масштабирование, если ваш сайт / веб-приложение станет действительно существующим, поскольку вы можете ежедневно настраивать главные и подчиненные соединения для распределения нагрузки по базе данных, плюс PHP движется к переходу на PDO в качестве стандарта.
Отредактированный ответ.
Имея некоторый опыт работы с обоими этими API, я бы сказал, что есть 2 функции уровня блокировки, которые делают mysqli непригодным для использования с собственными подготовленными операторами. Они уже были упомянуты в двух отличных (но недооцененных) ответах:
(оба также упоминаются в этот ответ)
По какой-то причине mysqli не работал с обоими. В настоящее время он получил некоторые улучшения для второго (get_result), но он работает только с установками mysqlnd, что означает, что вы не можете полагаться на эту функцию в своих сценариях.
Тем не менее, даже по сей день у него нет привязки по стоимости.
Итак, выбор только один: PDO
Все остальные причины, такие как
не имеют большого значения.
В то же время в обоих этих API отсутствует некоторый действительно важные особенности, например
Итак, чтобы удовлетворить жизненные потребности настоящий, нужно создать свою собственную библиотеку абстракции на основе одного из этих API, реализуя вручную анализируемые заполнители. В этом случае я бы предпочел mysqli, поскольку он имеет меньший уровень абстракции.
Наконец то, кто знает и не отрицает факты жизни ...
Этот статья поможет выбрать, какой из них использовать. Если вы считаете, что производительность это может помочь вам в выборе.