Гру 262011
 

Fatal error: Trying to clone an uncloneable object of class mysqli

 

Причины

Интерпретатор PHP работает в режими совместимости с Zend Engine первой версии zend.ze1_compatibility_mode

 

Решение

Отключение режима совместимости с Zend Engine 1.

В php.ini изменить значение параметра

zend.ze1_compatibility_mode off
Либо через .htaccess, путем добавления строки:
php_flag zend.ze1_compatibility_mode off

Гру 252011
 

В чем разница между одинарной кавычкой (‘) и двойной кавычкой (“)?

Эту синтаксическую особенность можно продемонстрировать на примере

<?php
$var=10;
echo ‘1) Значение переменной: $var’;
echo ‘<br>’;
echo “2) Значение переменной: $var”;
?>

Даст результат:

1) Значение переменной: $var
2) Значение переменной: 10

 

Как видите, в первом случае PHP воспринял $var как текст, во втором – как имя переменной. Соответственно, на месте $var во втором случае мы увидели значение переменной $var, при чем если между двойными кавычками встречается символ $, обозначающий переменную, то PHP воcпримет следующий за ним набор символов (вплоть до первого символа, который не разрешен для имени переменной), как имя переменной. Если эта переменная не была объявлена, PHP сгенерирует ошибку.

Важная деталь: при двойных кавычках интерпретер не «всего-лишь» заменяет переменные и спецсимволы на их значение, а сначала ищет их во всём наборе символов от начала до конца. Так как при одинарных кавычках этого не происходит, то и обработка, соответственно, быстрей. При объёмных проектах разница во времени выполнения скрипта становится ощутимой.

Гру 252011
 

Генерирование уникальных ID

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

1.// generate unique string
2.echo md5(time() . mt_rand(1,1000000));

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

01.// generate unique string
02.echo uniqid();
03./* prints
04.4bd67c947233e
05.*/
06.
07.// generate another unique string
08.echo uniqid();
09./* prints
10.4bd67c9472340
11.*/

Можно заметить, что, хотя строки уникальны, они кажутся подобными из-за нескольких первых символов. Это оттого, что сгенерированная строка связана со временем сервера. Прекрасный побочный эффект, так как каждый заново сгенерированный id в дальнейшем следует в алфавитном порядке, так что их можно сортировать.

Чтобы уменьшить вероятность получения дубликатов, можно использовать префикс или второй параметр для увеличения энтропии:

01.// with prefix
02.echo uniqid('foo_');
03./* prints
04.foo_4bd67d6cd8b8f
05.*/
06.
07.// with more entropy
08.echo uniqid('',true);
09./* prints
10.4bd67d6cd8b926.12135106
11.*/
12.
13.// both
14.echo uniqid('bar_',true);
15./* prints
16.bar_4bd67da367b650.43684647
17.*/

Эта функция будет генерировать более короткие строки, чем md5(), что позволит сэкономить место.

 Posted by at 07:24  Tagged with:
Гру 252011
 

Предопределенные, или «волшебные» константы

PHP предусматривает полезные «волшебные» константы для выборки текущего номера строки (__LINE__), пути файла (__FILE__), пути каталога (__DIR__), имени функции (__FUNCTION__), имени класса (__CLASS__), имени метода (__METHOD__) и пространства имен (__NAMESPACE__).

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

Когда в дело включаются другие скрипты, хорошая идея – использование константы __FILE__ (или __DIR__ в версии PHP 5.3):

1.// этот код зависит от пути загруженного скрипт
2.// и может вызвать проблемы при использовании из других каталогов
3.require_once('config/database.php');
4.
5.// а этот код всегда относителен к пути текущего файла
6.// в независимости откуда он был включен
7.require_once(dirname(__FILE__) . '/config/database.php');

Использование __LINE__ облегчает отладку программы. Можно отследить номера строк:

01.// some code
02.// ...
03.my_debug("some debug message"__LINE__);
04./* prints
05.Line 4: some debug message
06.*/
07.
08.// some more code
09.// ...
10.my_debug("another debug message"__LINE__);
11./* prints
12.Line 11: another debug message
13.*/
14.
15.function my_debug($msg$line) {
16.echo "Line $line: $msg\n";
17.}
Гру 252011
 

Сведения об использовании CPU

Для этого мы будем пользоваться функцией getrusage(). Помните о том, что она недоступна на платформе Windows.

