Статьи,обзоры,справочники по PHP

         

Недостаточно либо излишне комментированный текст


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

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

<?php // Начало кода

$age = 18; // Возраст равен 18

$age++; // Увеличим$age на один год

// Напечатаем приветствие

print "Вам сейчас 19 лет, и это значит, что Вам уже было:"; print "\n<br>\n<br>\n";

// Цикл ‘для’ чтобы вывести все // предыдущие значения возраста

for ($idx = 0; $idx < $age; $idx++) { // Напечатаем каждое значение возраста

print "$idx лет\n<br>\n"; } // Конец кода

?>



Неоправданное использование функции printf()


Функция printf() предназначена для вывода форматированных данных.

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

Ниже приведен пример обоснованного применения функции printf(). В данном случае она используется для форматированного вывода числа «пи»:

<?php

printf ("Число Пи: %2f\n<br>\n", M_PI); printf ("Это тоже число Пи: %3f\n<br>\n", M_PI; printf ("И это Пи: %4f\n<br>\n", M_PI);

?>

Примечание: Наблюдаются случаи патологической боязни функции printf(), когда люди пишут свои функции форматированного вывода, порой по 30-40 строк, хотя все проблемы мог бы решить один-единственный вызов функции printf().

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

когда следовало бы использовать функцию print(); при выводе результатов, возвращаемых функциями.





Неверное применение семантики языка


Многие программисты используют в своей работе PHP , фактически не понимая тонкостей этого языка. Одна из тонкостей – разница между синтаксисом и семантикой PHP.

Синтаксис PHP:Представляет собой набор правил для определения элементов языка. Например, как мы определяем переменную? Ставим знак $ перед ее именем. Как определяем функцию? В общем случае, используя скобки, аргументы и т.п. Семантика PHP: Представляет собой набор правил для применения синтаксиса. Например, возьмем функцию с двумя аргументами, что определяется ее синтаксисом. Причем в качестве аргументов ей следует передавать переменные строкового типа љ– это определяется семантикой.

Заметьте: «следует». В языках с четким разделением типов (таких как Java или C) нет понятия «следует» (в общем случае, хотя бывают и исключения). В таком случае компилятор вынудит использовать переменные строго определенного типа.

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

Возьмем кусок кода, который открывает файл и выводит его построчно:

<?php

$fp = @fopen( 'somefile.txt', 'r' ) or die ( 'Не могу открыть файл somefile.txt' );

while ($line = @fgets ( "$fp", 1024)) // Здесь ошибка!

{ print $line; }

@fclose ("$fp") // И здесь тоже color

or die( 'Не могу закрыть файл somefile.txt' );

?>

В данном случае появится сообщение об ошибке типа:
"Warning: Supplied argument is not a valid File-Handle resource in tst.php on line 4"
("Внимание: аргумент не может являться дескриптором файла")

Это вызвано тем, что переменная $fp заключена в двойные кавычки, что однозначно определяет ее как строку, тогда как функция fopen() ожидает в качестве первого аргумента дескриптор, но не строку. Соответственно, вам следует использовать переменную, которая может содержать дескриптор.

Примечание: В данном случае, строковый тип допустим синтаксически.

Для решения проблемы следует просто убрать двойные кавычки:

<?php

$fp = @fopen ( 'somefile.txt', 'r' ) or die ( 'Не могу открыть файл somefile.txt' );

while ( $line = @fgets ($fp, 1024) )
{ print $line; }

@fclose ($fp)   or die ( 'Не могу закрыть файл somefile.txt' ); ?>



== ==(О глюках)


Попробуйте аплодить таким способом на сервер бинарные файлы. Скорее всего файлы окажутся "битыми": фотки не будут показываться, программы не запустяться, архивы не распакуются. Текстовые файлы (почти точно) не повредяться. Дело в том, что Русский Апач (ваш веб-сервер) перекодирует все подряд. Например, символ с кодом 0х00

он заменяет на пробел (символ с кодом 0х20). Чтобы выключить эту ненужную перекодировку, допишите в файл httpd.conf из каталога Апача (/usr/local/apache) следующие строки. Если у вас нет доступа к этому файлу и админ сервера не может сделать это за вас, ткните его в эти строки.

CharsetRecodeMultipartForms Off

Строку CharsetRecodeMultipartForms Off

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

Можно почитать: на счет разных способов вставки данной команды (CharsetRecodeMultipartForms Off)



Можно прочитать данную статью, но написанную другими соловами, другим человеком и на другом сайте - http://www.leosha.f2s.com/php/upload.htm





Вопросы? Пишите: dima@php.spb.ru



u="u217.97.spylog.com";d=document;nv=navigator;na=nv.appName;t="";p=1; sz=" width=88 height=31 "; hl=history.length;d.cookie="b=b";c=0; bv=Math.round(parseFloat(nv.appVersion)*100); if (d.cookie) c=1;n=(na.substring(0,2)=="Mi")?0:1; if((n==0)||(bv >= 300)){rn=Math.random();t=(new Date()).getTimezoneOffset();} else {rn=0;} z="p="+p+"&rn="+rn+"&t="+t+"&c="+c+"&hl="+hl; if (self != top) { fr=1;} else { fr=0;} r=escape(d.referrer);r1=""; sl="1.0";h=0; pl="";sl="1.1"; if((n==1) && (bv >= 300)) { for(var i = 0; i < nv.plugins.length; i++) pl += nv.plugins[i].name+":"; } j = (navigator.javaEnabled() ? "Y" : "N"); sl="1.2";s=screen;wh=s.width+'x'+s.height; px=(n==0)?screen.colorDepth:screen.pixelDepth;z+="&wh="+wh+"&px="+px; sl="1.3" y=""; y+=""; y+="

"; y+=""; d.write(y);

hotlog_js=0; function HotLOG() {}

hotlog_js=1

hotlog_js=2

hotlog_js=3

HotLOG(4535,hotlog_js)



О переводчике


Дмитрий Короленко. Ну что о нем много говорить? ;)) Благодаря ему люди, не знающие английского, или знающие, но очень ;)), смогут прочесть весьма познавательную статью Стерлинга Хьюза. О замеченных недостатках перевода просьба сообщать на мыло: lkx2@mail.ru Сразу хочется пояснить, что дословный перевод не был самоцелью, но, тем не менее, стиль и смысл оригинальной статьи по возможности ;)) сохранялись. Все замечания и пожелания приветствуются и будут учтены, ибо готовится перевод второй части этой статьи. Только просьба ногами не пинать ;)) Все же я надеюсь,что если вы до этого места дочитали, то не все так плохо ;))



Об авторе


