Заказать php скрипт вы можете на сайте PHPZakaz.Net
PHP можно установить в двух вариантах: как отдельный интерпретатор, работающий через интерфейс CGI, или как модуль веб-сервера, встроенный в сам сервер. В последнем случае становятся актуальными все преимущества PHP.
Из аналогичных встроенных в сервер программных средств хорошо известны SSI, mod_perl, ASP. Но SSI обладает довольно ограниченными возможностями, а mod_perl, на мой взгляд, слишком много умеет. Ближайшим аналогом PHP является ASP, но технология ASP не прижилась в мире Unix/Apache, где простой, удобный и быстрый язык PHP постепенно завоевывает первые ряды.
Как и все процедурные языки, PHP можно разделить на собственно язык и библиотеку функций. Существует большое количество инструментальных средств для PHP, интерфейсы ко всем популярным СУБД, почтовым протоколам, к разделяемой памяти, графическим файлам, архивам и множество других инструментов.
Скрипт на PHP представляет собой файл, как правило, с суффиксом .phtml, .php3 или .php, который внутри выглядит как обычная страница на HTML. Отличие проявляется только в виде хитрого тега , делающего из HTML настоящий язык программирования. Часто применяют сокращенную форму или, для совместимости с визуальными средствами формирования страниц, <% %>. Будем ра-зумно придерживаться традиции и пользоваться тегом . Внутри этого тега располагается код на языке PHP.
Посетителю такой страницы будет показан документ с картинками, меню и текстом, красиво упакованным в хитро вложенную таблицу. Отдельные файлы header.html и footer.html будут просто включены в тот документ, что отдается сервером посетителю страницы. Таким образом можно отделить оформление страницы от ее наполнения, сильно облегчая работу по внесению информации на сайт даже неквалифицированным работникам.
Текст скрипта выполняется сверху вниз и справа налево, последовательно. Эта последовательность может быть изменена операторами цикла и условными операторами. Например:
Тебя зовут
Вася
капитан Немо
Здесь мы получим текст "Тебя зовут Вася" или "Тебя зовут капитан Немо" в зависимости от значения переменной $name.
В примере видно, что мы прервали текст тегами PHP. В языке есть несколько функций вывода - echo, printf и др., но приведенный в примере код работает намного быстрее, чем, например, if ($name=='Вася') echo 'Вася'.
Перевод строки, идущий после закрытия тега ?>, интерпретатор пропускает. Сделано это для удобства форматирования исходных текстов скриптов.
Переменные в PHP отличаются наличием символа $ (доллар) перед именем самой переменной. Объявлять их никак не надо, так как они создаются автоматически при присвоении им значения и удаляются при выходе из области действия. Переменные бывают типа строка, число, массив и объект. Некоторые трудности может вызвать нестрогое отличие строк от чисел. Поясню на примере:
$a=5; // Число
$b='6b'; // Строка
$c=$b.$a; // Строка: '6b5'
$d="$a$b"; // Строка: '56b'
$e=$a+$b; // Число: 11
$f=$b+$a; // Число: 11
?>
Интерпретатор очень вольно приводит типы строка и число друг к другу. Хотя чаще всего это даже удобно. Просто надо об этом помнить и не пытаться сравнивать строку с числом:
$a=5;
$b='ой!';
if ($a>$b) echo "1";
if ($b>$a) echo "2";
?>
В первом случае сравниваются числа 5 и 0 и результат, естественно, положительный. А во втором случае что сравнивается? Документация на этот счет молчит, а эксперимент показывает, что сравниваться будут тоже числа. Согласен, что это не строго и не очень красиво, и в условных операторах я рекомендую использовать операторы приведения типа, как в языке Cи.
Синтаксис языка PHP вообще очень похож на синтаксис Си, если бы не символы $ в начале имени переменных и некоторые вольности с типами и масси-вами. Как в "Поднятой целине" председатель колхоза английский учил: "... Анг-лийские слова такие же, как русские, только в конце шипение какое-то, революшн, например..."
Для изменения типа переменной, в принципе, особенного ничего делать не надо, достаточно просто присвоить ей значение нового типа:
$a=5; // Целое число
$a='5'; // Строка
$a=5.5; // Вещественное число
$a[0]=5; // Массив
$a['пять']=5; // Хэш-массив
?>
Последняя строка, например, показывает нам очень популярный и удобный тип данных - хэш-массив (hash array). В принципе, это обычный массив, только индексом у него выступает строка, а не целое число, и никакого приведения ти-пов, о котором я говорил ранее, здесь нет. PHP позволяет создавать многомерные сооружения вида массив хэш-массивов, как, например, $name[5]['ой'][6]= 'не мо-жет быть';
В принципе, массив - это тоже хэш, только в нем индексами являются строки, соответствующие числам. Почему так хитро? Это еще ничего, а вот, напри-мер, фраза $name[5]=0; создает массив $name из 6 элементов (индексы считаются от 0, как в Си), но только 1 элемент реально существует, остальные просто не определены. На практике это не сильно мешает, помните только, что это не Cи и не Паскаль.
Конечно, не очень хорошо, но частенько удобно пользоваться конструкциями вместо правильной.
просто потому, что первая запись короче. В первом случае, если переменная $test будет не определена, то ее значение будет как бы пустой строкой. Ло-гично считать, что "никакая" строка - это тоже пустая. Подобная фраза может вызвать предупреждение о синтаксической ошибке, если администратор включил параноидальный контроль синтаксиса, но это бывает редко. Если вам не лень, то пользуйтесь правильными конструкциями и проверяйте наличие переменной перед обращением к ней. А если лень, то считайте неопределенную переменную пустой строкой, нулем, логической ложью и т. п.
Как-то специально объявлять массив или хэш тоже не надо. Но в некоторых случаях это бывает полезно, например, если ваша функция возвращает массив, то она должна вернуть именно массив, а не неопределенное значение. Это, кстати, относится и к функциям:
0) return $a[$num]=$num;
return $a;
}
?>
Эта надуманная функция возвращает массив, если $num больше нуля, и не-пределенное значение - в противном случае, что затрудняет работу с результатом ее выполнения:
$foo=initArray(0);
...
$bar=$foo[0]; // Ошибка, $foo не массив.
...
?>
Здесь поможет функция array(), возвращающая массив, в том числе и пус-той. Либо стоит сразу инициализировать переменную $a=array() или вернуть пус-той массив как return array(). Первый вариант предпочтительнее.
В PHP есть даже некоторая объектность, то есть вы можете создавать клас-сы, методы и т. д. Как правило, классы хороши в больших приложениях или как средство ограничения области видимости переменных. Я бы не рекомендовал очень уж активно ими пользоваться: помните, что объектный подход нынче очень моден, но не стоит из него делать фетиш. Реализация классов в PHP версии 4 обещает быть намного эффективнее, чем в третьей. Поживем - увидим.
Как и для скриптов на языке Perl, в Интернете есть множество сайтов, со-держащих десятки готовых PHP-программ. Такие ресурсы делятся на два вида: наборы функций или классы, - что отражает идеологический подход авторов к программированию.
Программа на языке PHP, как правило, не живет сама по себе, а применяет-ся для обработки запросов через интерфейс CGI. Даже если интерпретатор PHP встроен в сервер как модуль, с точки зрения самой пользовательской программы, она, эта программа, работает через CGI. Конечно же, для обработки форм. Имен-но на скрипт указывет параметр action-тега.
По умолчанию и чаще всего форма передается HTTP-методом POST. А ста-тические страницы посетитель обычно получает методом GET. В последнем слу-чае вы тоже можете передавать "параметры" выполняющемуся скрипту через так называемую строку запроса (query string), то есть через URL. Выглядит такой URL как-то так: www.domain.ru/script.phtml?a=5&b=no&c=%2f.
Собственно параметры начинаются после знака "?" и состоят из пар "имя=значение", разделенных знаком "&". Как и в случае с полями формы, про-грамма script.phtml получит переменные $a, $b и $c с соответственным содержи-мым "5", "no" и "/". Обратите внимание на значение переменной $c. Вообще-то лучше не полениться и, зайдя на сайт www.w3c.org, вдумчиво прочитать доку-ментацию о протоколе HTTP/1.0. Это очень поможет вам в профессиональном росте.
Передавать данные скрипту можно не только посредством параметров в URL или в полях формы. Практически все современные броузеры понимают cookies. В PHP вы можете пользоваться ими совершенно свободно. Когда броузер отдает cookie вашему скрипту, вы просто получаете переменную с именем cookie и значением, соответствующим значению cookie. Отдать же cookie броузеру вы можете функцией
setcookie('имя','значение' [,необязательные параметры])
Помните, что эта функция должна выполняться до любого вывода текста страницы.
PHP позволяет с помощью cookies хранить в броузере клиента множество информации. Для этого реализован механизм cookies-массива. Например, после однократного выполнения такого фрагмента кода:
$myData['id']=1234;
$myData['name']='Вася';
$myData['email']='qq@xxx.ru';
setcookie('myData[]',$myData);
?>
все ваши скрипты будут иметь в начале выполнения хэш-массив $myData с точно тем же содержимым. Помните, что количество информации в cookies огра-ничено, так что старайтесь ими не злоупотреблять. Да, и не храните в cookies текст на русском языке или двоичную информацию, лучше предварительно зако-дируйте ее с помощью функции rawurlencode().
Если же вам очень хочется завести о пользователе целую уйму персональ-ных данных, а использовать для этого cookies неудобно, то вам стоит выбрать од-ну из схем "ведения пользователя" (user tracking). Их существует множество - это и модули к www-серверу, и отдельные библиотеки к PHP, и множество готовых функций или классов, написанных на самом PHP. Вы легко можете сделать и свою систему ведения. Вот вам простенький примерчик. Включив этот файл в на-чало любого скрипта, вы можете вести пользователей, сохраняя информацию о пользователе в течение года.
В результате мы получим хэш-массив со всеми заданными нами настрой-ками посетителя. Базы данных dbm* работают очень быстро и не требуют боль-ших ресурсов, и пользоваться ими можно и нужно. Мы могли бы использовать для хранения данных СУБД, но пока не будем. В данном случае применение SQL СУБД оправдано, если большая часть ваших страниц также формируется из базы данных. Сейчас стало очень модно применять SQL-серверы где угодно, там где надо и где не надо (чаще всего, где не надо). Даже www-чаты на SQL-базах дела-ют. При небольших объемах данных стоит подумать о простых средствах: тек-стовых файлах, хэш-базах (dbm*) и т. п. Прочитать файл в 100 К в память и по-рыться в ней будет намного быстрее, чем даже 1 запрос к SQL-базе. О пользова-нии СУБД я расскажу несколько позже.
А пока немного о файлах. Внешний по отношению к скрипту файл можно включить в скрипт функцией include(). Но всегда хочется большего. Например, вы гениальный дизайнер, вы нарисовали шикарный сайт некой фирме, но вам очень не хочется обновлять каждую неделю их прайс-лист. Вы можете за обнов-ление брать деньги, но много денег за это брать стыдно (я надеюсь), а повозиться придется. Как быть? А как готовят прайс-лист в той фирме? Скорее всего, у них есть некая таблица в неком табличном редакторе типа 1-2-3 или Excel. Вот его бы и положить на сайт... Но файл этот хитрого формата, да и размера немалого.
Владея PHP, вы можете легко уйти от рутины. Любой табличный процессор позволяет сохранять листы как текст с разделителями-табуляциями. А вот как та-кой файл красиво вывести в виде таблицы со строчками разного цвета.
PHP имеет достаточное количество встроенных функций для работы с фай-лами, но частенько хочется этот набор несколько расширить. Например как сде-лать www-чат? В теории все просто, все посетители пишут в один файл и читают последние N строк этого файла. Конечно, хотелось бы читать этот файл не после-довательно с начала. Я предлагаю вашему вниманию функцию tail(), которая ра-ботает очень быстро не зависимо от размеров читаемого файла.
$flen) $pos=0;
else $pos=$flen-($num*$appxlen);
$out=_readfile($fp,$pos,$num); // читаем строчки до конца файла
// на следующий цикл длиной строки считаем удвоенную среднюю
прочитанную
$appxlen=($flen-$pos+1)*$num*2/count($out); // *!*
} while (count($out)!=$num && $pos!=0);
fclose($fp);
}
return $out;
}
// вспомогательная функция
// читает файл $fp с позиции $pos и максимум $num строк
function _readfile($fp,$pos,$num) {
fseek($fp,$pos); // позиционируем файл
$tmp=array(); // временный массив
while (!feof($fp)) { // читаем файл до конца
$line=chop(fgetsl($fp)); // *!!*
$tmp[]=$line;
}
$j=count($tmp)-$num; // кол-во лишних строк
if ($pos!=0 && $j==0) { // если ровно сколько надо строк,
$j++; // пропустить первую неполную
}
if ($j<0) { // если не хватает строк,
$j=0; // выводить все
$xnum=$num-1;
} else $xnum=$num;
// переписать в выводной массив нужные строки.
for ($i=0; $i<$xnum && $j
Я не буду утверждать, что это лучший на свете алгоритм, и принимаю все предложения по его улучшению. Есть два замечания сразу.
*!* Здесь вычисляется средняя длина строки для следующего цикла. У меня это отлично работало и при $appxlen*=2, но так, наверно, быстрее будет. *!!* Здесь я применил функцию fgetsl(), но это особый разговор.
Функция чтения строки из файла имеет ограничение на длину считываемой строки. А думать о длинах строк при написании гениальных скриптов не хочется. Как быть? Я предлагаю небольшую функцию, аналогичную fgets(), но без непри-ятного ограничения:
function fgetsl($fp) {
while (!feof($fp) && strchr($out,"\n")) $out.=fgets($fp,1000);
return $out;
}
?>
Если вы решили продавать содержимое сайта или просто ограничить дос-туп к некоторой его части по паролю, то имеется возможность контролировать этот процесс с помощью PHP. Вопрос авторизации решается в PHP элегантно и просто. Я один раз оформил нужный фрагмент кода как включаемый файл и ис-пользую его уже больше года. Здесь я приведу код в несколько сокращенной об-щей форме.
Функцию authFunction() пишет сам пользователь, она получает аргумента-ми, соответственно, логин и пароль, введенные посетителем, и два необязатель-ных параметра по наследству от authCheck(). Автор скрипта должен просто вклю-чить файл auth.inc в свою программу, написать функцию authFunction(), которая, например, будет проверять пользователя по базе данных, и вызвать функцию authCheck() перед каким-либо выводом текста страницы, как было замечено про функцию setcookie(). Написание разных authFunction() позволяет контролировать доступ посетителей из множества различных источников, таких как файлы паро-лей, СУБД, хэш-файлы, запросы к сетевым сервисам авторизации, и из любых на ваше усмотрение.
Такой тип авторизации самый, так сказать, железный. При посещении за-крытой страницы посетителю выдается диалоговое всплывающее окно с полями имени и пароля. В дальнейшем броузер запоминает $realm и при последующем запросе пароля будет автоматически отправлять серверу пару имя/пароль. Однако это не единственный способ авторизации. Пример писать не буду, а просто поте-оретизирую немного. Описанная выше система ведения пользователя вполне по-дойдет с небольшими модификациями. Для регистрации создадим форму с поля-ми login и password. Обработчик формы генерирует случайный уникальный ключ и записывает с ним дату/время регистрации в хэш-файл. Вместо даты и времени годится значение функции time(), возвращающей количество секунд с 01.01.1970. Броузеру клиента выдается cookie, например, xfile со значением только что сгене-рированного ключа. Каждая страница, требующая авторизации, должна прове-рить наличие ключа $xfile в хэш-файле и, если он есть, записать туда время об-ращения, не затрагивая времени регистрации.
Для отказа от авторизации достаточно удалить ключ из базы. Внешняя про-грамма может раз в полчаса, допустим, удалять ключи, выданные 3 часа назад, и ключи, к которым не было обращения в течение 1 часа. Стойкость такой системы определяется трудностью подбора ключа-cookie за ограниченное время, так как ключи живут относительно недолго и они достаточно длинные. Ключ можно пе-редавать не только через cookie, но и через URL как параметр скрипта.
Конечно, гениальный автор сайта сам должен решить, какой алгоритм ав-торизации он себе выберет, так как у обоих вариантов есть свои плюсы и минусы. Возможно, есть еще какие-либо варианты. Пишите, обсудим.
В общем-то ведение пользователя и авторизация - это ключ к созданию электронного магазина. Может быть, об этом я тоже когда-нибудь напишу.
PHP поддерживает множество СУБД от xBase до дорогих коммерческих SQL-серверов. Особого внимания заслуживают такие базы, как MySQL (www.tcx.se) и PostgreSQL (www.postgresql.org) - по причине их популярности, хороших характеристик и бесплатности. Легкодоступность СУБД и интерфейса к ней побуждает юные умы применять базу данных направо и налево, не особенно задумываясь о необходимости применения и об алгоритмах работы с базой.
Самая распространенная ошибка авторов скриптов - это отношение к СУБД как к чему-то сверхоперативному. А это вовсе не так. Вот пример, как не надо пи-сать скрипты:
1 pg_pconnect("host=localhost dbname=test");
2 $s1=pg_exec("select a from b");
3 for ($i=0; $i
4 $a=pg_result($s1,$i,0);
5 $s2=pg_exec("select c,x,y,z from d where e=$a");
6 for ($j=0; $j
7 $c=pg_result($s2,$j,0);
8 $x=pg_result($s2,$j,1);
9 $y=pg_result($s2,$j,2);
10 $z=pg_result($s2,$j,3);
11 echo "$c $x $y $z
\n";
}
}
?>
1 - надо трижды подумать, прежде чем иcпользовать постоянное соедине-ние с базой. Здесь выбран хост localhost, но работа с локальным сервером через unix socket может быть быстрее.
2 - надо проверить, выполнился ли запрос без ошибок.
3 - нехорошо вызывать функцию в цикле, лучше завести дополнительную переменную $num=pg_numrows($s1).
5 - самая грубая ошибка: запрос в цикле по другому запросу, от такого про-граммирования не спасут ни множество процессоров, ни обилие памяти, ни быст-рая дисковая система. Почему бы не решить проблему в один запрос?
$s1=pg_exec("select a,c,x,y,z from b,d where e=a order by a");
В цикле можно запомнить предыдущее значение $a и прерывать цикл при смене этого значения. В любом случае, чем меньше запросов будет к базе, тем лучше - имейте это в виду.
7-10 - можно не вытаскивать поля по одному, а применить функцию pg_fetch_array() или pg_fetch_object(), которые возвращают хэш и объект соответ-ственно с именами полей, соответствующими именам полей результата запроса.
PHP позволяет поддерживать постоянные соединения с СУБД. То есть при завершении скрипта соединение с сервером базы данных разорвано не будет, а будет возобновлено при повторном запросе. Такой метод работы очень экономит время соединения, но съедает системные ресурсы (память, дескрипторы и т. д.). Если у вас один пользователь базы, одна база и один сайт, который непрерывно обращается к базе, то вам стоит попробовать поэкспериментировать. В конфигу-рации PHP можно глобально отменить постоянные соединения, чем и пользуются провайдеры, чтобы защитить свои хосты от жадных пользователей.
Раз уж мы начали говорить об электронной торговле, то можно развеять еще одно заблуждение, - что MySQL для нее годится. Это не совсем так. Он го-дится для макета, но не для серьезного сайта. В MySQL нет транзакций. Для сложной базы, для денежных расчетов, для оформления заказов и многих других важных операций транзакции необходимы. Так что используйте PostgreSQL, ко-торый все это умеет.
Допустим, магазин вы организовали, заработали кучу денег, давайте теперь продолжим ознакомление с программированием на PHP. Вкратце коснусь других возможностей.
Чего вожделеет каждый веб-мастер, создав на странице форму? Да, отпра-вить ее содержимое себе по почте. А сделать это на PHP очень просто - есть функция mail($to,$subj,$body, $header). Но есть и тонкость: почта будет уходить от имени www-сервера (как пользователя). Не забывайте, пожалуйста, про чет-вертый аргумент $header, в котором вы можете указывать любой параметр заго-ловка письма (см. RFC-822):
mail('user@isp.ru','test message','Выполучили письмо',
"From: bill@gates.ru\nContent-type: text/plain;
charset=windows-1251");
Указывайте хотя бы From: и Content-type: - это предохранит вас от раздра-женных получателей писем или, если получаете вы, от получения писем в непо-нятной кодировке неизвестно от кого.
Одно время у провайдеров были популярны системы чтения/отправки элек-тронной почты с www-сайта. На PHP вы можете сделать то же самое. Достаточно лишь почитать описание протоколов POP и IMAP и открыть сетевое соединение с почтовым сервером. Функция fsockopen(хост, порт) открывает сетевое соедине-ние, а пользоваться им можно при помощи обычных файловых функций. Только не открывайте соединение к своему www-серверу и не запрашивайте свой же скрипт - веб-мастеру это может сильно не понравиться. В целом работа с сетью в PHP оставляет желать лучшего - надеюсь, многие изъяны будут исправлены в четвертой версии. В первую очередь не хватает функции select() или аналога со-ответствующему вызову POSIX. Сетевое соединение - это не совсем файл, оно может прерваться, другая программа может не закрыть соединение и завершить-ся/зависнуть и т. п. Функция select() позволяет сделать работу с сетью более на-дежной. Подождем.
Не следует забывать еще про одно сетевое соединение - соединение клиен-та с веб-сервером, во время которого выполняется скрипт. Представьте себе си-туацию, когда ваш скрипт обрабатывает сложный запрос, что-то читает из базы, пишет в файл, изменяет данные в базе и т. д., а во время этого процесса клиент нажал кнопку "Стоп" и разорвал соединение. Процесс работы вашей программы будет прерван в самый неожиданный момент, и обработка не будет завершена. Но частично-то работа проделана. Необходимо как-то откатить назад внесенные из-менения. Для этого в PHP встроен механизм контроля за соединением. Вы можете подготовить функцию аварийной остановки с помощью register_shutdown_function(функция). Заданная функция вызывается интерпрета-тором PHP при завершении работы скрипта. Сетевое соединение в PHP находится в следующих состояниях:
0 - NORMAL;
1 - ABORTED;
2 - TIMEOUT.
Когда PHP работает нормально, статус соединения будет NORMAL. Когда клиент прерывает соединение, устанавливается флаг ABORT. Если для выполне-ния скрипта не хватило времени, то будет установлен флаг TIMEOUT.
Вы можете указать интерпретатору, будет или нет ваш скрипт прерван при разрыве соединения. Этот вариант можно выбрать функцией ignore_user_abort(). Другой вариант - это создание функции аварийного завершения, как было описа-но выше. При ее выполнении вы можете задать проверку причины завершения при помощи функций connection_aborted(), connection_timeout() и connection_status(). Если вы использовали ignore_user_abort(), то функция аварий-ного завершения может обнаружить два статуса, ABORT, если пользователь пре-рвал соединение, и TIMEOUT если при этом скрипт выполнялся слишком долго.