Передача соединения с базой данных по ссылке в PHP - PullRequest
11 голосов
/ 27 октября 2008

Вопрос в том, должно ли соединение с базой данных передаваться по ссылке или по значению?

Для меня я специально задаю вопрос о подключении PHP к MySQL, но думаю, что это применимо ко всем базам данных.

Я слышал, что в PHP, когда вы передаете переменную функции или объекту, она копируется в память и поэтому сразу же использует вдвое больше памяти. Я также слышал, что оно копируется только после внесения изменений в значение (например, добавление / удаление ключа из массива).

В соединении с базой данных, я думаю, оно изменяется внутри функции, так как запрос может изменить такие вещи, как последний идентификатор вставки или число строк. (Я предполагаю, что это другой вопрос: хранятся ли в соединении такие вещи, как число строк и идентификатор вставки, или реальный вызов возвращается в базу данных?)

Итак, имеет ли значение память или скорость, если соединение передается по ссылке или по значению? Имеет ли значение PHP 4 против 5?

// $connection is resource
function DoSomething1(&$connection) { ... }
function DoSomething2($connection) { ... }

Ответы [ 7 ]

16 голосов
/ 27 октября 2008

Ресурс 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
5 голосов
/ 28 октября 2008

Вам нужна не скорость, а память.

В PHP 4 такие вещи, как соединения с базой данных и наборы результатов, должны явно передаваться по ссылке. В PHP 5 это делается автоматически, поэтому вам не нужно делать это явно.

Кстати, одноэлементные методы для создания дескрипторов базы данных - хорошая идея: вы можете сделать $db = & Database::Connection(); и всегда получить правильный дескриптор. Это избавляет вас от использования глобального и статический метод может сделать дополнительную магию (например, открывая его автоматически) для вас. Просто будьте осторожны, когда ваше приложение масштабируется настолько, что ему нужно несколько баз данных: тогда ваша волшебная функция должна знать, как вернуть вам правильную. IME это не очень сложно; Основной способ решить эту проблему - для уровня кода, которому нужен дескриптор БД, чтобы узнать, как запросить правильный.

4 голосов
/ 27 октября 2008

Передача по ссылке во время разговора устарела, поэтому я бы не стал использовать метод, описанный вначале. Также, вообще говоря, ресурсы передаются по ссылке в 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;
}
}
?>
1 голос
/ 28 октября 2008

Несколько человек сказали, что вам не нужно беспокоиться об этом для PHP 5. Это неверно, если у вас есть ОБЪЕКТ базы данных, который вы используете для любого доступа. В этом случае вам нужно передать по ссылке, в противном случае он создает новый объект БД, который (часто) создает новое соединение с базой данных.

Я обнаружил это с помощью XDebug & WinCacheGrind, который любезно показывает все вызываемые деструкторы - в моем случае, полдюжины или более объектов базы данных.

Чтобы уточнить: причина, по которой я указываю на это, заключается в том, что это обычный способ использования соединений с базой данных, а не необработанного ресурса соединения.

1 голос
/ 27 октября 2008

База данных соединение на самом деле не содержит базовых значений, поэтому вам не нужно беспокоиться о потере присваиваний, сделанных внутри функции. Метафорически, вы можете думать о соединении БД как, скажем, номер ВПП - «ОК, соединение БД 12 очищено для использования в запросе» - запрос и набор результатов используют соединение, и ему может понадобиться эксклюзивный доступ некоторое время, но соединение ничего не знает о базовых данных.

0 голосов
/ 28 октября 2008

Вообще говоря, ссылки не быстрее в PHP. Это распространенное заблуждение, потому что они семантически похожи на указатели C, поэтому люди, знакомые с C, часто предполагают, что они работают одинаково. Не так. На самом деле, ссылки немного медленнее копий, если только вы на самом деле не присваиваете переменную (что в любом случае является плохим стилем, если переменная не является объектом).

В PHP есть механизм, называемый copy-on-write, что означает, что переменная не на самом деле не скопирована до того, как это потребуется. Вы можете передать огромную структуру данных в функцию; Пока это только читает из этого, это не имеет никакого значения. Ссылка, однако, нуждается в дополнительной записи во внутренних регистрах, так что на самом деле потребуется некоторая дополнительная обработка (хотя это едва заметно).

0 голосов
/ 27 октября 2008

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...