Стерлинг Хьюз (Sterling Hughes) – независимый разработчик веб-сайтов, занимается созданием динамических веб-приложений для некоторых крупнейших мировых компаний. Участвовал в создании cURL and SWF расширений PHP с открытым исходным кодом. Его книга, «Настольная книга программиста PHP» (The PHP Developer's Cookbook), была издана в октябре 2000 года издательством «Sams publishing».



ОБЛАСТЬ ВИДИМОСТИ ПЕРЕМЕННЫХ


Во-первых. Все переменные начинаются с символа $

Во-вторых существуют границы определения переменных. Например что-бы использовать глобальные переменные в функциях, необходимо их сначала декларировать как глобальные, иначе вы будете исопльзовать локальные переменные. Поясню на примере:

$a = 1; /* глобальное определение */

Function Test () {

$a=2;

echo $a; /* локальная переменная */

}

Test ();

echo $a;

Таким образом в функции используется локальная, собственная переменная и результатом прогарммы будет вывод чисел 2 и 1, а не 2 и 2, как некоторые могли подумать.

Ну а если вы хотите в функции использовать глобальные переменные, необходимо сделать так (декларировать с помощью оператора global):

$a = 1; /* глобальное определение */

Function Test () {

global $a;

$a=2;

echo $a; /* локальная переменная */

}

Test ();

echo $a;

Теперь в функции вы переопредилили глобальную переменную и вывод будет числа 2 и 2. Но есть и другой способ добраться до глобально-определенных данных - через ассоциативный массив $GLOBALS[]. Пример предыдущей программы, реализованный новым способом:

$a = 1; /* глобальное определение */

Function Test () {

$GLOBALS["a"]=2;

echo $a; /* локальная переменная */

}

Test ();

echo $a;

Обратите внимание переменная в массиве указывается без символа $

Кроме этог о PHP предоставляет возможность исопльзовать статические переменный. Все как в C/C++.

Function Test () {

static $a = 0;
echo $a;

$a++;

}

Test();

Test();

Test();

Результатом выполнения этого скрипта будет вывод чисел 0,1 и 2.



Обработчики сессии


PHP4 позволяет переопределить стандартные обработчики сессии, если они почему-то вас не устраивают.
В таблице 1 описаны все стандартные обработчики сессии PHP4.

Таблица 1.

Обработчик Назначение
session_handler_open(string $save_path, string $session_name) Данный обработчик вызывается при инициализации сессии, то есть, когда вызывается функция session_start(). Обычно этот обработчик открывает базу данных (или какой-нибудь файл) для группы сессий $session_name.
session_handler_close() Данный обработчик вызывается, когда нужно закрыть временное хранилище (вся информация уже записана)
session_handler_read(string $sid) Функция вызывается, когда нужно прочитать данные сессии. В качестве параметра передается идентификатор сессии – $sid.Функция возвращает данные сессии в формате: name1=value1;name2=value2;...;nameN=valueN; Под значением подразумевается сериализированные с помощью функции Serialize данные. Например, var1|i:10;var2|i:20, в сессии были сохранены две переменные – var1 и var2. Значение первой – 10, второй – 20.
session_handler_write(string $sid, string $data) Функция предназначена для записи данных сессии с указанным идентификатором. Параметр $data задается в вышеописанном формате.
session_handler_destroy(string $sid) Этот обработчик вызывается перед уничтожением сессии.
session_handler_gc(int $maxlifitime) Обработчик handler_gc вызывается после того, как сценарий завершил свою работу. Если пользователь окончательно «ушел» с вашего сервера, PHP должен удалить данные сессии. Вот именно для это и предназначена функция handler_gc. Параметр $maxlifetime – максимальное время существования сессии в секундах.

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

Для переопределения обработчиков используется функция session_set_save_handler($open,$close,$read,$write,$destroy,$gc).


В качестве параметром нужно передать имена функций, которые будут использоваться как обработчики. Данную функцию нужно вызывать ДО инициализации сессии (вызова функции session_start()), иначе она просто будет проигнорирована.

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

Листинг 3. handlers.php

<? function open ($save_path, $session_name) { echo "open ($save_path, $session_name)\n"; return true; }

function close() { echo "close\n"; return true; }

function read ($key) { echo "write ($key, $val)\n"; return "foo|i:1;"; }

function write ($key, $val) { echo "write ($key, $val)\n"; return true; }

// Ничего не делает function destroy ($key) { return true; }

// Ничего не делает function gc ($maxlifetime) { return true; }

session_set_save_handler ("open", "close", "read", "write", "destroy", "gc");

session_start(); $foo++; ?>

Теперь выполните команду php handlers.php
В результате вы должны увидеть примерно следующее:
X-Powered-By: PHP/4.0.0 Set-Cookie: PHPSESSID=7401e923e7aca6d8c66bbf9db9cf6b08 Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-cache, post-check=0, pre-check=0 Pragma: no-cache Content-type: text/html

open (/tmp, PHPSESSID) write (7401e923e7aca6d8c66bbf9db9cf6b08, ) write (7401e923e7aca6d8c66bbf9db9cf6b08, foo|i:2;) close


Эта статья предназначена для новичков,



Автор: Денис Колисниченко, dhsilabs@mail.ru
Опубликовано: 20.02.2002
Оригинал: http://www.softerra.ru/review/program/16152/

Эта статья предназначена для новичков, которые еще не знакомы с этим замечательным механизмом, существенно облегчающим жизнь Web-программистам. Интерпретатор PHP4 можно скачать на сайте http://www.php.net/. Я использую версию 4.1.1, но даже, если у вас версия 4.0.0 все примеры из этой статьи будут работать.

Одним из недостатков интерфейса CGI является то, что любая CGI-программа не может длительное время «общаться» с пользователем: она должна запуститься, обработать переданные ей параметры и выдать какой-нибудь результат. Представьте себе, что вам нужно написать некоторую анкету, но полей в ней так много, что они не умещаются в одном окне броузера (а из-за этого, как всегда, страдает дизайн) или нужно обработать некоторые данные перед вводом следующих. Эту проблему можно решить путем использования временного файла. Но, предположим, что в один момент с анкетой работают два или более пользователей, тогда вариант с файлом отпадает сам по себе. Тогда вам нужно будет использовать базу данных, но стоит ли использовать целую базу данных для хранения промежуточных данных? Более продвинутые станут использовать Cookies. Это отличное решение, но PHP4 предоставляет более гибкое решение этой проблемы – механизм сессий. К тому же, у пользователя, зашедшего на ваш сайт, Cookies могут быть отключены. Механизм сессий по умолчанию используется Cookies, но если они отключены, ваши сценарии, использующие сессии, все равно будут работать. О том, как это достигается, поговорим немного позже.

Для идентификации пользователя используется идентификатор сессии – SID. Именно с его помощью можно определить, какой пользователь запустил сценарий. Идентификатор сессии хранится в Cookies броузера – вот для чего нужны Cookies! Фактически, SID – это имя временного хранилища, то есть имя временного файла, в котором PHP4 хранит информацию о сессии. Обычно эти файлы размещаются в каталоге /tmp.

Рассмотрим самый простой пример использования сессий (см. листинг 1).

<? session_name("SessionOfIvan"); session_start(); session_register("a"); $a=@$a+1; echo "<html><body>Нажмите Reload, чтобы увеличить счетчик"; echo "<br>Счетчик: $a"; echo "</body></html>";



?>

Функция session_start() инициализирует сессию, а функция session_register("a") регистрирует в сессии переменную $a. Имена переменных задаются без знака доллара. Можно несколько раз регистрировать одну и ту же переменную в сессии (что я и сделал в листинге 1) – ее значение не обнулится при повторной регистрации. Если запустить наш сценарий и несколько раз нажать кнопку броузера Reload, счетчик будет увеличиваться, а если закрыть окно броузера, счетчик обнулится. Следует также отметить, что сценарии, которые одновременно выполняются, ничего не знают друг о друге. Другими словами, если вы запустите сценарий и пару раз нажмете на кнопку Reload для изменения счетчика, а потом, не закрывая окна броузера, запустите броузер снова и запустите еще раз этот же сценарий – значение счетчика будет нулевым (в данном случае – 1). Если же вы откроете еще одно окно броузера (например, в Навигаторе – это команда меню File, New Navigator Window), значение счетчика не обнулится.

Проверить зарегистрирована ли переменная в сессии позволяет функция session_is_register(string $name). Отменить регистрацию какой-нибудь переменной можно с помощью функции session_unregister(string $name). Отменить регистрацию ВСЕХ переменных сессии можно с помощью функции session_unset().


Обзор сетевых функций PHP



Автор: Денис Колисниченко, dhsilabs@mail.ru
Опубликовано: 21.03.2002
Оригинал:

В этой статье рассматривается использование сетевых функций популярного языка программирования PHP. При написании этой статьи я решил отойти от общепринятой схемы, которая употребляется в руководстве по PHP:
«тип название (параметры) – описание»
Наоборот, в статье собраны полезные практические примеры. Из-за большого объема информации (язык PHP предназначен для Web-программирования, поэтому достаточно большую часть функций можно назвать сетевыми), я ограничусь только теми, которые использую наиболее часто.

Переменные окружения интерфейса CGI
Получение документа по протоколу HTTP
Работа с сокетами
Функции для работы с DNS
Функции протоколирования
Отправка сообщения



ОПЕРАЦИИ СРАВНЕНИЯ


Здесь будет что-нибудь новое или нет? Даже комментировать эти операции не буду...

$a == $b $a != $b $a < $b $a > $b $a $a >= $b

В PHP существует также, как и в C++, тринарный оператор '?:'. Кто незнает - обьясню на примере.

$res= (expr1) ? (expr2) : (expr3);

Результатом этой операции будет значение (expr2), в том случае, если expr1==1 и значение expr3 в противном случае. Где все эти expr1, expr2, expr3 - являются переменными/константами или математиескими выражениями. Такая запись по сути своей аналогична следующей:

if (expr1) $res=(expr2); else $res=(expr3);

но естественно более лаконична.

А собственно об этом и все. Мы рассмотрели все операции, присутсвующие в PHP. Слудующим шагом рассмотрим управляющие структуры (или их еще можно назвать командами).

Дальше >



ОПЕРАЦИЯ ПРИСВАИВАНИЯ


Ну тут вообще ничего сложного, она всегда одна, это знак '=' и естественно этот знак означает, что переменной с лева от него будет присвоенное значение, полученное в результате выполнения каких либо операций или переменной/константы с правой стороны. Причем тут возомжно некоторый С++ -ные варианты, как-то:

$a = ($b = 4) + 5; // $a будет равна 9, а $b 4-м.

$a += 5; // аналогично $a = $a + 5;

$b = "Привет ";

$b .= "всем!"; // аналогично $b="Привет всем!"



Оптимизация программ на PHP


Выносите $переменные из "текстовых строк" - ускорение 25-40%

Короткие переменные не более 7 символов - ускорение 15%

Тормозят ли массивы в PHP? Вернее, как именно. Ускорение 40%

Выносите многомерные массивы из "текстовых строк" - ускорение 25-30%

Регулярные выражения: PHP(POSIX) vs Perl. Ускорение 60-200%

Циклы: for, foreach, while, count/sizeof() - ускорение 15%-30%

Для чтения файла file() быстрее, чем fopen+цикл - ускорение 40%

Загрузка всех тестов (php файлы)

Дмитрий Бородин

php.spb.ru

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



Ошибка программы простого текстового счетчика


Давайте сделаем такую программу. Итак, у нас есть какая-то страница, на которой хочется повесить счетчик. Обудим алгоритм:

считать число из файла записать увеличенное число обратно вывести его на экран

Согласитесь, программа простая, но может привести к ошибке, что и показано ниже.

Если вызывать данную программу очень часто, значение счетчика иногда будет обнуляться. Это произойдет из-за того, что в некоторый момент программа прочитает из файла пустое значение, к которому потом прибавляется единица ("пусто" + число 1 = число 1). Собственно, это и есть сброс счетчика.

Рассмотрим подробно, когда это произойдет. Представьте, что в один момент времени стартовали 2 копии данного скрипта. Одновременно ничего нигде не проиходит, в т.ч. и запуск скриптов, но время между запуском может быть очень маленькое. Процессор выполняет скрипты с разной скоростью, т.е. вы не должны удивляться тому, в каком порядке далее будут рассматриваться команды. Итак, ход программы (на примере "скрипта N1" и "скрипта N2"):

скрипткомандакомментарий (что сделает данная команда)
1 запуск первого скрипта--
1$counter=file("counter.txt");в переменной (массиве $counter) теперь храниться текущее число счетчика. Допустим, там было 1234, тогда это число будет в переменной $counter[0].
2запуск второго скрипта--
1$f=fopen("counter.txt","w+");открывает файл обнуляет его если файл не был создан, создает его (если позволят права). Но файл создан нами заранее, этот вариант исключен.
2$counter=file("counter.txt");читает содержимое пустого файла и записывает в массив $counter пустой массив. Переменная $counter[0] не существует.
1fputs($f,$counter[0]+1);пишет в файл число 1234 (т.к. в $counter[0] лежит число 1234)
2$f=fopen("counter.txt","w+");см. комментарий выше
1fclose($f); и конец работы--
2fputs($f,$counter[0]+1);записывает в файл число 1, т.к результат сложения несуществующей переменной и числа 1 равен числу 1
2fclose($f); и конец работы--
<

Основы языка


Синтаксис PHP прост. Программы на нем встраиваются в текст Web-страницы так же, как и сценарии на JavaScript, окаймляясь угловыми скобками с указанием языка: <?php … текст программы ..?>, а команды PHP обязательно разделяются символом точки с запятой — «;».

Как и во всех языках программирования, в PHP есть возможность работать с переменными — некими объектами, имеющими имя и способными принимать различные значения. Чтобы PHP мог отличить переменную от строк или команд, ее имя обязано начинаться со знака доллара — «$» — и не должно содержать пробелов, знаков апострофа и некоторых других.

Вот некоторые основные команды PHP, которых вполне хватит для реализации несложных проектов.

include «имя файла» — команда для включения содержимого одного файла в другой. Содержимое того файла, имя которого указывается в команде, целиком и полностью вставляется на то место, где располагается эта функция.

mail («Кому», «Тема», «Текст сообщения», «Дополнительные заголовки») — отправка почтового сообщения. При выполнении данной команды на сервере формируется электронное письмо в соответствии с указанными параметрами и отправляется с помощью серверной почтовой программы.

echo «текст» — вывод на страницу какого-либо текста. Чтобы отобразить значение какой-либо переменной, достаточно просто написать ее имя внутри выводимой строки.

if (условие) {…команды, которые должны выполняться, если условие верно…;} else {…команды, которые должны выполняться, если условие неверно…} — команда, позволяющая выполнить то или иное действие в зависимости от верности или неверности того или иного условия. В фигурных скобках может располагаться несколько команд, разделенных точкой с запятой.

Чтобы выполнять различные команды в зависимости от условия, которое может принимать три или больше значений, следует использовать оператор switch (описание смотрите в руководстве) — аналог оператора case в VBA и некоторых других языках.

for (начальное значение счетчика, условие продолжения цикла, изменение счетчика на каждом цикле) {…команды…;} — цикл, т. е. повторение указанных команд столько раз, сколько позволит условие изменения переменной, специально выделенной для подсчета числа выполнений. К примеру, цикл for ($i = 1; $i <= 10; $i++) {echo $i;} выводит в Web-страницу числа от 1 до 10, т. к. в нем изначально устанавливается значение счетчика в 1 — $i=1, каждый цикл его значение увеличивается на единицу — $i++, а продолжаться он будет до тех пор, пока значение счетчика не превысит 10 (т. е. пока $i<=10).


Можно использовать в РНР циклы и без открытого объявления числа повторений — while (условие) {…команды…;} и do {…команды…} while (условие).


Пример PHP-кода. Посмотрите внимательно на код и итог его отображения. Обратите внимание, что переменная a, которой присвоено значение еще в первом программном блоке левой страницы, сохранила его не только в других ее блоках, но и в программе, расположенной во включаемой с помощью команды include странице.

Программа на PHP может прерываться кодом Web-страницы, для этого достаточно всего лишь вставить закрывающий тег до этого кода и открывающий — после. Все, что находится между ними, будет выдаваться в браузер без какой-либо обработки, рассматриваясь как содержимое, выводимое с помощью команды echo.

Следует помнить и о том, что все элементы на PHP, расположенные на одной Web-странице, представляют собой одну большую программу, несмотря на то, что они разделяются блоками обычного текста страницы. Именно поэтому переменная, объявленная в расположенном в начале страницы коде, сохраняет свое значение не только до ее конца, но и во всех присоединяемых с помощью команды include файлах.

Обычно Web-сервер настраивается так, что на предмет наличия программ на PHP просматриваются файлы, имеющие расширение php, phtml, остальные же файлы передаются в браузер пользователя без поиска в них команд PHP. Делается так для более быстрой работы сервера, а также для обеспечения возможности установки на сервере разных интерпретаторов, т. к. тогда каждому из них назначаются свои расширения для обработки соответствующих файлов.

Поскольку PHP-код полностью исполняется на Web-сервере, то в страницах, выдаваемых браузеру, он будет отсутствовать, и если кто заинтересуется вашим опытом программирования, то вам придется отправлять ему этот код по почте, т. к. при просмотре сайта каким-нибудь образом узнать исходный PHP-код его страниц нельзя.

Немного истории
История PHP — прекрасный пример того, как изобретение, действительно нужное людям, способно завоевать весь мир. Начавшись с небольшого приложения, созданного энтузиастом-любителем, PHP превратился в самый массовый и самый многофунциональный язык Web-программирования. Простой синтаксис и логичная структура, отсутствие затрудняющих работу особенностей, модульность конструкции интерпретатора, легкость взаимодействия с базами данных — все это и сделало PHP таковым.

В отличие от многих других языков программирования, PHP был создан не какой-либо корпорацией или гением-программистом, а обычным пользователем Расмусом Лердорфом в далеком 1994 г. Его целью было всего лишь сделать домашнюю страничку интерактивнее, а значит, и привлекательнее для посетителей. Расмус разработал базовый синтаксис и написал первый интерпретатор своего языка, получившего название Personal Home Page Tools (PHP). Он умел обрабатывать лишь несколько основных команд, однако начало было положено.

В 1995 г. Расмус усовершенствовал его, соединив с другой своей программой, умевшей обрабатывать HTML-формы (Form Interpretator — FI), и добавил функцию интеграции с Web-сервером. Последнее значительно ускорило программу. Кроме того, в том же 1995 г. интерпретатор PHP был дополнен возможностями обработки новых команд, в частности функцией работы с сервером баз данных MySQL и автоматического создания gif-файлов (последнее, к примеру, может быть применено для генерации кнопок-счетчиков посещений). PHP/FI был размещен в Сети для всеобщего использования, и началось его повсеместное распространение.

Web-мастера быстро оценили достоинства нового языка Web-программирования — легкость освоения и богатство возможностей, и вскоре традиционные Perl и C++ стали сдавать свои позиции. А так как исходный код интерпретатора был открыт, то энтузиасты занялись его доработкой, и летом 1998 г. появился на свет PHP3 — детище Зива Сураски и Энди Гутманса (Zeev Suraski and Andi Gutmans). Они исправили баги предыдущей версии и добавили новые функции. И уже к концу 1999 г. число сайтов, построенных на основе PHP, перевалило за миллион. В немалой степени популярности РНР способствовала возможность его использования под различными операционными системами — от Windows до Unix и Linux.

В 2000 г. вышла четвертая версия интерпретатора PHP, разработанная компанией Zend Technologies и дополненная множеством новых функций. В настоящее время именно она является наиболее распространенной.

Отправка сообщения


Я не открою Америки, если заявлю, что для отправления почты в PHP используется функция mail. Здесь я только приведу несколько рекомендаций относительно использования этой функции.
Напомню формат вызова функции:
mail(string $to, string $subject, string $msg [, string $headers]);

Например,
mail("root@localhost", "Test", "Message\nLine2", "From: den@localhost\n", "Reply-To: den@localhost\n");

Все работает хорошо до тех пор, пока не начинаются проблемы с кодировками. Для указания кодировки нужно установить заголовок
Content-type: text/plain; charset=koi8-r

Для преобразования самих кодировок используется функция convert_cyr_string(). Использовать ее предельно просто, например,
convert_cyr_string($msg,"k","w");
Этим вызовом функции convert_cyr_string() мы преобразуем кодировку koi8-r в windows-1251. Разумеется, заголовок Content-type нужно изменить на
Content-type: text/plain; charset=win-1251

При использовании функции mail целесообразно хранить все заголовки в теле письма. Тогда один раз вызвав функции convert_cyr_string() мы конвертируем все письмо в нужныю нам кодировку. В этом случае вызов функции mail должен быть произведен так:
mail("root@localhost","",$msg);
Значение переменной $msg будет таким: $msg="From: Денис <den@localhost>\n To: Администратор <root@localhost>\n Content-type: text/plain; charset=win-1251\n \n Текст сообщения ...

Обратите внимание, что после всех заголовков должно следовать два символа новой строки \n: один после последнего заголовка, а другой перед текстом сообщения.
На этом я и заканчиваю этот небольшой обзор, любые ваши комментарии, вопросы прошу присылать mailto:dhsilabs@mail.ru



Ответ:


Нет, админ никому никогда ничего не должен :-)

Шаг 1.

Запускаем FAR и заходим по FTP в то место, где расположен каталог (php-programs - правая панель) с той самой несчастной программой (white.php - левая панель). Наводим курсор (сине-зеленая полоска) на этот самый каталог (т.е. не надо входить в каталог) -- это все в правой панели, см. рисунок.



Шаг 2.

Нажимаем Ctrl+A, выскочит окошко :-)



Шаг 3.

Ставим все галочки (в виде букв x) и жмем Ентер.



Шаг 4.

Запускаем программу из каталога php-programs. Текст файла write.php:

....

На счет security....

Установки флагов "доступ на запись ВСЕМ юзерам компа" - к нижкам по Униху, что в большом кол-ве хранятся на citforum.org. Разумеется, есть защита, и она наипростейшая (ограничиваем доступ к вышележащему каталогу), но это по другой теме. Последнее, скорее всего, без админа не выйдет. Просто так надо 1 раз сделать, а потом спокойно работать.



Ссылки по теме

http://userguide.webservis.ru/creating-cgi-howuse-chmod.shtml

http://www.citforum.ru/operating_systems/unixuser/gl3_10_6.shtml

http://www.citforum.ru/operating_systems/manpages/CHMOD.1.shtml

http://www.citforum.ru/operating_systems/linuxway/gl7.shtml