01.print_r(getrusage());
02./* prints
03.Array
04.(
05.[ru_oublock] => 0
06.[ru_inblock] => 0
07.[ru_msgsnd] => 2
08.[ru_msgrcv] => 3
09.[ru_maxrss] => 12692
10.[ru_ixrss] => 764
11.[ru_idrss] => 3864
12.[ru_minflt] => 94
13.[ru_majflt] => 0
14.[ru_nsignals] => 1
15.[ru_nvcsw] => 67
16.[ru_nivcsw] => 4
17.[ru_nswap] => 0
18.[ru_utime.tv_usec] => 0
19.[ru_utime.tv_sec] => 0
20.[ru_stime.tv_usec] => 6269
21.[ru_stime.tv_sec] => 0
22.)
23.
24.*/

Может выглядеть таинственно, пока у вас не будет навыков в администрировании системы. Вот объяснение каждого значения (учить это наизусть не нужно):

ru_oublock: количество операций блочной записи

ru_inblock: количество операций блочного чтения

ru_msgsnd: количество отправленных сообщений

ru_msgrcv: количество принятых сообщений

ru_maxrss: максимальный размер невыгружаемого набора

ru_ixrss: общий объем разделяемой памяти

ru_idrss: общий объем неразделяемых данных

ru_minflt: количество используемых страниц памяти

ru_majflt: количество ошибок отсутствия страниц

ru_nsignals: количество принятых сигналов

ru_nvcsw: количество переключений контекста процессом

ru_nivcsw: количество принудительных переключений контекста

ru_nswap: количество обращений к диску при подкачке страниц

ru_utime.tv_usec: время работы в пользовательском режиме (микросекунды)

ru_utime.tv_sec: время работы в пользовательском режиме (секунды)

ru_stime.tv_usec: время работы в привилегированном режиме (микросекунды)

ru_stime.tv_sec: время работы в привилегированном режиме (секунды)

Чтобы узнать, какие ресурсы CPU потребляет скрипт, нам нужно посмотреть на значения ‘user time’ (время работы в пользовательском режиме) и ‘system time’ (время работы в привилегированном режиме). По умолчанию величины секунд и миллисекунд представляются раздельно. Таким образом, вы можете разделить значение микросекунд на 1 миллион и добавить к значению секунд, чтобы вычислить общее количество секунд как десятичное число.

Рассмотрим пример:

01.// sleep for 3 seconds (non-busy)
02.sleep(3);
03.
04.$data getrusage();
05.echo "User time: ".
06.($data['ru_utime.tv_sec'] +
07.$data['ru_utime.tv_usec'] / 1000000);
08.echo "System time: ".
09.($data['ru_stime.tv_sec'] +
10.$data['ru_stime.tv_usec'] / 1000000);
11.
12./* prints
13.User time: 0.011552
14.System time: 0
15.*/

Хотя выполнение скрипта заняло примерно 3 секунды, использование CPU было очень-очень низким. Это происходит потому, что во время ожидания (sleep) скрипт фактически не потребляет ресурсов CPU. Существует множество других задач, которые могут занять реальное время, но при этом не использовать время CPU, например ожидание дисковой операции. Так что, как вы видите, использование CPU и действительная длительность времени исполнения – не всегда одно и то же.

Вот другой пример:

01.// loop 10 million times (busy)
02.for($i=0;$i<10000000;$i++) {
03.
04.}
05.
06.$data getrusage();
07.echo "User time: ".
08.($data['ru_utime.tv_sec'] +
09.$data['ru_utime.tv_usec'] / 1000000);
10.echo "System time: ".
11.($data['ru_stime.tv_sec'] +
12.$data['ru_stime.tv_usec'] / 1000000);
13.
14./* prints
15.User time: 1.424592
16.System time: 0.004204
17.*/

Этот скрипт использовал примерно 1,4 секунды времени CPU, и почти все время в пользовательском режиме, так как системных вызовов не было.

Время работы в привилегированном режиме (System Time) – это количество времени, которое CPU тратит на выполнение системных запросов к ядру от имени программы. Вот пример этого:

01.$start = microtime(true);
02.// keep calling microtime for about 3 seconds
03.while(microtime(true) - $start < 3) {
04.
05.}
06.
07.$data getrusage();
08.echo "User time: ".
09.($data['ru_utime.tv_sec'] +
10.$data['ru_utime.tv_usec'] / 1000000);
11.echo "System time: ".
12.($data['ru_stime.tv_sec'] +
13.$data['ru_stime.tv_usec'] / 1000000);
14.
15./* prints
16.User time: 1.088171
17.System time: 1.675315
18.*/

Теперь у нас используется довольно много времени привилегированного режима. Это происходит по тому, что скрипт много раз вызывает функцию microtime(), которая, чтобы получить данные о времени, выполняет запросы к ядру операционной системы.

Еще вы можете заметить, что цифры соответствуют 3 секундам неточно. Это потому что на сервере также, возможно, выполнялись и другие процессы, так что скрипт не использовал 100% CPU в течение всех 3 секунд.

 Posted by at 07:12