Новый релиз PHP 5.3.1

19 ноября команда разработчиков PHP представила новый релиз PHP 5.3.1 направленный на увеличение стабильности ветки 5.3.x По завялениям разработчиков исправлено более 100 ошибок, некоторые из которых связаны с безопасностью. Всем рекомендуется обновиться до этой версии.
Вот некоторые из изменений:

  1. Добавлена директива “max_file_uploads” в php.ini, которая может установить количество запросов при закачке файлов, для предотвращения DOS атак.
  2. Исправлен обход режима safe_mode в tempnam()
  3. Исправлен обход “open_basedir” директивы в функции posix_mkfifo
  4. Исправлено отсутствие safe_mode_include_dir

Более подробный лог изменений здесь.

Работа с сессиями в PHP или пошагово задаем данные.

Помните экран установки windows? Пошаговая настройка, удобнейшая вещь в некоторых случаях. При разработке WEB-сайтов, такое тоже весьма уместно применять. Ведь пользователю не важно как все устроено внутри, главное-чтобы ему было удобно и интуитивно понятно, и, такие интерфейсы удовлетворяют этим условиям. Но как же их реализовать? Ведь у нас есть фактически лишь три метода передачи: POST, GET и COOKIE. Ну не пихать же эти данные в тело страницы, в адресную строку…и уж упаси Боже в печенье. Это еще можно сделать с 1-3 переменными, а если данных очень много-все, пиши-пропало. Но, разработчики PHP тоже не лыком шиты, они придумали механизм который способен хранить данные, причем, он хоть и основан на работе с файлами, с сериализованными массивами, довольно сильно облегчает жизнь разработчику. Что же это такое? Это сессии. Подробнее »

MySQL, или удобное хранение данных.

Собственно, что такое MySQL? Это средство для удобного хранения информации. Согласитесь с файлами работать неудобно, а особенно это неудобство чувствуется если их очень много. А MySQL спокойно справляется с 25-гигабайтной базой..не без напрягов конечно, но в целом весьма неплохо.
Итак SQL-Структурированный Язык Запросов. “Почему же я заговорил о нем, ведь данный ресурс посвящен PHP”,-думаете вы. Да все просто. В PHP очень хорошо реализована схема работы c базами данных (БД) MySQL. Приведу простой пример, если вы ничего не понимаете в MySQL не расстраивайтесь, пока вам это и не нужно, позднее постараюсь немного обьяснить что к чему. Сейчас лишь разберитесь как с ним общается PHP.


<?php

if(!mysql_connect('server','username','password')) die('Невозможно подключиться к БД');

//Подключаемся к mysql серверу.

if(!mysql_select_db('dbname')) die('База данных не найдена');

//выбираем базу данных с которой будем работать.

$query mysql_query("SELECT * FROM table_name WHERE id>0;");

//посылаем запрос к MySQL 

if(mysql_num_rows($query))



//mysql_num_rows возвращает количество строк выбранных в БД

    
while($data mysql_fetch_assoc($query))

    {

        
//В цикле берем результат запроса в массив и выводим

        print '<pre>';

        print_r($data);

        print '</pre><br/>';

    }

}

?>

Итак что же за белиберда здесь написана? Для начала нам надо подсоединиться к MySQL для этого используем mysql_connect, где первый параметр сервер к которому подключаемся, второй-имя пользователя БД, третий-пароль пользователя БД. После чего выбираем БД с которой хотим работать с помощью mysql_select_db. Далее, шлем составленный нами, запрос к серверу. Получаем идентификатор (ресурс id наподобие идентификатора открытого файла) и читаем результаты в массив при помощи цикла while и оператора mysql_fetch_assoc. Но перед этим, чтобы цикл нам не выдал ошибки, нужно проверить, а есть ли вообще результаты. В этом поможет функция mysql_num_rows, которая считает количество результатов, возвращенных MySQL. Конечно это примитивный пример, но функции эти основные, без которых освоиться с MySQL будет просто нереально. Настоятельно рекомендую почитать в мануале как они ведут себя.
Так же, часто можно использовать вместо mysql_fetch_assoc другую функцию mysql_fetch_array, которая в зависимости от параметра создает или ассоциативный или пронумерованный или смешанный массив результатов. Достаточно часто это бывает очень удобно. При работе с базами данных надо всегда помнить, что большое количество запросов, или очень сложные запросы, могут сильно напрячь сервер и, если вы хоститесь, у обыкновенного хостера, а не на ВДС или Дедике надо как можно сильнее оптимизировать работу с MySQL. К примеру настоятельно не рекомендуется использовать в цикле запросы, даже очень простые. На странице, на мой взгляд, не должно быть более 20-30 запросов (в зависимости от посещаемости ее пользователями, возможно, если нельзя отказаться от запросов, стоит как-то кэшировать ее) . Ну на этом пожалуй закончу, ибо о MySQL можно говорить довольно долго и существует очень много различных аспектов работы с ней. В дальнейшем постараюсь вернуться к этому вопросу и, как можно более подробно, в рамках моего ресурса разумеется, описать MySQL

Ускорение работы сценариев PHP