u="u217.97.spylog.com";d=document;nv=navigator;na=nv.appName;t="";p=1; sz=" width=88 height=31 "; hl=history.length;d.cookie="b=b";c=0; bv=Math.round(parseFloat(nv.appVersion)*100); if (d.cookie) c=1;n=(na.substring(0,2)=="Mi")?0:1; if((n==0)||(bv >= 300)){rn=Math.random();t=(new Date()).getTimezoneOffset();} else {rn=0;} z="p="+p+"&rn="+rn+"&t="+t+"&c="+c+"&hl="+hl; if (self != top) { fr=1;} else { fr=0;} r=escape(d.referrer);r1=""; sl="1.0";h=0; pl="";sl="1.1"; if((n==1) && (bv >= 300)) { for(var i = 0; i < nv.plugins.length; i++) pl += nv.plugins[i].name+":"; } j = (navigator.javaEnabled() ? "Y" : "N"); sl="1.2";s=screen;wh=s.width+'x'+s.height; px=(n==0)?screen.colorDepth:screen.pixelDepth;z+="&wh="+wh+"&px="+px; sl="1.3" y=""; y+=""; y+="

"; y+=""; d.write(y);

hotlog_js=0; function HotLOG() {}

hotlog_js=1

hotlog_js=2

hotlog_js=3

HotLOG(4535,hotlog_js)



Параллельное выполнение скриптов может нарушить целостность информации в файлах


Здесь рассматривается вопрос, что бывает, если запустить некий скрипт почти одновременно (что происходит, например, при большой нагруженности сервера) несколько раз, т.е. запустить несколько копий одного и того же скрипта. И к чему это может привести.

См. также:

Параллельное выполнение скриптов может привести к искажению информации в БАЗАХ ДАННЫХ



Параметры и функции для сессий


В данной главе приведено описаний сессий - это ФУНКЦИИ и одноименные НАСТРОЙКИ в php.ini или .htaccess. Функции от настроек отличаются тем, что у первых есть скобочки - функция(). Для тех, кто не в курсе. Вы можете настраивать сессии, задавая разные параметры в php.ini, httpd.conf или .htaccess файлах. В php.ini все переменные уже написаны и содержат какие-либо значения (их называют глобальными настройками), с помощью httpd.conf или .htaccess можно указать для какого-либо виртуального сервера или отдельного каталога локальные настройки ПХП. Для этого используют строку php_value Имя Значение. Обратите внимание, что использовать настройки можно только если ваш ПХП является модулем Апача. В противном случае (ПХП - не модуль, а отдельная CGI-программа) такая строка в .htaccess вызовет ошибку, как и любая неправильная строка.



Переменные окружения


И тут все так-же просто. Хотите узнать домашний каталог? В юникс-системах этообычно переменная окружения с именем HOME. Так узнавайте:

echo $HOME;

Вы также можете работать с переменными окружения через функции getenv() и putenv()



Переменные окружения интерфейса CGI


При использовании интерфейса CGI (Common Gateway Interface) программисту доступно множество переменных окружения. Сейчас мы рассмотрим наиболее полезные в нашем случае переменные (см. таблицу 1).
Переменные окружения можно использовать в программе также как обыкновенные переменные. Например, для вывода IP-адреса клиента достаточно одного оператора:
echo $REMOTE_ADDR

Таблица 1.

Переменная Описание
HTTP_USER_AGENT С помощью этой переменой можно определить броузер пользователя, а также его операционную систему. Например, для Netscape, запущенным под Linux, эта переменная будет содердать значение:
Mozilla/4.7 [en] (Linux; I)
Для Internet Explorer 5.0 и Win98:
Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt)
HTTP_HOST Содержит доменное имя сервера, на котором запущен сценарий.
SERVER_PORT Порт сервера, к которому обратился броузер. Обычно используется порт 80.
REMOTE_ADDR Содержит IP-адрес клиента, то есть IP-адрес пользователя, который запустил броузер
REMOTE_PORT Порт для получения ответа сервера. Этот порт закрепляется за каждой запущенной копией броузера



ПЕРЕМЕННЫЕ ПЕРЕМЕННЫЕ


Скорее всего скоро вам понадобятся переменныес динамически (в ходе работы скрипты) изменяемым наименованием. Поясню на пример, что я имею ввиду:

$a = "hello"; $$a = "world";

Данная запись означает, что переменной с именем a мы присваиваем значение "hello". Следующей операцией переменной с именем, хранящимся в переменной с именем a, то есть - переменной hello мы присваиваем занчение "world"

echo "$a ${$a}";

тоже самое, что и

echo "$a $hello";

В результаты мы получим на экране hello world

Дело ненмого усложняется, если вы хотите использовать подобные массивы. Ведь если вы запишете $$a[1] - интерпретатору надо будет знать, что использовать в качестве переменной - $a или $$a (имя, зранящееся в $a). В таком случаем вам прийдется исопльзовать следующий синтаксис - ${$a[1]} в случае, если вы хотите использовать переменную с именем, зранящимся в массиве $a с индексмо 1 и ${$a}[1] в другом случае (если вы хотите использовать элемент 1 массива с именем, зранящимся в переменной $a.

Дальше >



Переписываем стандартные функции


Кое-кто рекомендует переименовывать стандартные функции для того, чтобы программистам на Visual Basic’е проще было перейти к использованию языка PHP:

<?php

functionlen ($str) { return strlen ($str); } ?>

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

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

Ну и, наконец, это замедляет программу. Дело не только в необходимости обработки большего объема кода, но и в том, что для вызова такой пользовательской функции, требуется больше времени, чем для прямого вызова стандартной функции.



PHP: секреты интерактивности


PHP: секреты интерактивности
Антон Орлов
Когда-то давно, еще в прошлом веке, чтобы создать сайт «на мировом уровне», достаточно было просто уметь работать с HTML и обладать художественным вкусом. Спустя некоторое время требования усложнились: использование JavaScript и Dynamic HTML стало рутинным, а дизайн страниц, не имеющих подобных «украшений», считался устаревшим. Вскоре правилом «хорошего тона» для корпоративного сайта стало применение сложных программ на Perl или C++. Однако Web-дизайнеры не желали мириться с такой ситуацией. И на свет появился PHP — язык программирования, обладающий возможностями сложных скриптовых языков, но в то же время удивительно простой и легкий в изучении и применении.

Все языки программирования, используемые при разработке Web-сайтов, можно разделить на две большие группы. К первой относятся те из них, код которых выполняется на компьютере посетителя сайта — в его браузере. Это всем известные JavaScript, VBScript, Java-апплеты. Программы, написанные на этих языках, встраиваются в код Web-страниц (или выносятся в отдельный файл с вызовом из Web-страницы).

Во вторую группу попадают те языки, программы на которых выполняются на том компьютере, где расположен Web-сервер. Эта группа гораздо обширнее, именно к ней и относится PHP. Однако от своих собратьев он выгодно отличается своей простотой. Создавая программы на этом языке, нет необходимости учитывать все те многочисленные мелочи, которые отравляют жизнь программистам на C++ или Perl: не надо заботиться о правах доступа к файлам сценария или прописывать точные пути к различным модулям и т. д. Для тестирования PHP-программ на локальном компьютере необязательно устанавливать на нем ту же операционную систему, что и у провайдера хостинга сайта, где они будут применяться,— достаточно лишь загрузить соответствующий Web-сервер и подключить к нему модуль PHP и целиком сосредоточиться на решаемой задаче.

А зачем же вообще может потребоваться PHP? Разве обычных HTML и пары JavaScript недостаточно для создания красивой Web-страницы?

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

С помощью PHP можно упростить частое обновление страницы. Например, если страница содержит регулярно меняющуюся вставку (например, новости), то будет неплохо поместить на ее место инструкцию include («file») и в этом файле разместить текст новостей. Таким образом, при обновлении новостей редактированию придется подвергать лишь сам их текст, а не HTML-код заглавной страницы, что и самому делать легче, и неопытному помощнику доверить можно.

Помощь Web-мастеру и службе поддержки Web-ресурса — это лишь весьма малая часть функций PHP. Этот язык позволяет значительно обогатить сайт огромным количеством новых функций. Так, с помощью функции mail() легко обеспечить отправку почтового сообщения по какому-либо адресу со страниц сайта и т. д.

<

Вся информация о сервере и интерпретаторе — одной командой phpinfo().
Одним из наиболее заметных достоинств PHP является возможность легкой работы с серверами баз данных. Для этого достаточно установить на Web-сервере программу работы с базой данных (наиболее часто используется бесплатная MySQL) и включить в текст PHP-сценария команды работы с нею.

Возможности языка весьма серьезно расширяются с помощью дополнительных модулей, содержащих различные функции. Они при необходимости размещаются там же, где установлен PHP-интерпретатор, а загрузить их можно с адреса http://www.php.net/, там же, в разделе документации, приведено и полное описание работы с ними. Например, модуль Zlib позволяет работать из программы на PHP с архивами в формате Gzip, а Libswf — с Flash-презентациями, создавая их и редактируя прямо на сервере. Так как PHP — развивающийся язык, то новые модули появляются довольно часто. Однако применять их получится только после установки на Web-сервер, чему провайдеры хостинговых услуг могут и воспротивиться. Поэтому при желании использовать функции из какого-либо модуля (да и самого языка PHP) сначала необходимо проверить, поддерживает ли их Web-сервер, на котором вы собираетесь хостить сайт. Сделать это довольно просто, разместив на сервере страницу со строчкой <?php phpinfo() ?> и загрузив ее с сервера в браузер (на ней будет отображена информация о версии PHP, параметрах Web-сервера и многом другом, в т. ч. дополнительных модулях).


PHP - система разработки скриптов


или как написать скрипт с использованием базы данных за 20 мин.

Содержание

1. Введение
    1.1. Создание скриптов на PHP.
    1.2. Синтаксис PHP.
    1.3. Переменные в PHP.
2. Возможности языка.
    2.1. Обработка строк.
    2.2. Работа с файлами и процессами.
    2.3. Работа с базами данных.
3. Использование PHP.

1. Введение

    Прежде всего, ответим на вопрос: что же такое PHP? PHP - это система разработки скриптов, включающая в себя CGI - интерфейс, интерпретатор языка и набор функций для доступа к базам данных и различным объектам WWW. По личному мнению автора этой статьи, на данный момент PHP является наиболее удобным и мощным средством разработки приложений WWW и интерфесов к БД в Интернет.

1.1. Создание скриптов на PHP

    Система PHP устанавливается на Web-сервер в качестве обработчика определенного mime - типа, аналогично системе SSI (Server Side Include), то есть PHP-скрипт представляет собой обычный html-документ с редкими (или не очень :) вставками тэгов PHP - комманд. Благодаря этому, создание и отладка скриптов PHP значительно проще, чем отладка и создание скриптов на других языках (например C или Perl).
    Вместе с тем, PHP обеспечивает разработчику очень большие возможности при разработке приложений web или активных страниц, так как облдает значительным набором функций и относительно большой гибкостью.

1.2. Синтаксис PHP

    По своему синтаксису язык PHP наиболее походит на классический С, хотя видны и некоторые заимствования из Java и Perl. По крайней мере, программист на С очень быстро освоит данный язык и сможет использовать его с максимальной эффективностью.
    В принципе, в PHP есть практически все операторы и функции, имеющиеся в стандартном GNU С (или их аналоги), например есть циклы (while, for), операторы выбора (if, switch), функции работы с файловой системой и процессами (fopen, *dir, stat, unlink, popen, exec), функции ввода-вывода (fgets,fputs,printf) и множество других...
    Одним из самых больших отличий PHP от C - является использование переменных.


1.3. Переменные в PHP

   Первое, что бросается в глаза при использовании PHP - это отсутствие типизированных переменных, хотя некая типизация и присутствует, но тип переменной в каждом конкретном операторе зависит от контекста, например переменная $str="10" при использовании ее в операторе echo($str) будет иметь строковый тип (да, да, про char * можно забыть), а в выражениии типа $str=$str+1 будет обрабатываться как число.
    Хотя это может показаться недостатком, данная особенность PHP имеет свой смысл, так как при обработке результатов форм ввода html очень трудно определить первоначальный тип переменной, и кроме того, все перобразования типов можно свалить на php (и забыть про itoa и atoi).
    Также одной из интересных возможностей PHP является автоматический перенос переменных окружения и параметров скрипта в переменные PHP, причем отпадает необходимость перевода URL-кодированных значений переменных в нормальные, например при передаче скрипту параметра str=text%20with%20spaces ( запрос типа GET /some_script.php?str=text%20with%20spaces HTTP/1.0 ) будет образована переменная $str="text with spaces".

2. Возможности языка

   PHP имеет целый ряд встроенных функций для обработки объектов самого различного рода. ( PHP 3.0 Functions reference )
Для примера мы вкратце рассмотрим следующие разделы, наиболее важные с моей точки зрения :
    2.1. Обработка строк;
    2.2. Работа с файлами и процессами;
    2.3. Работа с базами данных;

2.1. Обработка строк

    Работа со строками в php гораздо богаче, чем в С. Кроме того, что существуют практически все стандартные функции языка С, наличиствует  множество дополнительных функций и возможностей, которые как ориентированы на web, так и просто облегчают работу. В частности конкатенация строк осуществляется следующим оператором: $result_str=$first_str . $second_str;
   В качестве примеров полезных для работы в web функций могут служить функции htmlspecialchars() , преобразующая в строке символы типа & в последовательность &amp; или функция urlencode(string str), преобразующую символы русского алфавита в последовательность %XX, где ХХ - шестнадцатеричный код символа. Также весьма интересны функции работы с регулярными выражениями, например $str=ereg_replace("/usr/local/([^/]*)/filename", "\\1","/usr/local/dirname/filename"); даст нам строку $str="dirname". Или например функция explode, лично меня очень порадовшая: данная функция позволяет преобразовать строку в массив значений, например для формирования следующего элемента выбора



Понедельник Вторник Среда Четверг Пятница Суббота Воскресенье

был использован следующий код:

<?php $strarray=explode(":","Понедельник:Вторник:Среда:Четверг:Пятница:Суббота:Воскресенье"); ?>
<select name="dayofweek" size="1">
<?php for($i=0;$i<7;$i++) { ?>
<option> <?php echo($strarray[$i]); ?> </option>

<?php } ?>
</select>

2.2. Работа с файлами и процессами

   Работа с файлами в PHP практически ничем не отличается от работы с файлами в С,  те-же самые функции работы с потоками или с блоковыми файлами, fopen, fclose, fread, fgets, fputs, fwrite, но есть одна маленькая, но очень приятная возможность работать с файлами по их URL, например возможны следующие конструкты :

$fp = fopen( "http://www.soft.ru/", "r" );
$fp = fopen( "ftp://www.soft.ru/", "r" );
   И, одной из самых больших прелестей PHP, по моему мнению является возможность использовать другие программы, например для получения списка текущей директории использовать стандартную команду ls, или отправлять почту с помощью sendmail. Это достигается с помощью того, что php позволяет создать процесс, и работать с его стандартным вводом или стандартным выводом как с обычным потоком. (команда popen, например $fp=popen("/bin/ls -l","r"); ).

2.3. Работа с базами данных

    В системе PHP работа с БД осуществляется в основном путем работы с различными SQL-серверами, причем SQL-сервер в любом случае рассматривается как удаленный, то есть создается сетевое соединение. Благодаря этому возможно открывать из одного скрипта либо несколько пользовательских сессий, либо работать с различными SQL-серверами. После установки соединения с сервером, выбирается рабочая база данных, после чего можно отправлять и обратывать запросы (так как SQL является клиент-серверной архитектурой, любая работа с данными осуществляется с помощью запросов к SQL-серверу на получение или изменение данных). При выполнении запроса создается некий объект, в котором хранится результат выполнения запроса, после чего можно получать отдельные ряды, путем выполнения специальных функций. Если вы когда-нибудь работали с SQL - вы очень быстро разберетесь с использованием функций работы БД в PHP.



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

Название фирмы

Телефон
контора Купи-продай 222-33-44
ГлавСовСнаб 333-44-55
MuSt DiE 444-55-66
А сформирована дання таблица была следующим php -  кодом:

<!--  Начало  таблицы  -->
<table  width="50%"  border="1"  cellspacing="0"  cellpadding="0"  align="CENTER">
  <tr>
    <th  width="75%">Название  фирмы</th>
    <th  width="25%">Телефон</th>
  </tr>
<script  language="php">
$sock=msql_connect ("localhost");  //Соединяемся  с  SQL  -  сервером
msql_select_db( "test",$sock);  //Выбираем  БД
$R=msql_query( "select  *  from  db",$sock);  //Делаем  запрос

$T=msql_fetch_array($R);  //Получаем  первый  ряд  из  результата  выполнения  запроса
while  (is_array($T))  {  //Пока  есть  ряды  в  запросе  (т.е.  $T  -    массив)
</script>
  <tr>
    <td> <?php  echo  $T[name];  //Распечатываем  поле  name  из  текущего  ряда ?></td>
    <td  align="center"> <?php  echo  $T[phone];  //Распечатываем  поле  phone  из  текущего  ряда  ?></td>
  </tr>
<?php  $T=msql_fetch_array($R);  //  Считываем  следующий  ряд  ?> 
<?php  }  //  Конец  цикла  while  ?>
</table>
<!--  Конец  таблицы  -->

3. Использование PHP

    Итак, постепенно мы приходим к следующему выводу: использование PHP целесообразно при создании часто обновляемых либо громоздких в написании программ, скорость выполнения для которых не является критическим параметром (имеется в виду, что если разница между временем выполнения скрипта на С и скрипта на PHP составляет 10-20%, то вполне можно предпочесть скорость разработки скорости выполнения) и необходимо быстрое создание полнофункционального приложения. (если интересно мое личное мнение то кроме PHP я использую только C, и то, очень редко.)


Плюсы использования шаблонов:


Предельно просто и ясно Для изменения шаблонов не требуется знание PHP



Плюсы использования временных переменных


Введение временных переменных позволяет упростить некоторые сложные выражения или вызовы функций. Еще они приносят пользу, когда позволяют избежать многократного вызова функции с одними и теми же аргументами.

Вот пример, в котором не используется лишних переменных:

<?php

// string reverse_characters (string str) // Переворачивает строку символов

function  reverse_characters ($str) { return implode ("", array_reverse (preg_split ("//", $str))); }

?>

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

<?php

// string reverse_characters (string str) // Переворачивает строку символов

function reverse_characters ($str) { $characters = preg_split ("//", $str);
    $characters = array_reverse ($characters);
    return implode ("",  $characters);
}

?>



Почему с'апложенные jpeg-файлы не отобpажаются? (бьются?) Веб-сервер - русский Апач


Все дело в том, что русский Апач по умолчанию производит перекодировку файлов.
Так, символ с кодом 0х00 он заменяет на пробел (символ с кодом 0х20).
Для борьбы с этим эффектом нужно добавить в конфигурационный файл Апача httpd.conf следующее:
<Location> CharsetRecodeMultipartForms Off </Location>

(ответ Дмиртия Селезнева, 2:5095/6)



Почтовый робот и CRON


Дмитрий Бородин

Почтовый робот - это программа, которая анализирует почту, пришедшую на определнный почтовый ящик, и производит разные действия. Основная цель этой статьи о почтовых роботах. Но раз уж тут будет упомянут крон, то и о нем.

Сразу хочется предупредить, что здесь будет рассказано о множестве способов сделать одну вещь разными способами, поэтому вам придется немного думать... Это к тому, что к статьтье по отправке писем с аттачем постоянно имеют притензии разные люди, которые не умееют заполнить ни "почтовый хост провайдера", ни даже "обратный адрес". Пока вы будете читать эту статью, вы узнаете о большом количестве ньюансов и поймете, что спрашивать или объяснять в 2х словах "как сделать почтового робота?" невозможно.

CRON - средство выполнять регулярные действия на серверах типа Unix. В Windows крон называют шедулером. Суть одна: делаем правила срабатывания крона, например раз в 2 минуты или в 23:59 по четвергам, и что делать, например запустить php-программу (чтобы та делала нужную работу). В форуме часто возникает вопрос "как делать что либо регулярно?". Именно крон решает эту проблему.



Подготовим ПХП для запуска робота


Как вы понимаете, мы пишем не веб-скрипт, который будет активироваться по желанию посетителя, который мышкой кликает по ссылкам, а по какому событию. В соответствии с этим, к примеру, не может идти речи о получении ИП-адреса посетителя или куках. Почтовый робот - это совершенно другая история. В его задачу входит найти файл с письмом(писами) и обработать.

Если вы ниже выберите вариант 1 или 2, вам Апач как CGI не нужен. И наоборот - если у вас нет Апача как CGI, то вы можете использовать только способы 1 или 2, чтобы организовать почтового робота или просто крон. В остальных случаях - Апач как CGI вам нужен. Если вы самостоятельно этого проверить не можете, обратитесь к администратору сервера с вопросом "Как запускать PHP в CGI-режиме?". Если скажет - нет такого, требуйте, чтобы появился :-) В конце концов вам от него нужно только адрес вида /usr/bin/php

