Вопрос в том, должно ли соединение базы данных передаваться по ссылке или по значению?
Для меня я специально задаю вопрос о подключении PHP к MySQL, но я думаю, что это относится ко всем базам данных.
Я слышал, что в PHP, когда вы передаете переменную функции или объекту, она копируется в память и поэтому сразу использует вдвое больше памяти. Я также слышал, что он копируется только после внесения изменений в значение (например, добавляется / удаляется ключ из массива).
В соединении с базой данных я бы подумал, что он изменяется в функции, поскольку запрос может изменить такие вещи, как последний идентификатор вставки или число строк. (Я думаю, это еще один вопрос: такие вещи, как num rows и insert id, хранящиеся в соединении, или фактический вызов возвращается в базу данных?)
Итак, имеет ли значение память или скорость, если соединение передается по ссылке или значению? Это имеет значение PHP 4 против 5?
// $connection is resource function DoSomething1(&$connection) { ... } function DoSomething2($connection) { ... }
Ресурс PHP – это особый тип, который уже является ссылкой сам по себе. Передача его по значению или явно по ссылке не будет иметь никакого значения (т. Е. Она по-прежнему является ссылкой). Вы можете проверить это для себя в PHP4:
function get_connection() { $test = mysql_connect('localhost', 'user', 'password'); mysql_select_db('db'); return $test; } $conn1 = get_connection(); $conn2 = get_connection(); // "copied" resource under PHP4 $query = "INSERT INTO test_table (id, field) VALUES ('', 'test')"; mysql_query($query, $conn1); print mysql_insert_id($conn1)."<br />"; // prints 1 mysql_query($query, $conn2); print mysql_insert_id($conn2)."<br />"; // prints 2 print mysql_insert_id($conn1); // prints 2, would print 1 if this was not a reference
Это не та скорость, о которой вы должны беспокоиться, но память.
В PHP 4 такие вещи, как соединения с базой данных и результаты, должны быть явно переданы по ссылке. В PHP 5 это делается автоматически, поэтому вам не нужно делать это явным.
Кстати, методы singleton для создания дескрипторов баз данных – хорошая идея: вы можете сделать $db = & Database::Connection();
и всегда получите правильную ручку. Это избавит вас от использования глобального, и статический метод может сделать дополнительную магию (например, автоматически открыть ее) для вас. Просто будьте осторожны, когда ваше приложение масштабируется настолько, что ему нужно несколько баз данных: тогда ваша волшебная функция должна будет знать, как вернуть вам правильный. IME это не очень сложно; основной способ решить это для слоя кода, которому нужен дескриптор БД, чтобы знать, как запросить правильный.
Пошаговая привязка времени вызова обесценивается, поэтому я не буду использовать описанный метод. Кроме того, как правило, ресурсы передаются по ссылке в PHP 5 по умолчанию. Поэтому никаких ссылок не требуется, и вы никогда не должны открывать больше одного соединения с базой данных, если это вам действительно не нужно.
Лично я использую класс singleton-factory для моих подключений к базе данных, и всякий раз, когда мне нужна ссылка на базу данных, я просто вызываю Factory :: database (), поэтому мне не нужно беспокоиться о нескольких соединениях или передаче / получении ссылок.
<?php Class Factory { private static $local_db; /** * Open new local database connection * * @return MySql */ public static function localDatabase() { if (!is_a(self::$local_db, "MySql")) { self::$local_db = new MySql(false); self::$local_db->connect(DB_HOST, DB_USER, DB_PASS, DB_DATABASE); self::$local_db->debugging = DEBUG; } return self::$local_db; } } ?>
Соединение с базой данных фактически не содержит базовые значения, поэтому вам не нужно беспокоиться о потере назначений внутри функции. Метафорически вы можете думать о соединении с БД, как, скажем, номер ВПП – «ОК, DB Connection 12 очищается для использования для запроса» – запрос и результирующий набор используют соединение и могут нуждаться в эксклюзивном доступе для некоторое время, но соединение ничего не знает о базовых данных.
Несколько человек сказали, что вам не нужно беспокоиться об этом для PHP 5. Это неверно, если у вас есть OBJECT базы данных, который вы используете для всего доступа. В этом случае вам нужно пройти по ссылке, иначе он создаст новый объект базы данных, который (часто) создает новое соединение с базой данных.
Я обнаружил это с помощью XDebug & WinCacheGrind, который любезно отображает все деструкторы, которые вызываются – в моем случае – полдюжины или больше объектов базы данных.
Чтобы пояснить: причина, о которой я говорю, заключается в том, что это обычный способ использования соединений с базой данных, а не ресурс необработанного соединения.
у меня нет конкретного ответа для php, но в целом мне кажется, что вы захотите передать это по ссылке, если вы явно не уверены, что сталкиваетесь с проблемами производительности при передаче по значению.
Вообще говоря, ссылки не быстрее в PHP. Это распространенное заблуждение, потому что они семантически похожи на C-указатели, поэтому люди, знакомые с C, часто предполагают, что они работают одинаково. Не так. Фактически, ссылки немного медленнее копий, если только вы не назначаете эту переменную (что в любом случае является плохим стилем, если только переменная не является объектом).
PHP имеет механизм, называемый copy-on-write, что означает, что переменная на самом деле не копируется, прежде чем понадобится. Вы можете передать огромную структуру данных функции; Пока он только что читает, это не имеет значения. Однако для справки требуется дополнительная запись во внутренних регистрах, поэтому на самом деле потребуется дополнительная обработка (хотя и едва заметная).