Любой уважающий себя программист должен понимать, что сервер имеет конечное число ресурсов, которые рано или поздно заканчиваются. Поэтому требуется как можно тщательнее оптимизировать программный код, дабы потом не хвататься за голову и не сокрушаться что сервера не справляются. Каким же образом оптимизировать код? На самом деле, если не затрагивать MySQL (о чем надо, я считаю, говорить отдельно), способов оптимизации не так уж и много. Точнее их не мало, но результат от них, по отдельности очень маленький, а суммарно, как говорится, “копейка рупь бережет”.. Сейчас я хочу перечислить то, что знаю, и чем очень часто пользуюсь.

  1. Вы должны осознавать что при преобразованиях (preg_replace, str_replace) регулярки используют гораздо больше ресурсов чем строковые функции, поэтому рекомендую там где можно обойтись использовать именно str_replace или str_ireplace
  2. Помните о том, что в большинстве случаев, если все же надо использовать регулярку preg_match работает быстрее чем eregi
  3. Незачем генерировать файлы содержащие большие обьемы данных, если часто с ними надо работать сценарию. Гораздо лучше использовать множество мелких файлов. Хотя и в количестве файлов надо стараться знать меру.
  4. Незачем повторно выполнять одни и те же действия если вы можете создать переменную, которая будет содержать результат действия.
  5. Надо помнить, что например функция echo при выводе работает быстрее чем print, а вывод заключенный в одиночные кавычки работает быстрее чем в двойные. Связано это с тем, что в двойных кавычках текст еще и обрабатывается (переменные преобразуются), а в одиночных выводится как есть.
  6. Не стоит вводить переменные с длинными именами, в дальнейшем это может аукнуться весьма сильно.

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

Как я прикручивал php мануал (часть 2)

Прошу прощения за продолжительный перерыв, но к сожалению затянула рутина и работа, просто физически не было времени продолжать писать здесь.
Итак сегодня я хочу продолжить свой рассказ о том как я прикручивал мануал на данный ресурс.
В прошлой статье я описал, как возможно преобразовать html мануал под свои нужды. Надеюсь, что вы разобрались, что к чему. Ну что ж продолжим.
Мне требовалось интегрировать страницу в тело вордпресса. Они уже были подготовлены для этого, но полностью страница html мне была не нужна. Надо было выдернуть лишь часть ее внутри тэгов body. Вот тут-то мне и понадобились регулярки. Нет можно было конечно не осваиваться с регулярками, а взять мою любимую функцию explode и с ее помощью все сделать, но это было бы нудно, и, некрасиво. Согласитесь гораздо приятнее, когда весь код выглядит “элегантно”. Вот примерно такая функция работает у меня при запросах к мануалу php:


<?php

function HTML2WPDo()

{

    
preg_match('@([0-9A-Za-z_\.\s]+)@i',$_POST['search'],$search);

    
$search $search[1];

    
preg_match('@([\d\w_\.\s\-]+)@i',urldecode($_SERVER['QUERY_STRING']),$page);

    
$page $page[1];

    
//print $page;

    
$dir get_option('dir4html');

    
$abs_dir $_SERVER['DOCUMENT_ROOT'].'/'.$dir;

    if(
$search)

    {

        
$search str_replace('_','-',$search);

        
$content_file 'function.'.$search.'.html';

        if(
file_exists($abs_dir.$content_file))

        {

            
$man_func file_get_contents($abs_dir.$content_file);

        }

        else 
$content 'Произошла ошибка. Функция с подобным именем не найдена!';

    }

    else 

    {

        if(!
$page$page 'index';

        if(
file_exists($abs_dir.$page.'.html'))$man_func file_get_contents($abs_dir.$page.'.html');

    }

    
$count preg_match("|<body([^>]*)>(.*?)<\/body\s*>|si",$man_func,$func_body);

    if(
$count

    {

        
$content $func_body[2];

        
$func_body '';

    }

    return 
$content;    

}

?>

Что же она может? Данный алгоритм может как искать по имени функции, так и просто отдавать требуемые страницы. Хочу заметить что сделано все достаточно примитивно, ибо мне не нужны были какие-то изыски, единственное на данный момент что я хочу доработать это чтобы для каждой страницы в мануале генерился свой title и meta-description, но пока к сожаленеию не дошли руки. Ну это все на будущее, а теперь рассмотрим то что есть.
Первая строка:


<?php

preg_match
('@([0-9A-Za-z_\.\s]+)@i',$_POST['search'],$search);

?>

Здесь в строке поиска (элемент массива POST с ключом search) мы смотрим чтобы значение соответствовало шаблону(только цифры, латинские символы, точка, пробел, нижнее подчеркивание). Результат в виде массива помещается в переменную $search. Если выражение будет соответствовать то первый элемент массива как раз и будет содержать его.
Дальше подобную же проверку проходит элемент глобального массива $_SERVER['QUERY_STRING'] (для запросов к различным страницам мануала используется именно этот элемент).
После чего нам требуется получить дирректорию в которой лежит мануал. Так как все написано под вордпресс то я воспользовался функцией WP которая получает сохраненные в админке данные(дирректорию в данном случае).


<?php

$dir 
get_option('dir4html');

$abs_dir $_SERVER['DOCUMENT_ROOT'].'/'.$dir;

?>

Далее если переменная $search не пустая-проверяем существует ли файл с такой функцией (все файлы мануала имеют удобное для нас имя. function.имя функции.html), если такой файл существует-читаем его в строку.
В ином случае:
если не задана $page выдаем индекс;
иначе ищем файл с таким названием и если существует читаем в строку.
Ну, а дальше самое “сладкое”:


<?php

$count 
preg_match("|<body([^>]*)>(.*?)<\/body\s*>|si",$man_func,$func_body);

?>

регулярное выражение. Так как у боди могут быть параметры используем ([^>]*)
т.е любой символ, но не “>” и данные символы могут повторяться 0 или более раз (благодаря “*”).
(.*?) – это означает любой символ любое количество раз. Ну и ищем все это в переменной $man_func и пишем в $func_body. Таким образом $func_body[2] будет содержать именно то, что нам надо. (почему читайте в предыдущей статье цикла) Ну и собственно возвращаем результат обработки:


<?php

return $content;

?>

Все готово. Функция простая как топор. :) Пишите свои комментарии, пожелания, указывайте на замеченные недостатки. Всегда буду рад обсудить.