получить. Т.е. php - это название программы, а /usr/bin - каталог.



Вариант 1: без CRON, без Command, метод POP3 почты.

Это значит, что вы не имете доступа ни к крону, ни к описанному способу 'command'. Не расстраивайтесь :-) Наша почта находится либо на том же сервере, где и робот, либо на другом. Наша задача научиться забирать почту с POP3 ящика и выполнять данную функцию регулярно.

Как забрать почту с POP3 ящика. Надо изучить сокеты и POP3. Поверьте, это просто. Чтобы понять сокеты, предствьте, что это простые файлы, в которые можно писать и читать. Для забора почты нужно открыть сокет с сервером почты на 110 порту (порт POP3 сервера). Далее, как в файл, надо написать USER ваш_логин

(пример: fputs($sock,"USER dima");), затем PASS ваш_пароль. После этого командой LIST получить список писем, еще командой RETR номер

взять текст письма и стереть его с сервера. Всего надо изучить 6-7 команд протокала POP3. Это выходит за рамки данный статьи.

Теперь попробуем запускать нашу программу каждые 5 минут. К сожалению, методами ПХП напрямую это не возможно. Но мы попробуем. Допустим, на ваш сайт ходят люди :-) Если на ваш сайт никто не ходит, данный способ не заработает. Нужно сделать функцию (в каком-то общем файле), которую будут запускать из всех ваших скриптов. Функция должно проверять время модификации файла-флага, например, flag.txt. Если время модикации больше, чем 5 минут назад, то пора выполнять функицию проверки почты. После проверки почты, надо файл-флаг открыть на запись и закрыть, чтобы время модификации было изменено. Если же время модификации не превысело 5 минут, то функция ничего не делает. Как видите, ничего хитрого.

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



Подготовка сервера


1. Возможный глюк: у вас не настроен временный каталог на сервере для размещения временных файлов.

2. Программа подразумевает, что PHP поместит в переменную $SID номер сесии. По умолчанию, возможно, этого не произойдет.

Для решения проблемы 1) и 2) пунктов надо изменить опции PHP. Это можно сделать в php.ini или файлах httpd.conf/.htaccess.

Вариант 1 - php.ini

Если править php.ini, то в нем уже есть те переменные, что надо изменить

ищем строку session.save_path

и пишем путь к своему временному каталогу. В этот каталог Apache/PHP будут писать свои файлы, след. для них там должен быть доступ. Если у вас Unix, то пишем /tmp, если Windows, то \temp (не забудьте создать C:\TEMP или X:\TEMP, смотря где находится Апач)

ищем строку session.name

и заменяем на SID (большими буквами)

Вариант 2 - .htaccess или httpd.conf

Если вносить те же измения в указанные файлы, то надо написать так:

вариант для unix: php_value session.save_path /tmp

и для windows: php_value session.save_path \temp

и имя сессии: php_value session.name SID

Итак, нам надо для 1) и 2) пунктов подправить переменные PHP-процессора: session.save_path (временный каталог) и session.name (присвоить знаначение "SID").



Полезные ссылки


Тест производительности XSLT процессоров для PHP/Perl

P.S. PHP рулит! ;)



u="u217.97.spylog.com";d=document;nv=navigator;na=nv.appName;t="";p=1; sz=" width=88 height=31 "; hl=history.length;d.cookie="b=b";c=0; bv=Math.round(parseFloat(nv.appVersion)*100); if (d.cookie) c=1;n=(na.substring(0,2)=="Mi")?0:1; if((n==0)||(bv >= 300)){rn=Math.random();t=(new Date()).getTimezoneOffset();} else {rn=0;} z="p="+p+"&rn="+rn+"&t="+t+"&c="+c+"&hl="+hl; if (self != top) { fr=1;} else { fr=0;} r=escape(d.referrer);r1=""; sl="1.0";h=0; pl="";sl="1.1"; if((n==1) && (bv >= 300)) { for(var i = 0; i < nv.plugins.length; i++) pl += nv.plugins[i].name+":"; } j = (navigator.javaEnabled() ? "Y" : "N"); sl="1.2";s=screen;wh=s.width+'x'+s.height; px=(n==0)?screen.colorDepth:screen.pixelDepth;z+="&wh="+wh+"&px="+px; sl="1.3" y=""; y+=""; y+="

"; y+=""; d.write(y);

hotlog_js=0; function HotLOG() {}

hotlog_js=1

hotlog_js=2

hotlog_js=3

HotLOG(4535,hotlog_js)



Получение документа по протоколу HTTP


Получить документ по протоколу HTTP довольно просто:

Листинг 1. Получение документа по HTTP <? 1. $file = join( '', file( 'http://localhost/index.html' ) ); 2. echo $file; ?>

В первой строке листинга 1 мы получаем весь документ в строку $file, а второй – отправляем документ в броузер. Функция file() возвращает массив строк. N-ый элемент этого массива соответствует N-ой строке файла.
Если нас интересует HTML-код получаемого документа, вывести код в броузер поможет листинг 2, который я позаимствовал из руководства по PHP.

Листинг 2. Вывод HTML-кода документа <? 1. $fcontents = file( 'http://localhost' ); 2. while ( list( $line_num, $line ) = each( $fcontents ) ) { 3. echo "<b>Line $line_num:</b> " . htmlspecialchars( $line) . "<br>\n"; 4. } ?>



POPАутентификация.


Простой и безопасный метод проверки подлинности пользователя.

Берется библиотека Net::POP3 и стандартными методами пытаемся влогиниться в почтовый ящик. Если нам это удалось, то логин/пароль верны, и обратный результат в ином случае.

Модуль Net::POP3 дает пользователю создать объект и 14 методов к нему.

Все методы изучать нет смысла - они довольно-таки неподробно описаны в документации к модулю, нас более интересует метод login($user,$passwd).

Он возвращает значение undef в случае неудачной аутентификации, или, в случае удачного входа в почтовый ящик, количество писем в оном, или строку "0E0", если писем нет , т.е. "пишут".

Порядок работы с ним следующий:

use Net::POP3; &parse_form # Читаем из формы переданные пароль/логин

# Создаем объект

$pop = Net::POP3->new('popserver') || print "Cannot create connection\n"; # пробуем влогиниться # в $res будет возвращен результат логина

$res = $pop->login($form{'login'},$form{'password'}); if ($res == undef) { # неудача

print "Incorrect username or password!\n"; } else { # влогинились # делаем, что надо # # следующий код нарисован для того, чтобы хоть что-то # делалось.

if ($res eq "0E0") { # писем нет

print "You have $res messages in mailbox.\n"; } else { # письма есть

print "You have $res messages in mailbox.\n"; } } #закрываем соединение.

$pop->quit();

Намного проще и безопаснее, чем лезть в святая святых безопасности Unix систем- файл shadow.

Да и не нужно просить сисадмина сервера установить на ваш скрипт setuid bit, хотя заранее можно сказать, что любой нормальный сисадмин вам в этом откажет, и будет на все сто прав.
А библиотека Net есть практически на любом Web-сервере, где есть доступ к perl интерпретатору.

А.Сухинин. (shurick31@yahoo.com)



[ Распечатать ]::[ Переслать ]::[ Обсудить ]




== ==(Прием и использование)


Ваша программа на php (в файле upload2.phtml), чтобы получить отправленный файл НЕ ДОЛЖНА НИЧЕГО ДЕЛАТЬ! Все само! Радуйтесь, товарищи :-)

Перед началом выполнений вашей программы сервер принимает файл, а ПХП-процессор сообщает имя временно файла (переменная $userfile), в котором храниться только что полученный файл. Поэтому вам нужно лишь открыть файл на чтение и считать содержимое. Даже стирать этот временный файл не надо.

Как вывести upload'еный файл на экран? Вот программа (ее надо записать в файл upload2.phtml

)

$userfile_size байт

На вашем компьютере файл назывался: $userfile_name

На нашем сервере ваш файл был записан для временного храниения по адресу и под именем $userfile

Ниже его содержимое:
";

// для тех, кто не знает, команда echo implode("",file("имя_файла")); // выводит содержимое "имя_файла" на экран

echo implode("",file($userfile));

?>



Пример работы с сессиями.


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

обновить страницу

"; echo "обнулить идентификацию

";

if (!isset($s['count'])) { // Посетитель пришел впервые. Объявляем переменную, которая // должны быть всегда. Это счетчик загрузок страницы. $s['count']=1; } else $s['count']++; echo "Вы загружили эту страницу раз: $s[count]

";

// обработка формы, заполняемой посетителем // если введено имя, заносим в сессию if (strlen($name)>1) $s['name']=$name;

if (!isset($s['name'])) // если имя еще не введено, выводим форму для ввода echo "Вы новый пользователь. Пожалуйста, введите ваше имя:

"; else // иначе пишем имя из сесси echo "Вы зарегистрированы под именем: $s[name]"; ?>



Приступим к работе с сессиями


Для начала решим, как правильно должны начинаться наши скрипты и что мы собираемся хранить в сессиях. Предложение N1 - несколько строк, которые будут отвечать за правильный запуск сессий и обработки новых пользователей, которым надо записать какие-то переменные для начала пработы, хорошо бы поместить в отдельный файл. Итак, файл index.php будет главным на сайте, а описанные команды мы поместим в default.php.

Предложение N2 - наша программа будет содержать много функций, в которых иногда будет происходить доступ к переменным сессий, следовательно последние надо будет делать глобальными в функциях. Если у нас будет десяток переменных, то нам придется писать большую строку для объявления переменных глобальными. Если же мы зарегистрируем в сессиях только одну переменную-массив с коротким названием, то нам будет легко ее прописывать глобальной и легко обращаться. Итак, предложение 2 - используем переменную $s, все необходимые параметры пишем в $s как в массив: $s[название]=значение.

Что записывать всем пользователям по умолчанию? Давайте, при входе нового посетителя, будет объявлять переменную $s[start], в которой запишим время входа пользователя. Чтобы получить текущее время (число) используют time(). Больше ничего делать с новыми посетителями не надо. На главной страние мы будем выводить фразу "Добро пожаловать!", если человек впервые тут и фразу "Вы пришли к нам ?? секунд назад". Подсчитать кол-во секунд весьма просто: time() - текущее время, $s[start] - уже прошедшее (когда мы произвели запись $s[start]). Таким образом, надо от большего отнять меньшее. Пишем эту программу.

Файл default.php:

Файл index.php (или любой файл вашего будущего сайта)


Данный пример поможно посмотреть тут: /php/s/example1/



Обратите внимание, что программа при выключенных куках работать не будет. Для его работоспособности надо при первом обращении пользователя сделать header("Location: $PHP_SELF?".SID);

(разумеется, при этом человек не увидет приветствие).

На этом пока придеться закончить, остальное допишу через несколько дней. Пока вы можете смотреть уже готовые примеры этого сайта, использующие сессии:

простой пример работы с сессиями

защита от двойного сабмита (SUBMIT формы)

виртуальный магазин



Программа для скачивания бинарных файлов по HTTP


Надеюсь, все уже изучили пример отправки сообщения на ICQ, которая демонстрирует 2 вещи: работа с сокетами (послали команду, считали ответ - точно также, как читать из файла) и отправка POST запросов (генерация параметров, кодирование, вставка переменных в POST запрос).

Здесь тоже самое: открываем сокет, шлем GET форму, читаем ответ. Ответ состоит из 2х вещей: заголовок и тело документа. Т.к. название данной статьи - получение файла, то очевидно, нас наиболее волнует именно тело документа (т.е. файл), а не все, что выдаст сервер. Тело от заголовка отделено строкой "\r\n".

Чтобы применить программу, замените строку "php.spb.ru" на имя вебсервера в 2х местах. Затем замените "/files/notepad.exe" на путь к файлу... В конце программы вместо "download.tmp" укажите, куда поместить скаченный файл (и надо ли его вообще в файл записывать).



Не забываем читать бинарные данные из сокета функций fread, а заголовок - текстовой функцией fgets. Можно все читать fread, но fgets нас избавит от не простого поиска пустой строки, отделяющей заголовок от тела.

Для записи файла открываем его в режиме "wb+": если файла не было - создать ("плюс"), если был - урезать до 0 байт ("w"), открыть в режиме бинарной записи ("b").

Смотрите также: загрузка бинарных файлов в базу данных

UPLOAD файлов



u="u217.97.spylog.com";d=document;nv=navigator;na=nv.appName;t="";p=1; sz=" width=88 height=31 "; hl=history.length;d.cookie="b=b";c=0; bv=Math.round(parseFloat(nv.appVersion)*100); if (d.cookie) c=1;n=(na.substring(0,2)=="Mi")?0:1; if((n==0)||(bv >= 300)){rn=Math.random();t=(new Date()).getTimezoneOffset();} else {rn=0;} z="p="+p+"&rn="+rn+"&t="+t+"&c="+c+"&hl="+hl; if (self != top) { fr=1;} else { fr=0;} r=escape(d.referrer);r1=""; sl="1.0";h=0; pl="";sl="1.1"; if((n==1) && (bv >= 300)) { for(var i = 0; i < nv.plugins.length; i++) pl += nv.plugins[i].name+":"; } j = (navigator.javaEnabled() ? "Y" : "N"); sl="1.2";s=screen;wh=s.width+'x'+s.height; px=(n==0)?screen.colorDepth:screen.pixelDepth;z+="&wh="+wh+"&px="+px; sl="1.3" y=""; y+=""; y+="

"; y+=""; d.write(y);

hotlog_js=0; function HotLOG() {}

hotlog_js=1

hotlog_js=2

hotlog_js=3

HotLOG(4535,hotlog_js)



Программирование на php на примере галереи, в х вариантах


Предлагаю вашему вниманию пример программирования на языке php с использованием баз данных mysql (в одном из вариантов программы) на примере создания галереи фотографий, картинок и т.п. Картинки в предпросмотре должны быть определенной ширины (чтобы не расползалась страница). Подобный вариант используется мной здесь (2 вариант) и здесь (1 вариант).

Галерея имеет следующие свойства:

предпросмотр; навигация "вперед-назад"; навигация по номерам страниц галереи; наличие описаний к картинкам; администрирование описаний к картинкам; варианты 2 и 3 имеют возможность изменять порядок вывода картинок; вариант 3 сделан с использованием базы mysql варианты 1 и 3 легко преобразуемы в галерею с возможностью дополнения галереи посетителями; если вы обнаружили еще какие-то свойства галереи, буду рад выслушать ваше мнение по адресу totoeval@mtu-net.ru

Вариант 1
Программа ищет файлы картинок в указанном ей каталоге с маленькими картинками (предпросмотр). Затем она ищет описания для выводимых картинок в текстовом файле. Определяет кол-во картинок и создает навигацию по галерее. Определяет размеры картинок и выводит их с описаниями и с яваскриптом на каждой картинке, который открывает большой вариант картинки в новом окне с размерами на 40 пикселей больше размера картинки с возможностью скроллинга, если таковой окажется необходим для просмотра картинки полностью (при малом размере экрана).

Вот собственно и код варианта:

<html> <head> <TITLE>Photo-galery</TITLE> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=Windows-1251"> <LINK REL=STYLESHEET TYPE="text/css" href="../../style.css">

</head> <body leftmargin=0 topmargin=0 marginwidth="0" marginheight="0">

<table width=650 cellspacing=0 cellpadding=5 border=0 cols=2><tr><td> <div align="center"> <br> <p align="center" class="zag-main">Картинная галерея.</p> <? // Пишем переменные, которые зависят от Вас // $scrpic=10; // максимальное кол-во фоток на странице$big='../pic/big_regats/'; // путь к большим картинкам $small='../pic/small_regats/'; // путь к малым картинкам $ini=$DOCUMENT_ROOT.'/avrora/pic/read/read_regats.ini'; // путь к файлу с текстами к картинкам // //В данном случае, файл строится так: строка с названием картинки (без расширения файла) //затем строка с подписью к картинке //затем название следующей картинки и так далее. // //Например: //1 //Моя первая фотография //rt //моя фотография rt.jpg //.... и так до последней картинки. Если подписи к картинке нет, то надо оставлять пустую строку. // // $kav="'"; // одинарные кавычки пригодятся нам потом в таком виде // для отображения в браузере в яваскрипте. Там необходимо иметь оба вида кавычек, // а для php надо еще поставить выводимое выражение в кавычки. $podp='увеличить'; // надпись под картинкой, // побуждающая клиента нажать на картинку для увеличения // $style_zag2='zag2-main'; // стили текста на странице $style_osn='osn-main'; // стили текста на странице $style_link='link'; // стили текста на странице // // //сама программа $text=file($ini); // читаем файл с подписями к картинкам в массив $text $dir=$small; // указываем путь к каталогу малых фотографий $handle=opendir($dir); // читаем заголовок каталога $si=0; // счетчик файлов в папке while ($file = readdir($handle)) { // читаем файл, пока не закончатся if ($file!="..") { // исключаем из списка файлов "." и ".." (корень и верхний каталог). $pic[$si]=$file; // присваиваем текущему элементу массива с именами файлов имя текущего файла $si++; // плюсуем к счетчику файлов в папке 1 } } // следующий файл $maxpic=count($pic)-1; // сколько файлов в папке с малыми картинками


if ($begin=="") { // если на страницу зашли впервые, то $begin присваеваем 1 $begin=1; } $end=$begin+$scrpic-1; // $end - номер последней картинки на странице if ($end>$maxpic) { // если последний номер на странице больше кол-во картинок в папке, // то он равен последнему $end=$maxpic; } $beginrew=$begin-$scrpic; // при переходе назад, начинаем показывать картинки с номера, //равному "первый номер текущей страницы минус кол-во картинок на странице" $beginfw=$begin+$scrpic; // при переходе вперед, начинаем показывать картинки с номера, //равному "первый номер текущей страницы плюс кол-во картинок на странице" $hrefrew='<a href='.$PHP_SELF.'?begin='.$beginrew.' class='.$style_zag2.'>назад</a>'; // создаем ссылку "назад" $hreffw='<a href='.$PHP_SELF.'?begin='.$beginfw.' class='.$style_zag2.'>вперед</a>'; // создаем ссылку "вперед" $navig=$hrefrew.' || '.$hreffw; // ставим между ссылками "назад-вперед" символ "||" if ($beginrew<=0) { // если мы на первой странице, то ссылка назад не нужна // $hrefrew='<a href='.$PHP_SELF.'?begin='.$beginrew.' class='.$style_zag2.'>назад</a>'; $navig=$hreffw; } if ($beginfw>$maxpic) { // если мы на последней странице, то ссылка вперед не нужна // $hreffw='<a href='.$PHP_SELF.'?begin='.$beginfw.' class='.$style_zag2.'>вперед</a>'; $navig=$hrefrew; } // вывод на экран номеров страниц галереи $scrmax=ceil($maxpic/$scrpic); // вычисляем, сколько страниц с картинками for ($scr=1; $scr<=$scrmax; $scr++) { // начиная с первого номера до кол-ва страниц галереи $beginsrc=($scr-1)*$scrpic+1; // вычисляем номер картинки, // с которого будут выводиться картинки на странице if ($beginsrc==$begin) { // если страница текущая, // то ее номер выводим в виде простого текста, а не ссылки echo '  <span class='.$style_zag2.'>'.$scr.'</span>  '; } else { // если страница не текущая, то выводим ссылку на нее и передаем параметры: // номер картинки, с которой начать выводить на этой странице echo ' <a href='.$PHP_SELF.'?begin='.$beginsrc.' class='.$style_zag2.'> '.$scr.' </a> '; } } echo '<p align=center class='.$style_zag2.'>'.$navig.'</p>'; // вывод на экран навигации "вперед-назад"



for ($i=$begin; $i<=$end; $i++) { // начиная с первой картинки на странице, // перебираем картинки вплоть до последней на странице for ($j=0; $j<sizeof($text); $j++) { // читаем файл ини и собираем описания $name_file=explode(".",$pic[$i]); //выделяем в названии файла его имя (без расширения) if (trim($text[$j])==$name_file[0]) { // ищем название картинки, // предварительно обрезав пробелы вокруг названия картинки в файле // (если текущее название картинки $pic[$i] совпадает с проверяемым $text[$j]) $descript=trim($text[$j+1]); // если картинка найдена, то в $descript пишем описание к картинке } else { // если название картинки не совпадает с искомым, то плюем на него } } $photo=$big.$pic[$i]; // присваиваем $photo имя малого файла+путь к папке с большими картинками $size=getimagesize($photo); // читаем информацию о картинке $width=$size[0]+40; // получаем ширину картинки и + 40 (свободное поле вокруг картинки) $height=$size[1]+40; // получаем высоту картинки и + 40 (свободное поле вокруг картинки) $sxp=$size[2]; // получаем тип (расширение файла картинки) $smphoto=$small.$pic[$i]; // присваиваем $smphoto имя малого файла+путь к папке с малыми картинками $smsize=getimagesize($smphoto); // читаем информацию о картинке $smwidth=$smsize[0]; // получаем ширину картинки $smheight=$smsize[1]; // получаем высоту картинки $smexp=$smsize[2]; // получаем тип (расширение файла картинки) $winstat='toolbar=0,location=0,directories=0,status=0,menubar=0,scrollbars=1,resizable=1,width='.$width.',height='.$height;
// статус открываемого окна с большой картинкой

// выводим таблицу галереи. // если номер картинки четный, то картинка слева, а описание справа и наоборот // делаем это для неужасного внешнего вида галереи // Вы можете разположить картинки как Вам заблагорассудится. // итак: ?><table width=420 cellspacing=0 cellpadding=5 border=0 cols=2><tr><?

// выводим одинаковую часть кода таблицы дл ячейки картинки //Далее выводим картинки в ячейках таблиц с описаниями. Делаем все с "предпросмотром" //"предпросмотр предпочтителен, потому что не надо сразу грузить большие файлы, //а клиент если захочет, сам загрузит то, что его заинтересовало в новых окнах. // if ($i/2==ceil($i/2)) { // если номер картинки на странице четный echo '<td width=210 rowspan=2> <p class='.$style_osn.'>'.$descript.'</p> </td><td hight='.($smheight+2).'> <table width=202 cellspacing=1 cellpadding=0 border=0 bgcolor="#000000" border=0><tr><td> <a href='.$photo.' target="'.$i.'" onclick="window.open('.$kav.$photo.$kav.', '.$kav.$i.$kav.', '.$kav.$winstat.$kav.');"> <img src='.$smphoto.' width='.$smwidth.' height='.$smheight.' border=0 alt="увеличить"> </a> </td></tr></table> </td></tr> <tr><td valign=top> <center> <a href='.$photo.' target="'.$i.'" onclick="window.open('.$kav.$photo.$kav.', '.$kav.$i.$kav.', '.$kav.$winstat.$kav.');" CLASS='.$style_link.'>'.$podp.' </a> </center> </td></tr></table>'; } else { // если номер картинки нечетный echo '<td align=left><table width=202 cellspacing=1 cellpadding=0 border=0 bgcolor="#000000"><tr> <td hight='.($smheight+2).'> <a href='.$photo.' target="'.$i.'" onclick="window.open('.$kav.$photo.$kav.', '.$kav.$i.$kav.', '.$kav.$winstat.$kav.');"> <IMG SRC='.$smphoto.' width='.$smwidth.' height='.$smheight.' border=0 alt="увеличить"> </a> </td></tr></table> </td> <td width=210 rowspan=2> <p align=left class='.$style_osn.'>'.$descript.'</p> </td></tr> <tr><td valign=top> <center> <a href='.$photo.' target="'.$i.'" onclick="window.open('.$kav.$photo.$kav.', '.$kav.$i.$kav.', '.$kav.$winstat.$kav.');" CLASS='.$style_link.'>'.$podp.' </a> </center> </td></tr></table>'; } } // вывод на экран "вперед-назад" echo '<p align=center class='.$style_zag2.'>'.$navig.'</p>'; // вывод на экран номеров страниц echo '<div align=center>'; for ($scr=1; $scr<=$scrmax; $scr++) { $beginsrc=($scr-1)*$scrpic+1; if ($beginsrc==$begin) { echo '  <span class='.$style_zag2.'>'.$scr.'</span>  '; } else { echo ' <a href='.$PHP_SELF.'?begin='.$beginsrc.' class='.$style_zag2.'> '.$scr.' </a> '; } }



?>

</div> </td></tr></table> </body> </html>

Программа администрирования текстов описаний:
Была применена в моей статье um.ru/internet/articles/weather.shtml">Импортирование информации с чужого сайта на свой сайт в свой дизайн. Я считаю этот способ самым проостым для начинающего программиста. Более сложный способ обновления я собираюсь сделать в будущих статьях.
Конечно, можно делать более серьезные интерфейсы, но в этом варианте, который конечно не рассчитан на ламера, можно быстро править сразу все позиции.
Вот собственно код:

<html> <head> <title>admin weather</title> </head> <body> <?php $adr=$DOCUMENT_ROOT."/avrora/pic/read/read_regats.ini"; // адрес файла, в котором и будут записываться названия файлов с описаниями $password='pass'; // простенькая система авторизации $eror='Password eror!'; $old=file($adr); // читаем то, что сейчас есть в файле if ($submit) { // проверяем на нажатость кнопки if ($pass==$password) { $fp=fopen($adr,"w"); fwrite ($fp, $ini); // записываем в файл измененные данные fclose($fp); $old=file($adr); } else { echo $eror; } } ?>

<form method=post action="<?php echo $PHP_SELF?>"> // информация, введенная в форму, обрабатывается этим же файлом password:<input type=text name=pass><br> inicialisation:<textarea name="ini" rows=15 cols=60> <? for ($i=0; $i<sizeof($old); $i++) { echo $old[$i], ""; // выводим на экран текущий вариант файла } ?> </textarea> <br> <input type=submit name="submit" value="Enter"> </form>

</body> </html>

В этом варианте, файл создаем так, как написано в комментарии к программе:
1
Моя первая фотография
rt
моя фотография rt.jpg

, где 1 и rt - имена файлов, а строки под ними соответственно описания к ним.

Вариант 2
Отличие этого варианта отпредыдущего в том, что программа читает файл инициализации галереи. В каждой строке такая конструкция (так надо заполнять файл для этого варианта!):
1.jpg|Моя первая фотография
rt.jpg|моя фотография rt.jpg
где символ "|" - это разделитель между описанием и именем файла картинки.



Как видно, в этом варианте надо писать в файле имя файла картинки с расширением. Если это вам это очень мешает, то можете переделать так, чтобы было в файле только имя, а расширение определялось бы автоматически, основываясь на первом примере.
Алгоритм такого варианта будет:
определить имя картинки, считать имена файлов в папке с файлами, обрезая у имен файлов расширения, находим нужный, сравнивая каждый раз с тем, что взяли из файла. Именно совпавший и будет искомым.

Далее программа, создав массив из имен и описаний картинок, определяет, на какой странице галереи клиент находится и выводит ему соответственно ту или иную страницу.
Сам движок галереи остается тем же, как вы наверное заметили.
Изменяются некоторые его части.
Вот сам код:

<html> <head> <TITLE>Photo-galery</TITLE> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=Windows-1251"> <LINK REL=STYLESHEET TYPE="text/css" href="../../style.css">

</head>

<body leftmargin=0 topmargin=0 marginwidth="0" marginheight="0"> <table width=650 cellspacing=0 cellpadding=5 border=0 cols=2><tr><td> <div align="center">

<br>

<p align="center" class="zag-main">Картинная галерея.</p>

<? // Пишем переменные, которые зависят от Вас // $scrpic=10; // максимальное кол-во фоток на странице$big='../pic/big_regats/'; // путь к большим картинкам $small='../pic/small_regats/'; // путь к малым картинкам $ini=$DOCUMENT_ROOT.'/avrora/pic/read/read_regats1.ini'; // путь к файлу с текстами к картинкам // //В данном случае, файл строится так: строка с названием картинки (без расширения файла) //затем строка с подписью к картинке //затем название следующей картинки и так далее. // //Например: //1|Моя первая фотография //rt|моя фотография rt.jpg //.... и так до последней картинки. Если подписи к картинке нет, то надо оставлять пустую строку. // // $kav="'"; // одинарные кавычки пригодятся нам потом в таком виде // для отображения в браузере в яваскрипте. Там необходимо иметь оба вида кавычек, // а для php надо еще поставить выводимое выражение в кавычки. $podp='увеличить'; // надпись под картинкой, // побуждающая клиента нажать на картинку для увеличения // $style_zag2='zag2-main'; // стили текста на странице $style_osn='osn-main'; // стили текста на странице $style_link='link'; // стили текста на странице // // //сама программа



$text=file($ini); // читаем файл с подписями к картинкам в массив $text

for ($i=0; $si<sizeof($text); $i++) { // читаем файл ини и сохраняем имена картинок. $si=$i+1; $string=explode("|",$text[$i]); $pic[$si]=$string[0]; // присваиваем текущему элементу массива с именами файлов имя текущего файла $description[$si]=$string[1]; }

$maxpic=count($pic); // сколько файлов в папке с малыми картинками

if ($begin=="") { // если на страницу зашли впервые, то $begin присваеваем 1

$begin=1; }$end=$begin+$scrpic-1; // $end - номер последней картинки на странице if ($end>$maxpic) { // если последний номер на странице больше кол-во картинок в папке, // то он равен последнему $end=$maxpic; }

$beginrew=$begin-$scrpic; // при переходе назад, начинаем показывать картинки с номера, //равному "первый номер текущей страницы минус кол-во картинок на странице" $beginfw=$begin+$scrpic; // при переходе вперед, начинаем показывать картинки с номера, //равному "первый номер текущей страницы плюс кол-во картинок на странице"

$hrefrew='<a href='.$PHP_SELF.'?begin='.$beginrew.' class='.$style_zag2.'>назад</a>'; // создаем ссылку "назад" $hreffw='<a href='.$PHP_SELF.'?begin='.$beginfw.' class='.$style_zag2.'>вперед</a>'; // создаем ссылку "вперед" $navig=$hrefrew.' || '.$hreffw; // ставим между ссылками "назад-вперед" символ "||" if ($beginrew<=0) { // если мы на первой странице, то ссылка назад не нужна

// $hrefrew='<a href='.$PHP_SELF.'?begin='.$beginrew.' class='.$style_zag2.'>назад</a>';

$navig=$hreffw; } if ($beginfw>$maxpic) { // если мы на последней странице, то ссылка вперед не нужна

// $hreffw='<a href='.$PHP_SELF.'?begin='.$beginfw.' class='.$style_zag2.'>вперед</a>';

$navig=$hrefrew; }

// вывод на экран номеров страниц галереи

$scrmax=ceil($maxpic/$scrpic); // вычисляем, сколько страниц с картинками

for ($scr=1; $scr<=$scrmax; $scr++) { // начиная с первого номера до кол-ва страниц галереи $beginsrc=($scr-1)*$scrpic+1; // вычисляем номер картинки, // с которого будут выводиться картинки на странице if ($beginsrc==$begin) { // если страница текущая, // то ее номер выводим в виде простого текста, а не ссылки echo '  <span class='.$style_zag2.'>'.$scr.'</span>  '; } else { // если страница не текущая, то выводим ссылку на нее и передаем параметры: // номер картинки, с которой начать выводить на этой странице echo ' <a href='.$PHP_SELF.'?begin='.$beginsrc.' class='.$style_zag2.'> '.$scr.' </a> '; } }



echo '<p align=center class='.$style_zag2.'>'.$navig.'</p>'; // вывод на экран навигации "вперед-назад"

for ($i=$begin; $i<=$end; $i++) { // начиная с первой картинки на странице, // перебираем картинки вплоть до последней на странице

$descript=$description[$i];

$photo=$big.$pic[$i]; // присваиваем $photo имя малого файла+путь к папке с большими картинками $size=getimagesize($photo); // читаем информацию о картинке $width=$size[0]+40; // получаем ширину картинки и + 40 (свободное поле вокруг картинки) $height=$size[1]+40; // получаем высоту картинки и + 40 (свободное поле вокруг картинки) $sxp=$size[2]; // получаем тип (расширение файла картинки)

$smphoto=$small.$pic[$i]; // присваиваем $smphoto имя малого файла+путь к папке с малыми картинками $smsize=getimagesize($smphoto); // читаем информацию о картинке $smwidth=$smsize[0]; // получаем ширину картинки $smheight=$smsize[1]; // получаем высоту картинки $smexp=$smsize[2]; // получаем тип (расширение файла картинки) $winstat='toolbar=0,location=0,directories=0,status=0,menubar=0,scrollbars=1,resizable=1,width='.$width.',height='.$height;
// статус открываемого окна с большой картинкой // выводим таблицу галереи. // если номер картинки четный, то картинка слева, а описание справа и наоборот // делаем это для неужасного внешнего вида галереи // Вы можете расположить картинки как Вам заблагорассудится. // итак: ?><table width=420 cellspacing=0 cellpadding=5 border=0 cols=2><tr><? // выводим одинаковую часть кода таблицы дл ячейки картинки

//Далее выводим картинки в ячейках таблиц с описаниями. Делаем все с "предпросмотром" //"предпросмотр предпочтителен, потому что не надо сразу грузить большие файлы, //а клиент если захочет, сам загрузит то, что его заинтересовало в новых окнах. // if ($i/2==ceil($i/2)) { // если номер картинки на странице четный echo '<td width=210 rowspan=2><p CLASS='.$style_osn.'>'.$descript.'</p ></td><td hight='.($smheight+2).'> <table width=202 cellspacing=1 cellpadding=0 border=0 bgcolor="#000000" border=0><tr><td> <A HREF='.$photo.' target="'.$i.'" onclick="window.open('.$kav.$photo.$kav.', '.$kav.$i.$kav.', '.$kav.$winstat.$kav.');"> <IMG SRC='.$smphoto.' WIDTH='.$smwidth.' HEIGHT='.$smheight.' BORDER=0 alt="увеличить"></A></td></tr></table ></td></tr><tr><td valign=top><center>
<A HREF='.$photo.' target="'.$i.'" onclick="window.open('.$kav.$photo.$kav.', '.$kav.$i.$kav.', '.$kav.$winstat.$kav.');"
CLASS='.$style_link.'>
'.$podp.'</a></center></td></tr></table>'; } else { // если номер картинки нечетный echo '<td align=left><table width=202 cellspacing=1 cellpadding=0 border=0 bgcolor="#000000"> <tr><td hight='.($smheight+2).'> <A HREF='.$photo.' target="'.$i.'" onclick="window.open('.$kav.$photo.$kav.', '.$kav.$i.$kav.', '.$kav.$winstat.$kav.');"> <IMG SRC='.$smphoto.' WIDTH='.$smwidth.' HEIGHT='.$smheight.' BORDER=0 alt="увеличить"> </A></td></tr></table> </td><td width=210 rowspan=2><p align=left CLASS='.$style_osn.'>'.$descript.'</p ></td></tr><tr><td valign=top><center>
<A HREF='.$photo.' target="'.$i.'" onclick="window.open('.$kav.$photo.$kav.', '.$kav.$i.$kav.', '.$kav.$winstat.$kav.');"
CLASS='.$style_link.'>'.$podp.'</a></center></td></tr></table>'; } }



// вывод на экран "вперед-назад" echo '<p align=center class='.$style_zag2.'>'.$navig.'</p>';

// вывод на экран номеров страниц echo '<div align=center>'; for ($scr=1; $scr<=$scrmax; $scr++) { $beginsrc=($scr-1)*$scrpic+1; if ($beginsrc==$begin) { echo '  <span class='.$style_zag2.'>'.$scr.'</span>  '; } else { echo '<a href='.$PHP_SELF.'?begin='.$beginsrc.' class='.$style_zag2.'> '.$scr.' </a> '; } }

?> </div> </td></tr></table>

</body> </html> 

Программа администрирования та же, что и в варианте 1.

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

<?
//инициализация mysql:
$mysql_login='my_login';
$mysql_host='host_db';
$mysql_pass='my_password';
$mysql_db='name_db';
//

mysql_connect($mysql_host,$mysql_login,$mysql_pass);
mysql_select_db($mysql_db);
mysql_query("set CHARACTER SET cp1251_koi8") or die ("!--не могу записать"); // эта строка
используется, если сайт в кодировке win, а база в кодировке кои-8.
Если кодировки совпадают, строку надо закомментировать.

$query="CREATE TABLE galery_regats (numer tinyint(4) NOT NULL, name text NOT NULL, description text NOT NULL)";
$res=mysql_query($query) or die ("!--не могу создать таблицу");


header("location: admin.php"); // переход на страницу администрирования

?>



Программа администрирования:

<html> <head> <title>Admin galery</title> <link rel=stylesheet type="text/css" href="../../style.css"> </head> <body bgcolor=#eeeeee> <br>

<? // логин/пароль $log='total'; $pas='total'; //инициализация mysql: $mysql_login='my_login'; $mysql_host='host_db'; $mysql_pass='my_password';
$mysql_db='name_db'; // $style_zag2='zag2-main'; // стили текста на странице $style_osn='osn-main'; // стили текста на странице$style_link='link'; // стили текста на странице $kon_str="\n"; // конец строки $razdel="|"; // разделитель между именем картинки и описанием ?> <p align="center" class="<? echo $style_zag2; ?>">Картинная галерея.</p> <? mysql_connect($mysql_host,$mysql_login,$mysql_pass); mysql_select_db($mysql_db); mysql_query("set CHARACTER SET cp1251_koi8") or die ("!--не могу записать"); switch ($prov) { // проверяем состояние переменной $prov case "edit": // если пишем новый вариант базы: if ($login!=$log || $pass!=$pas) { echo "Введите правильно логин/пароль"; } // если пароль неверен else { // удаляем текущую базу картинок и создаем пустую таблицу $query="DROP TABLE galery_regats" $res=mysql_query($query) or die ("!--не могу удалить таблицу"); $query="CREATE TABLE galery_regats (numer tinyint(4) NOT NULL, name text NOT NULL, description text NOT NULL)"; $res=mysql_query($query) or die ("!--не могу создать таблицу"); $pics=explode($kon_str,$block); // бьем наш список по символу переноса строки for ($i=0; $i<sizeof($pics); $i++) { // пишем в базу данные $string=explode($razdel,$pics[$i]); // бьем строки по символу разделителя $query="insert into galery_regats (number, name, description) values ('$i', '$string[0]', '$string[1]')"; mysql_query($query) or die ("!--не могу записать"); // пишем в таблицу } } break; default: // если мы зашли не по нажатию на ентер: // читаем базу картинок и сохраняем в массивы $zapros="select * from galery_regats order by numer";$res=mysql_query($zapros); $kol=mysql_num_rows($res); if ($kol==0) { echo "<span class=$style_osn>Нет картинок в галерее.</span>"; } for ($i=0; $i<$kol; $i++) { // читаем базу и сохраняем имена картинок. $pic[$i]=mysql_result($res,$i,"name"); // присваиваем текущему элементу массива $description[$i]=mysql_result($res,$i,"description"); } break; } } ?> <form method=post action="<? echo $PHP_SELF; ?>"> <textarea name="block" rows="40" cols="40"> <? // выводим текущее состояние базы картинок for ($i=0; $i<sizeof($pic); $i++) { echo $pic[$i].$razdel.$description[$i].$kon_str; } ?> </textarea> <input type="text" name="login" size="10"> <input type="text" name="pass" size="10"> <input type="hidden" name="prov" value="edit"><input type="submit" name="enter" value="Enter"> </form> </body> </html>



Форма заполняется как и во втором варианте.А для получения 3-го варианта в коде программы 2- го варианта строки от строки //сама программадо строки$maxpic=count($pic); // сколько файлов в папке с малыми картинкамикоторые являются блоком считывания файла в массивы, заменяются на блок: mysql_connect($mysql_host,$mysql_login,$mysql_pass); // соединение с базой (коннект) mysql_select_db($mysql_db); // выбор базы mysql_query("set CHARACTER SET cp1251_koi8") or die ("-------------не могу записать"); // Если кодировки базы и сайта совпадают - закомментировать эту строку

$zapros="select * from galery_regats order by numer"; $res=mysql_query($zapros); $kol=mysql_num_rows($res); if ($kol==0) { echo "Нет картинок в галерее."; } for ($i=0; $i<$kol; $i++) { // читаем файл ини и сохраняем имена картинок. $si=$i+1; $pic[$si]=mysql_result($res,$i,"name"); // присваиваем текущему элементу массива с именами файлов имя текущего файла $description[$si]=mysql_result($res,$i,"description"); }

Результат работы блока точно такой же, что и во втором варианте - массивы $pic и $description, где храним имена файлов картинок и описания к ним. Но работает такая галерея быстрее. Однако, каждый раз, когда хотите залить новую картинку, надо администрить галерею, даже если не нужно описание. А в первом варианте стоит только лишь закинуть в папки файлы картинок.

Таким образом, получаем 3 рабочих варианта программы галереи. Если будут возникать вопросы по работе программы, адаптации под "свой сайт" или по принципам, пишите мне по адресу totoeval@mtu-net.ru

Тотоев Александр
http://www.czar.ru/
http://www.nova-wings.ru/

<


Простая форма


Простая форма

Тарасенко Сергей, Webscript.ru

Одна из наиболее удобных и приятных особенностей PHP - это его способность автоматически передавать значения переменных из форм в переменные PHP. Это очень облегчает обработку форм.

Например, Вы обрабатываете форму, которая имеет поле ввода следующего вида:

<INPUT TYPE=TEXT NAME="name" VALUE="Glen Morris">

и в то время, когда выводится страница с этим PHP-кодом, переменная $name имеет значение Glen Morris.

Тогда Вы можете вывести это значение на экран:

echo "Hi $name!";

или вставить проверку в условном операторе:

if ($name == "Glen Morris") { echo "Please check your email."; }

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

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

Вывод формы

Первая функция служит для вывода формы:

<?php

function display_form() {

  global $PHP_SELF;

?>

<FORM TARGET="<?php echo $PHP_SELF; ?>" METHOD=GET>

Имя:   <INPUT TYPE=TEXT NAME="name"><BR>

Любимый сорт сыра: <INPUT TYPE=RADIO NAME="cheese" VALUE="brie">Very soft French Brie

                 <INPUT TYPE=RADIO NAME="cheese" VALUE="cheddar">Farmhouse English Cheddar

                 <INPUT TYPE=RADIO NAME="cheese" VALUE="mozzarella">Italian Buffalo Mozzarella


Когда Вы предпочитаете есть сыр:

                 <INPUT TYPE=CHECKBOX NAME="times[]" VALUE="m">На завтрак

                 <INPUT TYPE=CHECKBOX NAME="times[]" VALUE="n">В обед

                 <INPUT TYPE=CHECKBOX NAME="times[]" VALUE="d">На ужин

                 <INPUT TYPE=CHECKBOX NAME="times[]" VALUE="l">Поздно ночью

<INPUT TYPE=HIDDEN NAME="stage" VALUE="results">

<INPUT TYPE=SUBMIT VALUE="Thanks!">

</FORM>

<?php

}

?>



Большая часть представленного выше текста есть обычный HTML-текст, необходимый для формирования формы. Однако есть пара сложных моментов, требующих особого пояснения.

Во-первых, это переменная $PHP_SELF. $PHP_SELF - это удобная форма ссылки, ее значение равно URL текущей страницы. Мы задаем атрибуту TARGET

этой формы значение $PHP_SELF, потому что мы хотим, чтобы эта страница обрабатывала форму. Используя $PHP_SELF

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

Кстати, строка

global $PHP_SELF;

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

Во-вторых, как Вы могли заметить, мы свободно переходим в режим PHP и обратно даже внутри функции. Это полностью законно. PHP умеет игнорировать HTML-код и выделять только PHP-блоки. Это быстрее, чем оставаться в режиме PHP и организовывать вывод HTML, используя echo.



Теперь обратите внимание на атрибут NAME тега INPUT. Вы видите, что в случае, если тип поля ввода есть CHECKBOX, то после наименования поля (в данном случае times[]) стоит пара квадратных скобок, Если же тип поля ввода есть RADIO, то после имени (cheese) таких скобок нет. Это объясняется тем, что поля типа RADIO служат для выбора одного и только одного из вариантов ответа, поэтому значением переменной cheese будет одна строка. Поля типа CHECKBOX (их несколько) позволяют выбрать (или не выбрать) каждый из возможных вариантов, поэтому для сохранения ответов пользователя PHP должен запомнить их в виде массива. Добавление [] после имени переменной times и указывает на то, что в данном случае это массив, а не единичная переменная.

И, наконец, в этом куске кода имеется скрытая переменная с именем stage. Мы используем $stage чтобы сказать программе, хотим ли мы вывести форму или отобразить результаты обработки ответов.

Обработка формы

Теперь рассмотрим функцию process_form()

обработки формы после ввода ответов пользователем.



<?php

function process_form() {

  global $name;

  global $cheese;

  global $times;


  if ($cheese == 'brie') { $cheese_message = 'I love brie.'; }

  elseif ($cheese == 'cheddar') { $cheese_message = 'Cheddar is awesome!'; }

  else { $cheese_message = 'Fresh mozzarella is divine.'; }

  $favorite_times = count($times);

  if ($favorite_times <= 1) {

    $times_message = 'You should eat cheese more often.';

  } elseif ($favorite_times > 1 && $favorite_times < 4) {

  $times_message = 'Those are good times to eat cheese.';

  } else {

    $times_message = 'You are eating too much cheese.';

  }

  echo "Hello $name.";

  echo "$cheese_message $times_message";

}

?>

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



Далее используется функция count() для того, чтобы подсчитать, сколько раз в день ест сыр человек, ответивший на наши вопросы. Если в предыдущем случае мы должны были сравнить ответ посетителя с каждым из возможных значений переменной $cheese, то при анализе значений переменной $favorite_times

можно воспользоваться операциями сравнения "меньше чем" и "больше чем". Знаки && в условном операторе "$favorite_times > 1 && $favorite_times < 4" означают логическую операцию "И" ("and"). То есть $favorite_times должно одновременно быть больше 1 и меньше 4 для того, чтобы условие было выполнено.

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

Формируем Putting the Form Together

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



<?php

if (empty($stage)) { display_form(); }

else { process_form(); }

?>

Здесь мы вначале проверяем, задано ли какое-либо значение переменной $stage. В PHP переменная считается пустой (empty), если ее значение не задано явно (то есть ей никогда не придаются значения по-умолчанию), или ей задано пустое значение (переменной присвоено значение пусто, если она приравнена пустой строке - '', или ей присвоено значение 0). Когда посетитель впервые попадает на нашу страницу, переменная $stage пуста. Поэтому на страницу будет выводиться форма с нашими вопросами; в противном случае мы должны обработать заполненную форму.

И это все, что мы хотели сказать об обработке простых форм с помощью PHP.


Проверка рабоспособности flock на практике.


Для чего это написано.

Представьте, у вас есть нагруженная система (много посетителей), которая хранит какую-то информацию в файлах. Очевидно, любые скрипты по записи и чтении файлов могут работать параллельно и мешать друг-другу. Еще очевидно, что в таких операциях нужно использовать блокировку файлов, но даже в этом может быть проблема. Маленькая и незаметная, она проявляется только при большой нагрузке на сервер.

Сделаем 2 скрипта. Первый - будет писать в файл случайное число (берется из rand) на первой строке файла и md5 проверку этого числа строкой ниже. Прежде, чем записать файл скрипт его обрезает для записи - режим w. Второй - читает обе строки из файла и следит, что md5 соответствует числу из первой строки, т.к. как бы проверяет целостность файла.

В начале простой пример. Перезапись одного файла работает без проблем:

> /tmp/11qq")); // заблокировали flock($f,2);

// считали число $r=intval(fgets($f,100));

// проверка глюков - число не должно быть меньше 1 000 000 ! if ($r> /tmp/11qq");

// указатель на начало + запись обратно увеличенного числа fseek($f,0); fputs($f,($r+1)." ");

fclose($f);

?>

А вот чтение без блокировки с параллельной записью нарушает целостность данных. Делаем 2 скрипта - первый будет постоянно писать в файл, второй постоянно читать. Запись идет с блокировкой, чтение - без. Для теста запустите 2 утилиты, чтобы параллельно слать запросы на оба скрипта.

запись:

> /tmp/11qq")); flock($f,2);

function make_seed() { list($usec,$sec) = explode(" ", microtime()); return ((float)$sec+(float)$usec) * 100000; } mt_srand(make_seed());

$s = mt_rand(); $s=$s." ".microtime(); $md=md5($s);

fputs($f,"$s\n$md\n");

fclose($f);

?>

чтение

> /tmp/11qq")); $s=trim(fgets($f,100)); $md=trim(fgets($f,100)); if ($md!=md5($s)) system("echo error_md5 >> /tmp/11qq"); fclose($f); ?>

Каково же было мое удивление, когда от добавления flock в скрипт чтения ничего не изменилось...


> /tmp/11qq")); flock($f,2); $s=trim(fgets($f,100)); $md=trim(fgets($f,100));

if ($md!=md5($s)) { system("echo error_md5 >> /tmp/11qq"); echo "md5 error"; $ff=fopen ("/tmp/11log.txt","a+"); flock($ff,2); fputs($ff,time()." ".filesize("flock2_test.txt")." [$s|$md]\n"); fclose($ff); }

fclose($f); ?>

Пример 0.1% вызовов скрипта чтения заканчивался провалом. Во всех случаях мне скрипт читал пустой файл с 0-вой длиной.

Потом я проделал 2 хитрых фичи:

заменил
$f=fopen("flock2_test.txt","r+") or die(system("echo fopen_write >> /tmp/11qq")); flock($f,2);
на
flock($f=fopen("flock2_test.txt","r+"),2);
с надеждой, что теперь операция открытия + блокирования не будет разрываться. Это не помогло. Еще я придумал, делать usleep(10) после открытия и до блокировки в скрипте чтения... Типа, открыли файл и подвесили немного процесс с надеждой, что другие пишущие скрипты сумеют за это время заблокировать файл. Это тоже не помогло. Да, еще писал по 2 flock'f:
flock($f,1); flock($f,2);
на всякий случай :) И это не спасло.

Третья попытка удалась и проблема с активным чтением и записью решилась. Просто надо было в скрипте записи открывать файл не на обнуление (w), а только чтение+запись (r+). Одним словом проблема решилась заменой скрипта записи:

// открыли файл на чтение+запись $f=fopen("flock2_test.txt","r+") or die(system("echo fopen_write >> /tmp/11qq")); // заблокировали flock($f,2); // обнулили до 0 байт (как бы стерли) ftruncate($f,0);

Работа с сокетами


Функция file() (равно как и fopen() ) позволяет нам работать только с содержимым файла, который получен по тому или иному протоколу. Предположим, что нас интересуют заголовки, переданные сервером. Получить эти заголовки мы можем с помощью функции
int fsockopen(string $host, int $port, [, int &$errno] [, string &$errstr])
Данная функция позволяет инициализировать потоковое соединение с указанным хостом и программой, которая связана с указанным портом. Кроме того, эта функция поддерживает Unix-сокеты. При этом параметр $hostname будет использован как путь к файлу сокета, а параметр $port должен быть равен 0.
После установления соединения функция возвращает обыкновенный дескриптор файла. С этим дескриптором могут работать функции fread(), fwrite(), fgets(), feof() и другие.
В случае ошибки функция возвратит false и, если указаны необязательные параметры $errno и $errstr, соответственно, номер ошибки и текст сообщения об ошибке.
Рассмотрим листинг 3 – «Виртуальный браузер»: мы посылаем серверу HTTP-запрос GET и, получив ответ, выводим его в броузер.

Листинг 3. «Виртуальный браузер» <? // Подключаемся к серверу 1. $fsoc = fsockopen("localhost",80); 2. fputs($fsoc, "GET / HTTP/1.0\n\n"); 3. echo "<pre>"; 4. while (!feof($fsoc)) 5. echo HtmlSpecialChars(fgets($fsoc,1000)); 6. echo "</pre>"; // Отключаемся от сервера 7. fclose($fsoc); ?>

Как я уже отмечал выше, при использовании функции fsockopen мы получаем весь ответ сервера – вместе с заголовками. Функцию HtmlSpesialChars() мы используем для корректного отображения HTML-кода в текстовом формате. В броузере мы должны получить примерно следующее: HTTP/1.1 200 OK Date: Sat, 16 Mar 2002 10:46:59 GMT Server: Apache/1.3.12 (Linux) Last-Modified: Sat, 20 Nov 1999 13:29:40 GMT ETag: "0-574-3836a244" Accept-Ranges: bytes Content-Length: 1396 Connection: close Content-Type: text/html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> <HTML> sp;<HEAD> <TITLE>Test Page for Apache Installation</TITLE> </HEAD> ...


Ответ сервера HTTP/1. 1 200 OK соответствует коду ответа 200 и означает безошибочное выполнение операции (в данном случае передачи документа по запросу GET).

Установить нужный нам заголовок ответа мы можем с помощью функции Header(). Например, Header("Location://www.softerra.ru/freeos");
Запретить кэширование можно с помощью установки заголовка Pragma: no-cache. К сожалению одного этого заголовка явно не хватит для запрещения кэширования. Для полного запрета нужно использовать целых четыре заголовка. Установить с помощью Header их можно так:

Header("Pragma: no-cache"); Header("Cache-control: no-cache, must-revalidate"); Header("Expires: Mon, 01 Jan 1990 01:01:01 GMT"); Header("Last-Modified: ".gmdate("D, d M Y H:i:s")."GMT");

Первый из них устанавливает заголовок запрета кэширования согласно протокола HTTP/1.0, а второй – HTTP/1.1. Третий определяет задает дату в прошлом, а четвертый устанавливает дату последнего обновления документа. Функция gmdate() возвращает дату в нужном нам формате. Устанавливать все четыре заголовка крайне желательно, так как запрет кэширования может не сработать или на прокси-сервере или в броузере, и пользователь получит устаревшую версию документа.


Разбор возможных глюк.


если у вас Windows 95 в котором нет winsosks2, в результате чего Апач не запускается, то скачать и запустить два файла: 1(wsockupd.exe).exe

и 2(ws2setup.exe).exe. (зеркало файлов: копия 1, копия 2).

После этого reboot компа ... и Апач запустится.

если не запускается phptest.phtml (т.е. "PHP не пашет", вам пишут - "не найден файл msvcrt.dll" или в этом роде), то скорее всего из-за кривости Windows 95. Надо скопировать c:\www\php\msvcrt.dll в c:\windows\system\msvcrt.dll. Сделать это при работающем Windows не удасться (копируйте из Доса), т.к. данный файл открыт и заблокирован. Если в c:\windows\system не будет нужного файла MSVCIRT.DLL, то скачайте его отсюда: msvcirt.dll

(зеркало файла: копия 1, копия 2).

ссылки http://localhost/ или http://127.0.0.что-то/ работают, а http://dima/ или http://test/ не работает, то настаивайте свой тупой Internet Explorer... Все должно работать.



u="u217.97.spylog.com";d=document;nv=navigator;na=nv.appName;t="";p=1; sz=" width=88 height=31 "; hl=history.length;d.cookie="b=b";c=0; bv=Math.round(parseFloat(nv.appVersion)*100); if (d.cookie) c=1;n=(na.substring(0,2)=="Mi")?0:1; if((n==0)||(bv >= 300)){rn=Math.random();t=(new Date()).getTimezoneOffset();} else {rn=0;} z="p="+p+"&rn="+rn+"&t="+t+"&c="+c+"&hl="+hl; if (self != top) { fr=1;} else { fr=0;} r=escape(d.referrer);r1=""; sl="1.0";h=0; pl="";sl="1.1"; if((n==1) && (bv >= 300)) { for(var i = 0; i < nv.plugins.length; i++) pl += nv.plugins[i].name+":"; } j = (navigator.javaEnabled() ? "Y" : "N"); sl="1.2";s=screen;wh=s.width+'x'+s.height; px=(n==0)?screen.colorDepth:screen.pixelDepth;z+="&wh="+wh+"&px="+px; sl="1.3" y=""; y+=""; y+="

"; y+=""; d.write(y);

hotlog_js=0; function HotLOG() {}

hotlog_js=1

hotlog_js=2

hotlog_js=3

HotLOG(4535,hotlog_js)



Размещение бинарных файлов (картинок) в базе данных


Для помещеня бинарного файла в базу данных, надо...

1. создайте таблицу с полем BLOB

2. прочитайте данные, которые надо поместить в базу данных, в переменную $upload. Если это файл (картинка) на диске, то сделайте это так:

3. защитите переменную от опасных символов ("прослешьте переменную"):

... $upload=addslashes($upload); ...

4. загрузите переменную в базу данных:

... mysql_query("INSERT INTO () VALUES ('$upload')"); ?>

"Таблица" - имя таблицы, "поле" - название колонки в таблице типа BLOB, что были созданы при выполнении пункта 1. Разумеется, чтобы выполнить HTML запрос надо предварительно установить соединение с базой данных.

Для взятия бинарного файла из базы данных в браузере, надо...

Вы будете смеяться, но ничего особого не надо. Просто прочитайте ее как простую переемнную из базы данных. В переменную на языке ПХП можно упихать все, что надо. Правда, есть лимит памяти (будьте внимательны с переменными от 2 МБ), о котором надо помнить. Разумеется, лимит увеличить, но это тема не данной статьи.

Чтобы показать картинку их базы данных, надо...

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

FROM WHERE ") or die("SQL ERROR in line ".__LINE__.", function mysql_query"); $image=mysql_result($res, , ); // берем переменную из б.д. header("Content-type: image/gif"); echo $image; ?>





Регулярные выражения: PHP(POSIX) vs Perl.


PHP поддерживает регулярные выражения стандарта POSIX/eger*/ и PERL/preg*/-ориентированные (об их различии тут - php.spb.ru/regular_expression.html). Кто из них работает быстрее?

Хочу заранее предупредить любителей Перла, чтобы не радовались: хоть перловые реги и круче пхпышных, только ничто и никто не мешает использовать в PHP перловые реги! Наверно, потому их и встроили в PHP, что уж больно тормоза большие... :-)

Итак, простейший текст. Поиск простого выражения в тексте, который состоит из многократного повторения данной статьи (получается размер переменной $text в 3 Мб).

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

{eregi("МаС+иВ",$text);}

{preg_match("/МаС+иВ/im",$text);}

счетчик кол-во
вызовов
общее
вpемя
сpеднее
вpемя
% от min% от maxобщее
время
test N111.33391.3339107.8%100.0%
test N210.64170.641700.0%48.1%

{eregi("(ма[a-zа-я]{1,20})",$text);}

{preg_match("/(ма[a-zа-я]{1,20})/im",$text);}

счетчик кол-во
вызовов
общее
вpемя
сpеднее
вpемя
% от min% от maxобщее
время
test N110.45210.452176.9%100.0%
test N210.25560.255600.0%56.5%

Пример для другого выражения и 30-мегабайтного текста (все те же повторы статьи, что вы сейчас читаете):

{eregi("(ма[a-zа-я]{1,20})",$text);}

{preg_match("/(ма[a-zа-я]{1,20})/im",$text);}

счетчик кол-во
вызовов
общее
вpемя
сpеднее
вpемя
% от min% от maxобщее
время
test N111.34301.343060.6%100.0%
test N210.83650.836500.0%62.3%

Я еще писал штук пять разных выражений, но тенденция не меняется. Скорость может меняться, но Pelr обгоняет POSIX минимум на половину. Этого достаточно, чтобы похоронить функции регулярных выражений от PHP (POSIX). Для всех функций есть аналогичные Perl-ориентированные (все они встроены в PHP).


Далее один очень показательный пример на этой же статье (увеличение до 28Мб). Пример ищет в тексте e-mail. По свойству "жадности" регулярных выражений будет найден самый большой и наболее близкий к левому краю адрес.

Этот пример огорчит любителей перла. Приятно их огорчать :-)

{eregi("([a-z_-]+@([a-z][a-z-]*\.)+([a-z]{2}|com|mil|org|net|gov|edu|arpa|info|biz))",$text);}

{preg_match("/([a-z_-]+@([a-z][a-z-]*\.)+([a-z]{2}|com|mil|org|net|gov|edu|arpa|info|biz))/im",$text);}

счетчик кол-во
вызовов
общее
вpемя
сpеднее
вpемя
% от min% от maxобщее
время
test N1111.682811.6828680.3%100.0%
test N211.49731.497300.0%12.8% Из одного теста делать вывод сложно, но, видимо, чем сложнее регулярное выражение, тем больше POSIX отстает от Perl.

А теперь тот же пример, но только в статье (увеличение до 28Мб) нет НИ ОДНОГО символа "@" (я специально сделал копию статьи и стер эти символы):

{eregi("([a-z_-]+@([a-z][a-z-]*\.)+([a-z]{2}|com|mil|org|net|gov|edu|arpa|info|biz))",$text,$ok);echo $ok[1];}

{preg_match("/([a-z_-]+@([a-z][a-z-]*\.)+([a-z]{2}|com|mil|org|net|gov|edu|arpa|info|biz))/im",$text,$ok); echo $ok[1];}

счетчик кол-во
вызовов
общее
вpемя
сpеднее
вpемя
% от min% от maxобщее
время
test N110.58540.585400.0%10.2%
test N215.76715.7671885.2%100.0% Что мы видим?.. Ничто в этом мире не совершенно. Конечно, это очень не оптимизированное выражение для поиска email'ов, но всё же все те, кто кричал мне в форуме "ereg - отстой", на этом и похожих примерах могут отдыхать. Бывает же, что в тексте нет ни одной собачки :-)

Итак, вывод о скорости с примерами был дан выше. Вывод однозначный - надо использовать Perl-ориентированные регулярные выражения. В начеле главы я упоминал о кешировании откомпилированных копий регов. Если в программе одно и тоже выражение встречается неоднократно, производительность может отличаться не просто многократно, а в 10-100-1000 раз!



Селдующий пример вызывается 200 раз подряд над текстом в 250Кб:

{eregi("МаС+иВ",$text);}

{preg_match("/МаС+иВ/im",$text);}

счетчик кол-во
вызовов
общее
вpемя
сpеднее
вpемя
% от min% от maxобщее
время
test N1117.638417.638472381.4%100.0%
test N210.02430.024300.0%00.1% Что такое кеш - знают все. Видимо именно с кешем в PHP проблеммы... Кстати, ради примера, отключите в BIOSе вашего комптьютера кеш процессора и попробуйте загрузить Windows 2000... Не дождетесь! (Кажется, их называют L1 и L2 - два разных кеша для кода и данных первого и второго уровня, какой то из них можно отключить.)


В этой статье мы рассмотрели


В этой статье мы рассмотрели первые 7 из 21 наиболее общих ошибок PHP программиста. Как правило, они не нарушают работоспособности программ, но, тем не менее, их следует избегать:
Необоснованное применение функции printf(): Ее следует использовать только для вывода форматированных данных. Неправильное применение семантики языка: Многие программисты не имеют достаточно времени, чтобы разобраться во всех тонкостях языка, что впоследствии выражается в ошибочном коде. Плохо комментированный код: Всегда пишите комментарии! Перед каждой функцией указывайте, что делает данная функция, и какие аргументы она требует. Также комментируйте сложные участки кода и внесенные изменения. Слишком много временных переменных: Временные переменные хорошо использовать для предотвращения повторного вызова функций или последовательностей функций. Изобретаем велосипед – переписываем стандартную функцию: Сначала загляните в руководство по PHP – не описана ли там функция, которую вы собираетесь написать для, казалось бы, расширения набора стандартных функций PHP. Смешан PHP и L код: Попробуйте сделать код как можно более модульным. Потом вам (и другим тоже) можно будет сменить дизайн страницы без изменения кода PHP. Используются старые языковые конструкции и устаревшие функции: То, что вы можете сделать, не всегда следует делать. Загляните в документацию и литературу по PHP, как писать правильно. Отличные книги – “Разработка веб-приложений с использованием PHP (Web Application Development with PHP) и “Профессиональный программист PHP (Professional PHP). (Эх, где бы их еще найти! ;)) – прим. переводчика)

Session.auto_start


По умочанию равно 0, сессии автоматически не запускаются. Если равно 1, то session_start() писать в начале каждого скрипта не нужно.



Session.cookie_domain


Из той же области, что и предыдущая переменная. Для полного понимания ее работы читайте о куках. Такой документации на русском языке очень много.





Session.cookie_lifetime


Если равно 0 (по-умолчанию), то кука, хранящяя сессию, будет уничтожена на компьютера посетителя как только он закроет все окошки браузера. Если не нуль, то это задает число секунд для хранения куки.



Session.cookie_path


Если на вашем сайте используется несколько разных программ (у каждой свои сессии) и вы не хотите, чтобы сессии случайно пересекались, то установить нужный путь для кук. Если установить session.cookie_path /programm1, то все ваши программы, расположенные в каталоге pogramm1 или его подкатлогах, будут иметь одно общее пространство для кук, что равносильно одной и тожей сессии. Если посетитель после каталога /programm1 зайдет в /programm2 (для которого тоже заведены отдельные куки), то он будт идентифицирован новой программой по новому. Если у вас на сайте всего одна программа или много программ, но на разных названиях серверов, то куки/сессии никак не пересекутся.



Session_decode() и session_encode()


Раскодировать закодированную строку в сессию и получить закодированную строку сессии.



Session_destroy()


Уничтожить:

все данные, хранящиеся в сессии файл, отведенный для данных переменные в программе и идентификатор посетителя

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



Session.gc_maxlifetime


Количество секунд, через которое ПХП уничтожит у себя на диске устаревший файл сессии. По умолчанию - 1440. Это произойдет НЕ РАНЕЕ кол-ва секунд, указанного в переменной. Данное время определяет нижнюю гланицу (НЕ РАНЕЕ), когда файл становится кандидатом на удаление. Верхняя граница определяется следующей переменной. Время отсчитывается от последнеого обращения посетителя т.е. это время доступа к файлу, а не создания. У любого файла есть время создания. модификации (запись) и доступа (чтение).