| ||
Во первых надоевшие вопросы из форумов!
Только осторожнее. Создавайте
корректные - понятные названия...
Здесь гибкая система прав. Напишите faq@phpclub.net свои данные.
Любая помощь приветствуется...
Вспоминайте свои бывшие ошибки, проблемы
Напишите вопрос и варианты его решения..
С помощью тега <LINK> сам текст | сам линк и закрывающий тег линк
Имя линка
http://phpclasses.upperdesign.com/browse.html/package/222
Тут находится класс, для работы с /etc/passwd но я думаю, что переделать
его под свои нужды не составит никакого труда
Администрированием занимаются сами посетители данного ресурса. Для того чтобы
получить логин и пароль, достаточно быть полностью уверенным в своих силах и
написать письмо на phpclub@unet.ru с
заголовком - "Хочу участвовать в создании faq.phpclub.net".
В письме укажите
следующее:
Логин
Пароль
E-mail
Ф.И.О.
ну и чтобы
сомнений в квалификации не было, парочку ссылок на свои работы.
PHP это скриптовый server-side язык программирования, предназначенный в
основном для включения в html страницу и выполняемый сервером перед выдачей
страницы браузеру. Это не CGI, но вполне заменяет его! PHP очень похож на ASP
(существует даже конвертор asp2php), но приспособлен к unix-like системам и чаще
всего употребляется с web-сервером apache, хотя может работать и с MS IIS и в
принципе с любым другим веб-сервером. Кроме того, PHP3 является
объектно-ориентированным.
На мой взгляд, основное преимущество PHP -
простота, гибкость и скорость выполнения. Мне, например, понадобилось минут 15
для просмотра мануалов и примеров, для того, чтобы перевести весь контент моего
сайта на SQL (подробнее с елудющих ШАГ-ах) и написать php-скрипт для выдачи его
в html коде с шаблонным дизайном. Зачем так сложно? А вовсе и не сложно. Теперь,
чтобы выложить на сайт новую статью или просто новость, я всеголишь добавляю
новую запись на sql сервере с помощью MS Access или web-интерфейса sql,
написанного кстати тоже на php, а при запросе страницы пользователем
соответствующий php-скрипт выуживает из sql то, что ему надо и выдает уже
красиво оформленную, готовую страницу.
SQL. Вот это является еще одним
преимуществом PHP, такое впечатление, что он (PHP) просто рожден существовать в
связке apache+php+sql. Для свой работы я выбрал MySQL, который также существует
и под linux и под win9x/NT.
В качестве иллюстрации простоты php,
предлагаю пример, передающий список файлов в текущем каталоге.
<HTML><BODY>
Список файлов:
<?
$dir =
opendir(".");
while($file = readdir($dir))
echo "$file<BR>";
closedir($dir);
?>
</BODY></HTML>
Код,
помещенный в теги <? и ?> не передается браузеру, а выполняется
непосредственно на стороне сервера. А выдается то, что выводит команда echo. Я
думаю, что человек, мало-мальски знающий хотя бы один язык программирования,
поймет этот пример без проблем. Кажется, PHP похож на C? или Perl? или Basic? А
вот к стати тот же пример в ООП варианте:
<?
$dir = dir(".");
while($file = $dir->read())
echo "$file<BR>";
$dir->close();
?>
И ведь вы можете это писать в своем любимом
html редакторе! Лично я настолько полюбил этот язык, что пишу в нем и скрипты
для linux shell (хотя это уже из области XXX ;) и даже под dos/win. А запустить
скрипт из шела проще некуда: php3 -q <filename> получается отличный
интерпретатор.
А вот, для наглядности, еще пример для работы с MySQL:
<?
$conn=mysql_connect("127.0.0.1");
if
(mysql_select_db("db",$conn)) {
$res=mysql_query("select * from tabl",
$conn);
while(($data=mysql_fetch_row($res)))
echo("$data[0]
$data[1]\n");
} else
echo "Error!\n";
?>
Этот скрипт выводит
таблицу tabl из базы данных db на локальном MySQL сервере.
PHP.NET - основной сервер
разработчиков.
ZEND.COM - сервер
команды движка ZEND (кодеры скриптов, кеш)
На мой взгляд, это самый оптимальный редактор для создания/отладки скриптов.
Причём не важно каких скриптов, поскольку в этом редакторе можно настроить,
кажется, абсолютно всё. Очень удобная подсветка текста (Highlighting) с
поддержкой синтаксиса, просто великолепная система проектов, пользовательские
шаблоны, автозавершение (тоже полностью регулируемое), закачка по FTP,
поиск/замена во всех открытых файлах, огромный архив пользовательских файлов, с
синтаксисом для-всего-на-свете и другими полезностями...
Минуса только три -
неудобная подсветка CSS по умолчанию, невозможно выделять блоки, только линии
(но редактора с блоковым выделением вообще кажется нет :) и то что EditPlus -
shareware на 30 дней. Впрочем код в сети находится ~за 15 минут.
P.S. Чуть
не забыл - живёт тут
Comments
from dRam:
Полностью согласен с автором, за исключением одного ...
В
EditPlus есть возможность выделения блоков. Для этого выключаем word-wrap
(Ctrl+Shift+W), нажимаем Alt+C, выделяем блок текста (в произвольном месте),
Ctrl+C, выбираем куда вставить Ctrl+V ... :)
UltraEdit32 http://www.ultraedit.com|http://www.ultraedit.com</LINK>.
Прекрасный редактор для
программиста. Обладает множеством необходимых
функций в т.ч.:
практически любая синтаксическая подсветка (файлы можно
скачать на
сервере)
работа по ftp
поддержка проектов
работа в
режиме колонок/блоков
hex-редактирование
полностью настриваемая панель
инструментов, usertools, подсветка
макросы
и многое другое...
единственный недостаток - вставка html-тагов, по моему мнению,
организована не очень удачно.
Во первых строках своего письма хочу сообщить, что хотя инсталяция PHP - дело
совсем не хитрое и по крайней мере линуксоиды, отличающиеся умом и
сообразительностью ;-) , а так же уменем вникать в тексты документации на любом
языке, с этим делом справляются на р-р-р-р-аз, у виндозистов зачастую возникают
странные, на мой взгляд, вопросы. В таком случае целесообразно всетаки
рассмотреть инсталяцию PHP, но только под windos. Сразу предупрежу, что способов
работы с php существует несколько и я не буду здесь описывать каждый из них, а
лишь один и самый простой, на мой взгляд. Также учтите и то, что этот способ не
является безопасным (всмысле вашего сервера, читайте security.shtml в мануале от
PHP), да и о какой безопасности под виндами может идти речь. Хотя линчо у меня
на моей WindowsNT стоят Apache, MySQL и PHP - они естественно используются лишь
для отладки скриптов, перед выкладыванием их на сервер и эта комбинация не
является полноценным вебсервером, поэтому к неу нет доступа извне. Зато очень
даже здорово отлаживать скрипты и дизайн, таким образом, всем рекомендую.
Начнем с того, что вам не стоит скачивать и компилировать PHP из
исходного кода, это лишнее. Возьмите готовый дистрибутив (у меня он назывался
php-3.0.11-win32.zip) и просто скопируйте все файлы туда, где вы хотите
содержать php (лично у меня это c:/php3/). Пол дела сделанно! Кстати, кроме
самого дестрибутива, вам понадобится еще и документация, валяющаяся на том же
сервере ( список, html-вариант).
Идем дальше. Теперь в первую очередь
вам необходимо отредактировать файл php3.ini (оригинал php3.ini-dist). Измените
в нем праметр extension_dir=<путь где лежит ваш PHP3 со всеми модулями> (у
меня, как говорилось это c:/ php3/), а также уберите коментарии со строк
extension= с теми модулями, которые вам будут необходимы (если вы не просекаете
и смысл, значит вам они не нужны). И все! Теперь поместите этот файл (php3.ini)
в корневой каталог вашей windows (c:\windows обычно). Собственно сам php3 -
готов. Что-бы проверить его работу - создайте файл со следующим содержимым:
<?
echo "Список файлов\n";
$dir = dir(".");
while($file =
$dir->read())
echo "$file\n";
$dir->close();
?>
и
запустите его так <путь к вашему php>/php.exe -q <имя файла>. Для
особо талантливых обьясняю подробнее. Если вы поместили все файлы из
дистрибутива php в каталог c:/php3/, а созданный вами файл с вышеописанным
скриптом называется test.php то запустить его вам нужно будет так:
c:/php3/php.exe -q test.php
Этот скрипт должен вывести список файлов
в текущем каталоге.
Следующий шаг - конфигурирование вебсервера для
работы с PHP. Если вы используете IIS - ваши проблемы ;) (используйте файл
php_iis_reg.inf в поставке PHP3), если вы используете apache, то сейчас я вам
помогу.
Вообще идеология обработки php-сценариев сервером очень проста.
Есть такое понятие как mime тип файла, который определяется по расширению,
гляньте в файл mime.types и вы сами, надеюсь, все поймете. Файл имеет простой
формат: <тип файла> <расширение файла>. Вот мы и вставим в него
следующие три строчки:
application/x-httpd-php3 php
application/x-httpd-php3 php3
application/x-httpd-php3 phtml
Что мы
этим имеем ввиду? Что файлы с расширением php, php3 и phtml являются приложением
(application) типа x-httpd-php3 (а можете и сами название этого типа придумать,
дальше поймете зачем это вообще нужно). Есть, к стати, и второй вариант
прописывания mime типов, напрямую в httpd.conf вот так:
AddType
application/x-httpd-php3 .php
AddType application/x-httpd-php3 .php3
AddType application/x-httpd-php3 .phtml
После того. Как мы покончили
с определнием типов (и все знают этих типов). Нам осталось добавить в httpd.conf
всего одну строчку для запуска этих сценариев. Вот эту: Action
application/x-httpd-php3 <путь и имя php транслятора> Которая означает,
что для файлов типа application/x-httpd-php3 запускать указанную вами прогу. у
меня под win эта строчка выглядит так:
Action application/x-httpd-php3
/cgi-bin/php.exe
То есть я положил сам php.exe в директорию прописанную как
/cgi-bin/ и не мучался (добавить три лишние строки) с прописыванием разрешения
на запуск из собствненой директории php.
Собственно вот и все.
Запускайте ваш вебсервер и пробуйте скрипты из архива с документацией от php или
описанные мной. Если у вас все таки что-то неработает - смотрите логи от
вебсервера.
Опишу в кратце еще раз все необходимые действия:
скопировать php дистрибутив в выранную вами директорию;
соответсвенное
конфигурирование php3.ini (добвление этой самой директории) и помещение его в
директорию windows;
добавление новых mime типов для распознавания
документов, содержащих сценарии php;
сообщение серверу что делать с
документами этих типов (запускать для них php.exe)
Эти строки не претендуют на правильность но у меня всё получилось именно
таким методом.
При установке я столкнулся с неожиданными трудностями.
Первая состояла в том, что MySQL напрочь отказывался конфигурится с параметрами
или без таковых говоря при этом что checking size of char..0 и то, что наверно у
меня отсутсвует libm.a . Я проверил все пути (библиотека оказалась в /usr/lib
так что всё должно было быть ок!), проверил наличие zlib, gtar (с обычным
сановским tar скорее всего будет проблема), сменил cc на gcc-2.95.3. Проблема
всё равно осталась. После чего заглянув в config.log я нашёл место где
сваливалось configure. Вот оно : configure:6540: unterminated `#if' conditional
configure: failed program was:
line 6535 "configure"
#include
"confdefs.h"
#include <stdio.h>
main()
{
FILE
*f=fopen("conftestval", "w");
if (!f) exit(1);
fprintf(f, "%d\n",
sizeof(char));
exit(0);
}.
Cудя по всему это баг в mySQL но его
можно обойти (вероятно это не совсем правильно но тем не менее после этого я
смог запустить СУБД. Просто создаёте файл conftestval после чего записать туда
1.
Далее
После запуска gmake all при линковке libtool солярка просто
свалилась в core. Использование стандартного Sun'вского make решило все траблы.
Начнем с того, что я и сейчас не знаю, имеет ли данная конфигурация
практическую ценность. Очень может быть, что моя проблема являлась частной.
Короче - мне надо было установить PHP на Пентиум 100 с Windows 95 и малым
размером жесткого диска - ок. 500 МБайт. Пользователь такого компьютера
просто вынужден экономить каждый мегабайт. Кроме того, компьютер не был
подключен к Интернету либо к локальной сети, поэтому весь софт для него
приходилось грузить на флоппи.
Известный мне легкий вариант - установка
сервера ОМНИ - не сработал. Новый
ОМНИ создан уже для Windows 98/МЕ/2000.
Совершенствовать Windows 95 у меня
явно не хватало квалификации.
Инсталляционник Apache великоват, вдобавок,
судя по описапниям, тоже имеются
проблемы с Windows 95.
В одном из немецких форумов мне попалась ссылка на
сервер BadBlue -
www.badblue.com. Сервер оказался вполне компактным
(инсталляционник ок. 600
кБайт) и предельно легким в установке. Собственно
говоря, существуют две
версии сервера - для Windows 95 и для более высоких
версий. Для
установки РНР следовало:
- установить РНР в выбранную
директорию;
- скопировать файл php.ini-dist в директорию Windows и
переименовать в
php.ini ;
- при отключенном сервере отредактировать файл
EXT.INI (обычно находящийся
в c:\program files\badblue\pe) путем добавления
строчек:
[SERVICES]
extension1=php,c:\php\php.exe
(конечно, путь к
РНР должен быть указан правильно).
Недостаток, на мой взгляд, заключается в
расположении файла конфигурации
EXT.INI в одной директории с собственно
программными файлами РНР
(http://127.0.0.1/ -
c:\program files\badblue\pe). В эту директорию для
проверки пишите тестовый
файл .
В настоящее время у меня в данной конфигурации стоит РНР3. Попытка
"привязать" РНР4 из комплекта ОМНИ провалилась. Однако, поскольку цель
установки - дать возможность 13-летнему школьнику освоить в первом
приближении синтаксис языка и писать простые программы - достигнута, дальше
эксперименты пока не проводились.
Ниже я скопировала информацию с сайта
www.badblue.com. Я не претендую на
хорошее знание предмета, и вполне может
быть, что в оригинальной информации
Вы найдете нечто более ценное, чем я
могу не то что истолковать, а и
представить.
С уважением,
Елена
Геллер
How do I get started with PHP?
If you don't already have it,
download <down.htm> BadBlue. Download
<http://www.php.net/downloads.php> one of the PHP Win32
Binaries (either
the installer or the ZIP file). When installing or
unzipping the Win32
Binary version of PHP, note the folder to which PHP is
installed. Remember
to copy a PHP INI file (e.g., php.ini-dist) to the
Windows directory and
rename it php.ini. Stop the BadBlue service. Edit the
BadBlue EXT.INI file
(usually in the directory c:\program files\badblue\pe)
by adding the lines:
[SERVICES]
extension1=php,c:\php\php.exe
making
sure that the path to PHP.EXE is correct.
Start the BadBlue service. Test
BadBlue's PHP support by saving a test page
(see below for a sample) in the
directory where BadBlue is stored (e.g., as
c:\program
files\badblue\pe\hello.php). Type the name of your site with the
file name
(e.g., <http://127.0.0.1/hello.php>).
Which
built-in (CGI) variables does BadBlue support?
Built-in Variable
Description
ALL_HTTP All raw headers in HTTP format
ALL_RAW All raw
headers (IIS *)
CONTENT_LENGTH Header: Content-length
CONTENT_TYPE
Header: Content-type
DOCUMENT_ROOT Server path to HTML document root
GATEWAY_INTERFACE Current CGI version
HTTP_ACCEPT Header: Accept
HTTP_ACCEPT_ENCODING Header: Accept-encoding
HTTP_ACCEPT_LANGUAGE
Header: Accept-language
HTTP_COOKIE Header: Accept-cookie
HTTP_HOST
Header: Host
HTTP_REFERER Header: Referer
HTTP_USER_AGENT Header:
User-agent (browser)
PATH_INFO Requested URL
PATH_TRANSLATED Script
filename (if any)
QUERY_STRING Form GET query string
REMOTE_ADDR Remote
IP address
REMOTE_USER Basic authentication user name
REMOTE_PASSWORD
Basic authentication password
REQUEST_METHOD HTTP request method
REQUEST_URI Complete URL of requested page
PHP_AUTH_USER Basic
authentication user name (Apache *)
PHP_AUTH_PW Basic authentication
password (Apache *)
REQUEST_METHOD Header: request method
REQUEST_URI
Requested URL
SCRIPT_FILENAME Script filename (if any)
SCRIPT_NAME
Script filename (if any)
SCRIPT_URI Complete URL of requested page
SCRIPT_URL Requested URL
SERVER_PORT Server listen port
SERVER_PROTOCOL Server name and protocol
SERVER_SOFTWARE Server name and
version
* Certain variables are supported for compatibility with other
servers
ТерминСписокопределенийАдресаЦитатыГотовыйDownload
<http://www.mysql.net/downloads/index.html> and install
MySQL (Gamma). Open
a command window and start MySQL.
cd \mysql\bin
mysqld
Create a database using the root account.
mysqladmin -u root
create mydb
Create the following SQL which must be on separate lines, making
sure they
lines don't wrap, and save it to the MySQL bin directory, e.g.,
c:\mysql\bin\test.sql .
CREATE TABLE users (id tinyint(4) DEFAULT '0'
NOT NULL AUTO_INCREMENT,
first varchar(20), last varchar(20), address
varchar(255), company
varchar(50), PRIMARY KEY (id), UNIQUE id (id));
INSERT INTO users VALUES (1, 'Arnold','Fizbin','25 Wide St.','TinyCo');
INSERT INTO users VALUES (2, 'Fred', 'Fernakadan', '50 My Way', 'BigCo');
INSERT INTO users VALUES (3, 'Doris','Spam', '15 Top Rd', 'Zindi Corp');
If the lines wrap, make sure that each statement is on a new line.
Execute the create and inserts:
mysql -u root mydb <test.sql
Save
the following page to c:\program files\badblue\pe\mysql.php.
<html><body>
<?php
$db = mysql_connect("localhost",
"root");
mysql_select_db("mydb", $db);
$result = mysql_query("SELECT *
FROM users", $db);
printf("First Name: %s<br>\n",
mysql_result($result, 0, "first"));
printf("Last Name: %s<br>\n",
mysql_result($result, 0, "last"));
printf("Address: %s<br>\n",
mysql_result($result, 0, "address"));
printf("Company: %s<br>\n",
mysql_result($result, 0, "company"));
?>
</body></html>
Run the page in the browser to display the first record.
http://127.0.0.1/mysql.php
Проверено на:
- Win2000 Pro Rus + Service Pack 1
- PHP 4.0.5 (бралось
с сайта php.net)
1) Идем в "Панель управления" --> "Установка и
удаление программ" --> "Добавление и удаление компонентов Windows". Помечаем
чекбокс "IIS".
Вставляем диск с дистрибутивом Windows 2000.
Ждем пока
установится.
2) Распаковываем архив с дистрибутивом PHP в директорию, к
примеру, c:\php\
Копируем файл php.ini-dist в директорию "\WinNT\". Находим
его там, переименовываем в php.ini
Пока можно ничего не трогать в нем.
Копируем все файлы из директории c:\php\dlls\ в директорию
"\WinNT\system32\".
Копируем файлы c:\php\php4ts.dll и c:\php\php4ts.lib в
директорию "\WinNT\system32\"
3) Движемся в "Панель управления" -->
"Администрирование" и запускаем "Диспетчер служб Интернета".
Выбираем вторую
строку в левом окне. Там должно стоять имя вашей машины. Жмем правую кнопку
мыши. Выбираем "Свойства".
Около раздела "Основные свойства" жмем
"Изменить". Переходим на закладку "Фильры ISAPI".
Кнопка "Добавить" -->
Имя фильтра == PHP, Исполняемый файл == c:\php4\sapi\php4isapi.dll
Переходим
на закладку "Домашняя директория". Жмем баттон "Настройка". Жмем кнопку
"Добавить".
Исполняемый файл == c:\php4\sapi\php4isapi.dll ; Расширение ==
.php
Должно быть отмечено "Все команды" и "Обработчик сценариев".
Жмем
Ok столько раз, сколько попросят. Закрываем "Internet Information Services".
4) Движемся в "Панель управления" --> "Администрирование" и запускаем
"Личный диспетчер Web".
Жмем "Дополнительно". Переходим на "Домашний
каталог". Щелкаем (клювом).
Каталог == c:\inetpub\wwwroot
Отмечаем
Чтение, Сценарии Жмем Ок.
Ставим галку "Задать документ, используемый по
умолчанию", пишем туда index.php
Переходим в "Главное окно", жмем
"остановить", потом "Запустить". Или, просто "Запустить".
5) Последний,
и самый главный пункт. Смотрим на результаты наших трудов. Делаем файл index.php
в каталоге c:\inetpub\wwwroot\
В файле пишем одну строку <? phpinfo();
?>
Открываем броузер, пишем в строке состояния: 127.0.0.1
Долго ждем
пока отработает такой простой скрипт. Убеждаемся что все работает (правда
медленно), теперь удаляем IIS, устанавливаем Apache.
Оригинал заметки
на: http://leosha.hoster.ru
Скачиваем PHP самый свежий, который найдем.
Искать стоит на http://php.net/downloads.php
Распаковываем архив в
любую директорию.
Берем файлы из этой директории: php4apache.dll и
php4ts.dll и копируем их в директорию $SERVER_ROOT/modules
$SERVER_ROOT -
это там, где лежит Apache.
Там есть директория modules.
Теперь, в
httpd.conf (это файл настроек Apache)
пишем след. строки:
LoadModule
php4_module modules/php4apache.dll
AddType application/x-httpd-php .php
.phtml
Берем файл php.ini-dist из директории, где установлен PHP и
копируем его в директорию, где установлен Windows (c:\windows\ , c:\WinNT\)
Переименовываем этот файл в php.ini
Если требуется - правим этот
php.ini. Для начала, можно ничего не делать.
Все. Запускаем Apache.
Проверяем работоспособность PHP.
PS. Стоит почитать статью по установке
PHP+Apache+MySQL. Найти можно, например, на http://dklab.ru
PHP поддерживает следующие типы данных:
integer (целочисленные)
floating-point numbers или double (числа с плавающей запятой)
string
(строки, текст)
array (массивы)
object (обьекты)
Преобразование
типов происходит следующим образом. Если переменной при равнивается строка
(текст в кавычках) то эта переменная становится строковой. Если-жы с ней
совершается одна из многих математических функций или она приравнивается
численой переменой, она становится численной, причем если приравниваетс яне
целому значению - то станет типом double. Пример:
$foo = "0"; // $foo
строка (ASCII 48)
$foo++; // $foo тоже строка "1" (ASCII 49)
$foo += 1;
// $foo теперь integer (2)
$foo = $foo + 1.3; // $foo теперь double (3.3)
$foo = 5 + "10 паросят"; // $foo теперь снова integer (15)
$foo = 5 +
"10 ящиков"; // $foo и по прежнему integer (15)
значение в скобках -
результирующее значение переменной
Преобразовывать типы можно чистА в сишном
стиле:
$foo = 10; // $foo это integer
$bar = (double) $foo; // $bar
это double
Разрешенный преобразования:
(int), (integer) - cast to
integer
(real), (double), (float) - cast to double
(string) - cast to
string
(array) - cast to array
(object) - cast to object
К стати,
определить тип переменной можно функциями gettype(), is_long(), is_double(),
is_string(), is_array() и is_object().
Вы можете использовать не только переменный но и константы с помощью функции
define(). Взгляните на следующий пример:
define("CONSTANT", "Hello
world."); echo CONSTANT;
обратите внимание на то, что перед именем константы
не пишется символа переменной $ и это правильно.
Ну и напоследок список
предопределенных констант.
__FILE__ Имя файла выполняемого скрипта.
__LINE__ Колличество линий, интерптетированный на данный момент в этом
скрипте.
PHP_VERSION Тут хранится версия PHP. Например: '3.0.8-dev'.
PHP_OS Имя операционной системы, на которой выполняется PHP-скрипт.
TRUE
Истина.
FALSE Ложь.
E_ERROR Описывает случившуюся ошибку, продолжение
работы после которой невозможно.
E_WARNING Описывает ошибку, после которой
продолжается выполнения скрипта.
E_PARSE Описывает синтаксическую ошибку,
рпи разоре интерпретатором текста скрипта.
E_NOTICE Просто какое-то
сообщения от интерпретатора. Возможно ошибка, а возможно и нет.
Во-первых. Все переменные начинаются с символа $
Во-вторых существуют
границы определения переменных. Например что-бы использовать глобальные
переменные в функциях, необходимо их сначала декларировать как глобальные, иначе
вы будете исопльзовать локальные переменные. Поясню на примере:
$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.
Скорее всего скоро вам понадобятся переменныес динамически (в ходе работы
скрипты) изменяемым наименованием. Поясню на пример, что я имею ввиду:
$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.
Что бы подставлять нужную тебе функцию к примеру...
Another important feature of variable scoping is the static variable. A
static variable exists only in a local function scope, but it does not lose its
value when program execution leaves this scope. Consider the following example:
Другим важным свойствм области видимости переменных является возможность
определения статических (static) переменных. Статические переменные можно
определять только внутри функций, но они не потеряют своего значения после
завершения функции. Рассмотрим пример:
function Test ()
{
$a =
0;
echo $a;
$a++;
}
This function is quite useless since
every time it is called it sets $a to 0 and prints "0". The $a++ which
increments the variable serves no purpose since as soon as the function exits
the $a variable disappears. To make a useful counting function which will not
lose track of the current count, the $a variable is declared static:
Эта
функция бесполезна как счетчик. При каждом вызове переменная $a будет
установлена в 0 и выведена на печать. $a++ увеличит переменную а на 1, но
значение переменной $a будет утеряно после выхода из функции. Надо объявить
переменную $a как статическую для того, чтобы она выполняла роль счетчика и ее
значение не терялось после завершения функции:
function Test()
{
static $a = 0;
echo $a;
$a++;
}
Now, every time the
Test() function is called it will print the value of $a and increment it.
Теперь при каждом вызове функции Test() - она будет выводить на печать
значение переменной $a и увеличивать его на 1.
Static variables also
provide one way to deal with recursive functions. A recursive function is one
which calls itself. Care must be taken when writing a recursive function because
it is possible to make it recurse indefinitely. You must make sure you have an
adequate way of terminating the recursion. The following simple function
recursively counts to 10, using the static variable $count to know when to stop:
Статические переменные ведут себя точно так же при рекурсивном вызове
функций. Функция называется рекурсивной, если она вызывает саму себя. Вы должны
быть очень аккуратны при написании рекурсивных функций, поскольку можно получить
бесконечную рекурсию при неправильном подходе. Выдолжны быть уверены в том, что
ваша рекурсия будет прервана в какой-либо момент. Следующий пример демонстрирует
рекурсивный счетчик до 10, используя статическую переменную $count для того,
чтобы прервать рекурсию.
function Test()
{
static $count = 0;
$count++;
echo $count;
if ($count < 10) {
Test ();
}
$count--;
}
Скрипты написанные на PHP можно запускать и при отсутствии Web-сервера. Чтобы
передать при вызове такому скрипту параметры, есть несколько путей:
1)
>php.exe file.php 10 20
file.php содежит:
<? echo "$argv[1] \n
$argv[2]"; ?>
Выведет
X-Powered-By: PHP 4.0.5
Content-type:
text\html
10
20
2) >php.exe -f file.php &a=10&b=20
file.php содежит:
<? echo "$a \n $b"; ?>
Выведет
10
20
АРИФМЕТИЧЕСКИЕ ОПЕРАЦИИ
А рифметических операция в PHP всего пять, вот
они:
$a + $b
$a - $b
$a * $b
$a / $b
$a % $b
Я думаю
здесь все ясно. Ну можеттолко поясню последнюю операцию, результат ее выполнения
остаток от деления $a на $b.
СТРОКОВЫЕ ОПЕРАЦИИ
Ха! А здесь и того
меньше! Чисто строковой операцией считается операция сложения двух строк. Причем
выглядит она довольно необычно, но практично:
$c = $a . $b;
То есть
символом этой операции является точка. А результатом ее выполнения будет
обыкновенная строка, состоящая из $a и $b
ОПЕРАЦИЯ ПРИСВАИВАНИЯ
Ну
тут вообще ничего сложного, она всегда одна, это знак '=' и естественно этот
знак означает, что переменной с лева от него будет присвоенное значение,
полученное в результате выполнения каких либо операций или переменной/константы
с правой стороны. Причем тут возомжно некоторый С++ -ные варианты, как-то:
$a = ($b = 4) + 5; // $a будет равна 9, а $b 4-м.
$a += 5; //
аналогично $a = $a + 5;
$b = "Привет ";
$b .= "всем!"; // аналогично
$b="Привет всем!"
ДВОИЧНЫЕ ОПЕРАЦИИ
Аа... и тут вообщем-то ничего
нового:
$a & $b Побитовое И (AND)
$a | $b Побитовое ИЛИ (OR)
~ $a Исключающее или (XOR)
$a << $b Сдвиг влево на $b битов
$a
>> $b Сдвиг вправо на $b битов
ЛОГИЧЕСКИЕ ОПЕРАЦИИ
Все тоже...
$a and $bИ (AND)
$a && $bТоже самое, что и предыдущее
$a
or $bИли (OR)
$a || $bТоже, что и предыдущее
$a xor $bИсключающее или
(XOR)
! $aИнверсия (NOT)
ОПЕРАЦИИ СРАВНЕНИЯ
Здесь будет что-нибудь
новое или нет? Даже комментировать эти операции не буду...
$a == $b
$a != $b
$a < $b
$a > $b
$a <= $b
$a >= $b
В
PHP существует также, как и в C++, тринарный оператор '?:'. Кто незнает -
обьясню на примере.
$res= (expr1) ? (expr2) : (expr3);
Результатом
этой операции будет значение (expr2), в том случае, если expr1==1 и значение
expr3 в противном случае. Где все эти expr1, expr2, expr3 - являются
переменными/константами или математиескими выражениями. Такая запись по сути
своей аналогична следующей:
if (expr1) $res=(expr2); else $res=(expr3);
но естественно более лаконична.
Мне кажется не стоит попусту лить воду и описывать тут и так всем известные
из других языков програмирования структуры управления. Вместо этого я приведу их
полный список и все методы их использования.
IF
Структура:
if (выражение)
блок_выполнения
Пример
использования:
if ($a > $b)
print "a больше, чем b";
if
($a > $b) {
print "a больше, чем b";
$b = $a;
}
ELSE
Пример использования:
if ($a > $b) {
print "a больше, чем b";
} else {
print "a не больше, чем b";
}
elseif
Интересный
оператор. Он применяется в случае, когда вам необходимо использовать IF сразу
после ELSE
Пример использования:
if ($a > $b) {
print "a
is bigger than b";
} elseif ($a == $b) {
print "a is equal to b";
}
else {
print "a is smaller than b";
}
if(): ... endif;
Тоже
довольно необычная структура. Смысл ее в том, что если условие, записанное в
круглых скобах оператора IF оказалось истинной, то будет выполняться весь код,
начиная от двоеточия ':' то команда ENDIF;
Пример использования:
<?php if ($a==5): ?>
A = 5
<?php endif; ?>
Или
вот еще с использованием вышеописанного оператора ELSEIF
if ($a == 5):
print "a equals 5";
print "...";
elseif ($a == 6):
print "a
equals 6";
print "!!!";
else:
print "a is neither 5 nor 6";
endif;
WHILE
Структура:
while (выражение): блок_выполнения
... endwhile;
И примерчик:
$i = 1;
while ($i <= 10) {
print $i++;
}
do.. while
Вообщем-тоничего необычного - цикл, как
цикл. Выполняется блок выполнения до тех пор, пока справедливо выражение.
Структура:
do блок_выполнения while (выражение);
FOR
Точно
такой-же цикл как и в C++. Структура:
for (выражение1; выражение2;
выражение3)
блок_выполнения
Хотя - нет. Есть в PHP еще одно дополнение.
Структура:
for (выражение1; выражение2; выражение3):
блок_выполнения; ...; endfor;
Обратите внимание, на двоеточие перед
блоком выполнения.
break
Старо как мир. Этот оператор позволяет
выскакивать из любого цикла (for, while, do.. while) до окончания его
выполнения. Пример:
$i = 0;
while ($i < 10) {
if ($arr[$i] ==
"stop") {
break;
}
$i++;
}
continue
Тоже ничего нового.
Этот оператор позволяет пропустить дальнейшее действия блока_выполнения любого
цикла и продолжить выполнение с нового круга. Пример:
while (выражение)
{
if (выражение2)
continue;
действие;
};
Такая програма
аналогична следующей, без использования continue:
while (выражение) {
if (!выражение2)
действие;
};
switch
Часто очень необходимый оператор выбора. Хотя все его и так знают, попробую
представить ясный пример. Допустим у вас есть следующий участок в программе:
if ($i == 0) {
print "i равно 0";
} else
if ($i == 1) {
print "i равно 1";
} else
if ($i == 2) {
print "i равно 2";
} else
print " ниодно условие не прошло"
Сэкономить время
выполнения данного участка, а так-же представить его более логичным способом и
поможет нам этот оператор. Следующий пример совершает действия, аналогичные
предыдущему, но в более красивой форме:
switch ($i) {
case 0:
print "i равно 0";
break;
case 1:
print "i равно 1";
break;
case 2:
print "i равно 2";
break;
default:
print " ниодно
условие не прошло"
}
в таком представлении есть и еще одно преимущество.
Если вы не поставите оператор break например перед case 1:, то в случае, когда
$1 будет равен нулю после вывода на экран сообщения об этом программа пойдет
дальше и выведет также сообщение о тов, что $I равна еще и 1 и только после,
встретив break; продолжит свое выполнение за пределами switch
require
Этот оператор действует примерно так-же как и #include в C++. Файл,
указанный в кавычках включается в скрипт и выполняется, но только однажды. В
файле, включаемом оператором require резонно хранить какие-то даные, необходимые
для многих скриптов и соответсвенно влкючать его в эти "многие" скрипты.
Структуа его такая:
require 'header.inc';
include
Структура:
include 'func.inc';
Этот оператор позволяет включать код,
содержащийся в указанном файле (func.inc в нашем случае) и выполнять его столько
раз, сколько программа встречает этот оператор. То есть. Например в файле
func.inc у нас хранится программа вывода на экран определенных параметров. Ну и
каждый раз, когда нам нужно будет выводить эти параметры мы будем вставлять в
текст нашей основной программы include 'func.inc', то есть это в принципе тоже
самое, как если-бы мы везьде в таких случаях вставили-бы текст, содеражийся в
файле func.inc
Обратите внимание. Разница между include и require
довольно существенная, поэтому поэкспереминтируйти с ними сами, если вы ее так и
не усмотрели.
После заполнения пользователем HTML формы PHP может получить доступ к этим
данным через переменные, имеющие такие-же название, что и поля в форме. Как
всегда продемонстрирую на примере:
<form action="foo.php3"
method="post">
Name: <input type="text" name="name">
<input
type="submit">
</form>
Значит после того, как пользователь
нажмет в форме кнопку submit в php-скрипт foo.php3 методом post передадутся
данные из формы, а обратиться, например к текстовому полю, из этого скрипта
можно будет через переменную $name. Кроме того, можно использовать и массивы в
качестве названий полей.
<form action="array.php" method="post">
Name: <input type="text" name="personal[name]">
Email: <input
type="text" name="personal[email]">
Beer:
<select multiple
name="beer[]">
<option value="warthog">Warthog
<option
value="guinness">Guinness
</select>
<input type="submit">
</form>
В результате это скрипт (array.php) может вывести
полученные результаты так:
echo "Имя: ".$personal["name"];
echo
"Email: ".$personal["email"];
for ($i=0;$i<sizeof($beer);$i++)
echo
$beer[$i]."<br>";
Кроме этого, как известно в форме в качестве
submit-кнопки можно применять картику <input type=image src="image.gif"
name="sub">. В таком случаем скрипту возвращаются еще две дополнительных
переменных, содержащих координаты точки, на которой кликнули мышкой. Это sub_x и
sub_y.
----
Дополнено DVA
----
Если включена в настройках опция
track_vars, то в зависимости от способа передачи у вас появится ассоциативный
массив с именем $HTTP_POST_VARS, (Для POST) или $HTTP_GET_VARS (Для GET),
который будет содержать все переменные переданные из формы. Например скрипт,
покаывающий, что именно нам передаёт форма, может выглядеть так:
<?
function show($value, $name)
{
echo "Переданна переменная
<b>$name</b> = $value<br>";
}
array_walk($HTTP_POST_VARS,'show');
// Или
array_walk($HTTP_GET_VARS,'show');
?>
В скрипт передаются все именованные элементы форм. Таким образом, если у
кнопки указан атрибут name="button_name", то будет установлена соотвествующая
переменная в запросе, а ее значение будет равно атрибуту value. что характерно,
это текст на кнопке.
Если у кнопки опущен элемент name, то
соответствующей переменной не будет установлено в запросе.
Обратите
внимание что для того, чтобы эти переменные автоматически создавались,
необходимо выполнение следующих параметров кофигурации:
register_globals
boolean
По умолчанию включено.
Если выключено, то переменные не
создаются.
gpc_order string
По умолчанию GPC.
Определяет
нужно ли принимать GET, POST и COOKIE.
Если оставить, например, GC то данные
переданные по POST не будут определены.
track_vars boolean
По
умолчанию включено.
Определяет создавать ли глобальные массивы
$HTTP_ENV_VARS, $HTTP_GET_VARS, $HTTP_POST_VARS, $HTTP_COOKIE_VARS, и
$HTTP_SERVER_VARS
Уровень подготовки читателя: Ламер со стажем.
Решение:
Для примера создадим таблицу "country" для хранения
названий стран и соответствующего им кода ISO (полагается что БД "testbase" уже
создана):
CREATE TABLE country (
country_id smallint(6) NOT NULL
auto_increment,
country_iso_code char(2) NOT NULL,
country_name
varchar(60) NOT NULL,
PRIMARY KEY (country_id),
UNIQUE country_id
(country_id, country_iso_code, country_name),
KEY country_id_2 (country_id,
country_iso_code, country_name)
);
Теперь, занесем в нее
немножко данных:
<?php
$country = array(); /* Ассоциативный
массив где: индекс=код ISO, значение=страна */
$country[ 'AF' ] =
'Afghanistan';
$country[ 'AL' ] = 'Albania';
$country[ 'DZ' ] =
'Algeria';
$country[ 'AD' ] = 'Andorra';
$country[ 'AO' ] = 'Angola';
$country[ 'AQ' ] = 'Antarctica';
$country[ 'AR' ] = 'Argentina';
$country[ 'AM' ] = 'Armenia';
$country[ 'AU' ] = 'Australia';
$country[ 'AT' ] = 'Austria';
$country[ 'AZ' ] = 'Azerbaijan';
$country[ 'BS' ] = 'Bahamas';
$country[ 'BH' ] = 'Bahrain';
$country[ 'BD' ] = 'Bangladesh';
$country[ 'BY' ] = 'Belarus';
$country[ 'BE' ] = 'Belgium';
$country[ 'BJ' ] = 'Benin';
$country[
'BM' ] = 'Bermuda';
$country[ 'BT' ] = 'Bhutan';
$country[ 'BO' ] =
'Bolivia';
$country[ 'BA' ] = 'Bosnia-Herzegovinia';
$country[ 'BW' ] =
'Botswana';
$country[ 'BR' ] = 'Brazil';
$country[ 'BN' ] = 'Brunei
Darussalam';
$country[ 'BG' ] = 'Bulgaria';
$country[ 'BF' ] = 'Burkina
Faso';
$country[ 'BI' ] = 'Burundi';
$country[ 'KH' ] = 'Cambodia';
$country[ 'CM' ] = 'Cameroon';
$country[ 'CA' ] = 'Canada';
$country[ 'CV' ] = 'Cape Verde';
$country[ 'CF' ] = 'Central African
Republic';
$country[ 'TD' ] = 'Chad';
$country[ 'CL' ] = 'Chile';
$country[ 'CN' ] = 'China';
$country[ 'CO' ] = 'Colombia';
$country[
'KM' ] = 'Comoros';
$country[ 'CG' ] = 'Congo';
$country[ 'CR' ] =
'Costa Rica';
$country[ 'HR' ] = 'Croatia';
$country[ 'CU' ] = 'Cuba';
$country[ 'CY' ] = 'Cyprus';
$country[ 'CZ' ] = 'Czech Republic';
$country[ 'DK' ] = 'Denmark';
$country[ 'DJ' ] = 'Djibouti';
$country[ 'DO' ] = 'Dominikanische Republik';
$country[ 'EC' ] =
'Ecuador';
$country[ 'EG' ] = 'Egypt';
$country[ 'SV' ] = 'El Salvador';
$country[ 'GQ' ] = 'Equatorial Guinea';
$country[ 'EE' ] = 'Estonia';
$country[ 'ET' ] = 'Ethiopia';
$country[ 'FЦ' ] = 'Faroe Islands';
$country[ 'FI' ] = 'Finland';
$country[ 'FR' ] = 'France';
$country[
'GF' ] = 'French Guiana';
$country[ 'PF' ] = 'French Polynesia';
$country[ 'GA' ] = 'Gabon';
$country[ 'GM' ] = 'Gambia';
$country[
'GE' ] = 'Georgia';
$country[ 'DE' ] = 'Germany';
$country[ 'GH' ] =
'Ghana';
$country[ 'GI' ] = 'Gibraltar';
$country[ 'GR' ] = 'Greece';
$country[ 'GL' ] = 'Greenland';
$country[ 'GP' ] = 'Guadeloupe';
$country[ 'GT' ] = 'Guatemala';
$country[ 'GN' ] = 'Guinea';
$country[ 'GW' ] = 'Guinea-Bissau';
$country[ 'GY' ] = 'Guyana';
$country[ 'HT' ] = 'Haiti';
$country[ 'VA' ] = 'Holy See';
$country[
'HN' ] = 'Honduras';
$country[ 'HK' ] = 'Hong Kong';
$country[ 'HU' ] =
'Hungary';
$country[ 'IS' ] = 'Iceland';
$country[ 'IN' ] = 'India';
$country[ 'ID' ] = 'Indonesia';
$country[ 'IQ' ] = 'Irak';
$country[
'IR' ] = 'Iran (Islamic Republic of)';
$country[ 'IE' ] = 'Ireland';
$country[ 'IL' ] = 'Israel';
$country[ 'IT' ] = 'Italy';
$country[
'CI' ] = 'Ivory Coast';
$country[ 'JM' ] = 'Jamaica';
$country[ 'JP' ] =
'Japan';
$country[ 'JO' ] = 'Jordan';
$country[ 'KZ' ] = 'Kazakhstan';
$country[ 'KE' ] = 'Kenya';
$country[ 'KP' ] = 'Korea (Democratic
Peoples Republic of)';
$country[ 'KR' ] = 'Korea (Republic of)';
$country[ 'KW' ] = 'Kuwait';
$country[ 'LA' ] = 'Laos ';
$country[
'LV' ] = 'Latvia';
$country[ 'LB' ] = 'Lebanon';
$country[ 'LS' ] =
'Lesotho';
$country[ 'LR' ] = 'Liberia';
$country[ 'LI' ] =
'Liechtenstein';
$country[ 'LT' ] = 'Lithuania';
$country[ 'LU' ] =
'Luxembourg';
$country[ 'MO' ] = 'Macau';
$country[ 'MG' ] =
'Madagascar';
$country[ 'MW' ] = 'Malawi';
$country[ 'MY' ] =
'Malaysia';
$country[ 'MV' ] = 'Maldives';
$country[ 'ML' ] = 'Mali';
$country[ 'MT' ] = 'Malta';
$country[ 'MQ' ] = 'Martinique';
$country[ 'MR' ] = 'Mauritania';
$country[ 'MU' ] = 'Mauritius';
$country[ 'MX' ] = 'Mexiko';
$country[ 'MD' ] = 'Modavia';
$country[
'MC' ] = 'Monaco';
$country[ 'MN' ] = 'Mongolia';
$country[ 'MA' ] =
'Morocco';
$country[ 'MZ' ] = 'Mozambique';
$country[ 'NA' ] =
'Namibia';
$country[ 'NP' ] = 'Nepal';
$country[ 'NL' ] = 'Netherlands';
$country[ 'NC' ] = 'New Caledonia';
$country[ 'NZ' ] = 'New Zealand';
$country[ 'NI' ] = 'Nicaragua';
$country[ 'NE' ] = 'Niger';
$country[ 'NG' ] = 'Nigeria';
$country[ 'NO' ] = 'Norway';
$country[
'PK' ] = 'Pakistan';
$country[ 'PA' ] = 'Panama';
$country[ 'PG' ] =
'Papua New Guinea';
$country[ 'PY' ] = 'Paraguay';
$country[ 'PE' ] =
'Peru';
$country[ 'PH' ] = 'Philippines';
$country[ 'PL' ] = 'Poland';
$country[ 'PT' ] = 'Portugal';
$country[ 'PR' ] = 'Puerto Rico';
$country[ 'RO' ] = 'Romania';
$country[ 'RU' ] = 'Russian Federation';
$country[ 'RW' ] = 'Rwanda';
$country[ 'SM' ] = 'San Marino';
$country[ 'SA' ] = 'Saudi Arabia';
$country[ 'SN' ] = 'Senegal';
$country[ 'SC' ] = 'Seychelles';
$country[ 'SL' ] = 'Sierra Leone';
$country[ 'SG' ] = 'Singapore';
$country[ 'SK' ] = 'Slovakia';
$country[ 'SI' ] = 'Slovenia';
$country[ 'SB' ] = 'Solomon Islands';
$country[ 'SO' ] = 'Somalia';
$country[ 'ZA' ] = 'South Africa';
$country[ 'ES' ] = 'Spain';
$country[ 'LK' ] = 'Sri Lanka';
$country[ 'SD' ] = 'Sudan';
$country[ 'SR' ] = 'Suriname';
$country[
'SZ' ] = 'Swaziland';
$country[ 'SE' ] = 'Sweden';
$country[ 'CH' ] =
'Switzerland';
$country[ 'SY' ] = 'Syrian Arab Republic';
$country[ 'TW'
] = 'Taiwan';
$country[ 'TZ' ] = 'Tanzania';
$country[ 'TH' ] =
'Thailand';
$country[ 'MK' ] = 'The Former Yugoslav Republic of Macedonia';
$country[ 'TG' ] = 'Togo';
$country[ 'TT' ] = 'Trinidad and Tobago';
$country[ 'TN' ] = 'Tunisia';
$country[ 'TR' ] = 'Turkey';
$country[
'UG' ] = 'Uganda';
$country[ 'UA' ] = 'Ukraine';
$country[ 'AE' ] =
'United Arab Emirates';
$country[ 'GB' ] = 'United Kingdom';
$country[
'US' ] = 'United States';
$country[ 'UY' ] = 'Uruguay';
$country[ 'UZ' ]
= 'Uzbekistan';
$country[ 'VE' ] = 'Venezuela';
$country[ 'VN' ] =
'Vietnam';
$country[ 'YE' ] = 'Yemen';
$country[ 'YU' ] = 'Yugoslavia';
$country[ 'ZR' ] = 'Zaire';
$country[ 'ZM' ] = 'Zambia';
$country[
'ZW' ] = 'Zimbabwe';
$link = mysql_connect("localhost","","") or die
("Не могу соедениться с MySQL"); /* Не забудте изменить! */
mysql_select_db("testbase",$link) or die ("Не могу выбрать базу");
while(list($key,$name)=each($country)){ /* Пользователи PHP4 могуть
использовать foreach($country as $key => $name){...} */
if(!mysql_query("INSERT INTO country (country_iso_code, country_name)
VALUES ('$key', '$name')",$link))
{
echo "<pre>Ошибка ввода
строки $key :".mysql_error($link)."</pre>";
die;
}
}
echo "Everything is nishtyak!";
?>
Теперь, если все прошло без ошибок :), можно приступить к
главному. Для начала решим в каком виде мы хотели бы видеть дискриптор
<select>? Положим что вам быть не раз придется решать подобную задачу, да
и просто ради удобства выделим наш код в отдельную функцию, которая будет
находится в отдельном файле и подключаться по мере необходимости.
Назовем ее незатейливо - "select":
<!-- select.inc.php -->
<?php
function select($result, $value_index = 0, $text_index
= 1, $selected = 1, $param=array()){
/*
$result результат запроса
SQL
$value_index индекс в массиве для значения VALUE (необязательный)
$text_index индекс в массиве для текстового значения OPTION (необязательный)
$selected индекс в массиве для выбранного значения OPTION (необязательный)
$parametrs ассоциативный массив атрибутов дискриптора SELECT
(необязательный)
*/
echo "<SELECT";
if
(isset($param)){
while (list($param_name, $param_value) = each($param)){
/* Добавляем переданные через массив атрибуты (можно использовать foreach() см.
выше) */
if($param_value ==
"multiple"){ /* Здесь, по
необходимости, можно добавить обработку JS */
echo " $param_value";
continue;
}
echo " $param_name=\"$param_value\"";
}
}
echo ">";
while ($row = mysql_fetch_row($result)){
if ($row[$value_index] == $selected){
echo "<OPTION
VALUE=$row[$value_index] SELECTED>$row[$text_index]</OPTION>\n";
}
echo "<OPTION
VALUE=$row[$value_index]>$row[$text_index]</OPTION>\n";
}
echo "</SELECT>";
}
Теперь оттестируем нашу
функцию:
<!-- test_select.php -->
<?php
include("select.inc.php"); //Убедитесь, что оба файла находятся в одном
каталоге
$host =
"localhost"; /* Не забудте
изменить! */
$user =
"";
$pass =
"";
$db = "testbase";
if (!$link = mysql_connect ($host, $user, $pass)){
echo "Не
могу соедениться с MySQL";
die;
}
If (!mysql_select_db($db,
$link)){
echo "Не могу выбрать базу $db. Ошибка: ".mysql_error($link);
die;
}
if (!$result = mysql_query("SELECT * FROM country")){
echo "Ошибка запроса ".mysql_error($link);
die;
}
/*
Теперь в переменной $result находится результат выборки из таблицы "country".
Важно заметить, что в результате могут быть задействованы множество полей
таблицы (в нашем случае 3), так как мы полагаем, что запрос используется не
только для генерации нашей менюшки, но еще для каких-то целей; а нам для
<select>'а нужно только 2, поэтому в качестве параметров фунции могут
передаваться также и номера полей. Помните, что после SQL-запроса вида "SELECT *
FROM table_name", в результате, поля будут располагаться так, как они были
расположены в таблице при ее создании (В нашем случае порядок такой: country_id
country_iso_code country_name) Так что перед тем как передавать эти параметры,
убедитесь в том, что вы представляете себе структуру вашей таблицы, либо не
используйте (*) а перечисляйте поля ручками :) Можно,также использовать
функции mysql_list_fields() , mysql_num_fields(),, mysql_field_name(). По
умолчанию установлены данные из 1-го поля для значения VALUE, из второго - для
текстового значения OPTION. */
echo "<FORM>";
$discriptor_param = array (name => "select_1",
size => "5",
multiple); /* Передаем атрибуты,
для подробной информации читайте спецификацию HTML */
$value_index=1; //т.е. для значения VALUE выводить строки из поля
country_iso_code
$text_index=2; //т.е. для текстового значения OPTION
выводит строки из поля country_name
$selected="RU"; //установить выбранным
опцию где VALUE="RU"
select($result, $value_index, $text_index,
$selected, $discriptor_param);
echo "\n<BR>\n<BR>\n";
/* И еще разок: */
$discriptor_param = array (name =>
"select_2");
$value_index=0; /* т.е. для
значения VALUE выводить строки из поля country_id */
$text_index=2; /* т.е. для
текстового значения OPTION выводит строки из поля country_name */
$selected="136"; /* установить выбранным опцию где
VALUE="136" */
mysql_data_seek($result,0); /*
сбросим внутренний указатель результата */
select($result, $value_index,
$text_index, $selected, $discriptor_param);
echo "</FORM>";
mysql_free_result($result); //на любителя
mysql_close($link); //Также
на любителя :)
?>
Можно также, доработать функцию и добавить
в нее обработку переданного в качестве параметра JS. Функция не совсем :)
оптимальна, но главное, что она показывает как решать подобные задачи. Удачи!
<-- рифма :)
<?
function languagelist($lang)
{
//I am use phplib for acces
to mysql-databases ....
$languagedb = new db;
$query="use
".$languagedb->Database;
$languagedb->query($query);
if($languagedb->query_id()==0)
{
echo("Database not using");
halt;
};
$query="select * from lang";
$languagedb->query($query);
$count=$languagedb->num_rows();
if($count>0)
{
for($i=0;$i<$count;$i++)
{
$languagedb->next_record();
echo("<option
value='".$languagedb->f('id')."'");
if($lang==$languagedb->f('id'))echo(" selected");
echo(">".$languagedb->f('name')."</option>");
};
};
};
?>
<select name="lang" style={width=108pt}>
<option value="">Please select one</option>
<?
@languagelist($lang);
?>
</select>
У Вас есть форма такого типа:
<form action="page.php"
method="POST">
...
<input type="checkbox" name="checkme"
value="yo">
...
<input type="submit" value="ok">
</form>
После нажатия на "ok" данные передаются скрипту
page.php. Здесь выполняем проверку на предмет, был ли отмечен чекбокс:
<?
...
if (isset($checkme) &&
strlen($checkme)>0) // здесь "checkme" - имя чекбокса
{
... //
если чекбокс отмечен, выполняем какие-то действия
}
...
?>
Решение от Roman Korobeinikov <shainsky@mail.ru>
Есть еще
один способ сделать это, как мне кажется, более простой:
в форме _перед_
тегом <input type='checkbox'> поместить тег
<input
type='hidden'> с тем же самым значением параметра 'name':
<form
...>
...
<input type="hidden" name="checkme" value="0">
<input type="checkbox" name="checkme" value="1">
...
</form>
Теперь если checkbox взведен, в переменной $checkme
передастся "1",
в противном случае "0".
Немного теории. Это нужно, для понимания что и как работает.
- вы в
броузере указываете файл для загрузки на сервер;
- броузер передает
выбранный файл на сервер;
- PHP-интерпретатор на сервере записывает
полученный файл во временную директорию. Причем, имя, под которым записывается
файл, может быть абсолютно случайным. Это только под Windows PHP пишет файл с
именами подобными <b>PHP2<b>.
Нам, в принципе, вовсе не
обязательно знать под каким именно именем загруженный файл хранится во временной
директории. Почему не надо знать? Потому что, вполне достаточно того, что PHP
"знает". И, в любом случае, после завершения работы скрипта, этот файл
удаляется.
- Вы говорите PHP, что загруженный файл надо скопировать из
временной директории туда, куда хотите.
На этом, сам процесс "аплоада"
можно считать завершенным.
Что вы потом сделаете с этим файлом, вопрос
другой.
И еще: все трудности под Win32 связанные с "непонимаем" системой
конструкции вида "\\PHP2" (кто сталкивался, поймет) кроются в файле php.ini
(php3.ini) Лично у меня, это выглядит так (получено опытным путем):
upload_tmp_dir = "f:/tmp/" - php3.ini
upload_tmp_dir = "f:\tmp" -
php.ini
С такими настройками, никаких проблем я не замечал. Попробуйте.
Теперь про ограничение размера загружаемого файла. Конечно, и в php.ini
есть параметр upload_max_filesize, можно ограничить и размер и тип указанием
соответствующих параметров в теге FORM, но, в любом из этих случаев мы получим
ошибку, которую не сможем обработать. Что не здорово. Поэтому, удобней
ограничивать размер в самом скрипте.
НО: РАЗМЕР файла невозможно узнать до
ПОЛНОЙ загрузки файла на сервер. Никаким способом.
Также, при uploade,
до ЗАВЕРШЕНИЯ загрузки, файл хранится в памяти, потом пишется во временную
директорию, и, еще раз напомню, сразу удаляется из temp по завершению работы
скрипта. Вообщем, с помощью PHP не получится сделать индикатор загрузки файлов.
Итак, сначала у нас файл upload.html примерно такого вида.
<html><head><title>Upload</title></head><body>
<form action=upload.php method=post enctype=multipart/form-data>
<!-- обратите внимание на enctype!!! -->
<input type=file
name=file1>
<br>
<input type=file name=file2>
<br>
<input type=submit name=upload value="Загрузить">
</form></body></html>
Теперь, сам скрипт.
<?
$max_size = 65535;
// максим. размер в БАЙТАХ
$type_1 = "application/x-zip-compressed";
$type_2 = "text/plain";
//
типы файлов, которые мы хотим принимать
$path = "/home/test/frob";
// каталог, куда сохраняем файлы
if ( ($file1 == "none") &&
($file2 == "none") ) {
echo "Не выбрано ни одного файла!"; exit; }
if ($file1_size > $max_size)
{ echo "Неверный размер! Файл
$file1_name НЕ загружен."; }
elseif ( ($file1_type != $type_1) AND
($file1_type != $type_2) )
{ echo "Неверный тип! Файл $file1_name
($file1_type) НЕ загружен."; }
else {
copy ("$file1",
"$path/$file1_name");
echo "
Вы загрузили файл $file1_name. Этот файл
сохранен в каталоге $path<br>\n
Размер файла - $file1_size
байт<br>\n
Тип файла -
$file1_type<br>\n<br><br><br>
";
}
if
($file2_size > $max_size)
{
echo "Неверный размер! Файл
$file2_name НЕ загружен.";
}
elseif ( ($file2_type != $type_1) AND
($file2_type != $type_2) )
{
echo "Неверный тип! Файл $file2_name НЕ
загружен.";
}
else {
copy ("$file2", "$path/$file2_name");
echo "
Вы загрузили файл $file2_name. Этот файл сохранен в каталоге
$path<br>\n
Размер файла - $file2_size байт<br>\n
Тип файла
- $file2_type<br>\n
";
}
?>
Итак, если Вы не
удосужились открыть Manual, рассказываю (хотя, FAQ то он, конечно, FAQ, но
чтение manual'ов никто не отменял):
В форме есть поле с type=file и именем
file1.
При аплоаде, у нас возникают переменные:
$file1 - имя файла
во временной директории;
$file1_name - исходное имя файла;
$file1_type -
MIME тип файла;
$file1_size - размер файла;
Так, осталось
рассмотреть случай, когда PHP работает в safe-mode. Т.е., если вы сделали все
как написано, а вам говорят
Safe-mode restriction is effect... Или, про то,
что невозможно выполнить команду copy() - попробуйте copy() заменить на
move_uploaded_file().
Но, невозможность выполнить copy() может крыться и
просто в том, что у PHP-процесса не хватает прав на запись в указанную вами
директорию. В этом случае, вам проще всего спросить у своего администратора,
какие права должны быть на директорию, в которую хочется записывать файлы.
Фу-у-у-у...
Последний штрих: на самом деле, если вам следует
загрузить несколько файлов, не стоит пользоваться приведенной конструкцией.
Лучше, обозвать поля для ввода файлов именем, например, file[], а потом
разбирать полученный массив file[] уже.
Итак, вы сделали форму для аплоада файлов, вы сделали скрипт, который
принимает загруженные файлы, но теперь возникла следующая проблема:
Картинки
загружаются, но не показываеются. Бинарные файлы загружаются, но не запускаются
(или, не распаковываются, если это архив).
Основная причина данной проблемы
- Russian Apache.
Именно он (т.е. web-server) перекодирует все что ни
попадя. Соответственно, после такой перекодировки, в файлах оказываются
замещенными (перекодированными) некоторые символы. Что избежать подобного есть
несколько решений:
1) В директории, где лежит скрипт для Upload'a делаем
файл .htaccess в котором пишем:
CharsetDisable On
2) В файл
httpd.conf дописать строки:
<Location />
CharsetRecodeMultipartForms Off
</Location>
Обычно, этого
вполне достаточно для решения проблемы.
Оригинал - http://php.spb.ru/php/upload.html
в PHP4 работа с upload'ами стала несколько иной.
теперь вся информация о
залитых файлах хранится в массиве $HTTP_POST_FILES
для примера:
если
у нас в форме было так: <input type="file" name="screenshot">
то
информацию о файле надо смотреть здесь:
$HTTP_POST_FILES['screenshot']['name']
Оригинальное имя файла. Например
"screen1.jpg"
$HTTP_POST_FILES['screenshot']['type']
mime type
файла. Например "image/gif".
$HTTP_POST_FILES['screenshot']['size']
Размер файла в байтах
$HTTP_POST_FILES['screenshot']['tmp_name']
Временное имя файла на сервере.
В остальном смотри 13.6
В PHP реалиован также простой способ работы с куками. С помоью функции
SetCookie() можно их устанавливать, получать значения, как и в случае с формами
- по имени переменной. В случае, если вы ожидаете получить несколько значений от
куки имеет резон исопльзовать в качестве имени переменной - массив. Как в
следующем примере.
SetCookie ("MyCookie[]", "Testing", time()+3600);
Существует только одно небольшое ограничение. Так-как куки - это часть HTTP
заголовка их следует посылать самыми первыми. То есть грубо говоря, ваш скрипт
должен начинаться с установки куки, а потом уже заниматься выводом html кода.
Еще один пример, уже полноценного счетчика:
$Count++;
SetCookie
("Count", $Count, time()+3600);
SetCookie ("Cart[$Count]", $item,
time()+3600);
Функции, это, блин, очень полезная штука. Ща расскажу :)
Вот, допустим,
тебе необходимо повторить одну и ту же операцию несколько раз, но с разными
параметрами.
Как пример, возьмем вывод даты в селекте:
Function
PrintMyDate ($from,$to) {
for ($i=$from;$i<=$to;$i++) {
$options.="<option value='$i'>$i\n";
}
return $options;
}
Теперь напечатаем 3 селекта с датами:
<select name=date1>
<?=PrintMyDate(1,31)?>
</select>
<select
name=date2>
<?=PrintMyDate(1,12)?>
</select>
<select name=date3>
<?=PrintMyDate(2001,2002)?>
</select>
Вот. Быстро и понятно. А если этот делать "ручками" в
html-e, то время уйдет не 3 минуты а все 30.
Все переменные создаваемые внутри функции являются локальными,
т.е. они
существуют только пока выполняется функция и при выходе из нее они будут
уничтожены.
Чтобы получить доступ г глобальным переменным их надо
объявить с модификатором global, т.е.
global $<var1_name>[,
$<var2_name> ... ];
причем если внутри функции делаете include то
все переменные из этого include'а тоже надо объявить как global.
существует 'совсем' глобальный массив $GLOBALS - глобальные переменные,
его можно не объявлять global.
Переменные можно объявлять с
модификатором static - это обозначает, что значение переменной будет сохранено
между повторными вызовами функции.
надо сделать несколько функций для того, чтобы работать с массивами в php3
так же удобно как в php4
// возвращает все ключи массива
function
array_keys($all) {
for (reset($all); list($k, $v) =
each($all);) {
$keys[] = $k;
}
return $keys;
}
// возвращает все
значения массива
function array_values($all) {
for (reset($all); list($k, $v) = each($all);) {
$vals[] = $v;
}
return $vals;
}
// сливает два массива
в один
function array_merge($to, $from) {
for
(reset($from); list($k, $v) = each($from);) {
$to[$k] = $v;
}
return $to;
}
// возвращает
массив, состоящий из N элементов исходного массива
// начиная с M-того
function array_slice($all, $offset, $limit=0) {
$ptr = reset($all);
for ($i=0; $i<$offset;
$i++) $ptr = next($all);
if (!$limit) $limit = sizeof($all)-$offset;
else $limit = min(sizeof($all)-$offset, $limit);
for ($i=0;
$i<$limit; $i++) {
$ret[] = $ptr;
$ptr = next($all);
}
return $ret;
}
если понадобится что-то еще пишите
Один из вариантов решения заключается в работе с файлом формата DBF.
Его
понимает РНР и с ним работает Excel.
Для создания dbf файла, сохраняем
выделенные ячейки как файл dBase.
<TABLE>
<?
$db=
"excelfile.dbf"; // файл Excel, сохраненный как dBase
$open_db=
dbase_open($db, 0); // открывает базу (read-only)
$fields=
dbase_numfields($open_db); // Количество полей в таблице
$records=
dbase_numrecords($open_db); // Количество строк в таблице
for ($i=1;
$i<= $records; $i++) // Цикл "строки"
{
echo "<TR>";
$row=
dbase_get_record($open_db, $i); // получает строку
for($a=0; $a< $fields;
$a++) // Цикл "столбцы"
{
echo "<TD> $row[$a] </TD>";
}
echo "</TR>";
}
?>
</TABLE>
Если
необходимо, можно занести таблицу в базу данных.
Для удобства, желательно
перекодировать все символы функцией
convert_cyr_string().
Андрей
Транский (Romantik)
Еще вариант сохранять как *.CSV Файл. А потом
загружать в таблицу.
Нужно взять за правило!
Делать addslashes() при добавлении строки в
таблицу и
stripslashes() при выборке.
И тогда будет намного меньше
проблем.
Из мануала-
string addslashes (string str)
Returns
a string with backslashes before characters that need to be quoted
in
DATABASE QUERIES etc. These characters are single quote ('), double quote
("), backslash () and NUL (the null byte).
Написано же -
DATABASE QUERIES, т.е. спец. для этого и придумано.
Читаем все имена в массив а потом формируешь урл из элементов массива в урле
передаешь номер следующего или предыдущего номера картинки
<?
$fd=@opendir("$id");} $i=0;
if($fd)
{ while($file=@readdir($fd))
{if($file!="." and $file!="..")
{$cornerimage[$i]=$file;$i++;}
else
{$r=100;}
}
@closedir($fd);$r=count($cornerimage);
?>
<font face=arial>
<table height=400 cellspacing=10
cellpadding=0 valign=top width=100% >
<tr>
<td aligh=center
valign=top wrap><center>
<br><font size=-2>
<!--Модуль навигации цифрами-->
<? $j=0;
if($r<100)
{
for ($i=0;$i<($r);$i++)
{ if ($j<19)
{;?><a
href=index.php3?idd=<?echo
$i.'&id='.$id.'&mid='.$mid.'&lng='.$lng;?>><?echo
$i+1;?></a> <?$j++;}
else
{$j=0;?><br><a href=index.php3?idd=<?echo
$i.'&id='.$id.'&mid='.$mid.'&lng='.$lng;?>><?echo
$i+1;?></a> <?}
};?> </font><?
}
else
{
}
;?>
</font> <hr>
<!--
Модуль вывода картинки и навигации стрелками-->
<?
if(!$idd )
{$idd=0;?><img src="<?$size=getimagesize("$id/$cornerimage[$idd]");
echo $id.'/'.$cornerimage[$idd].'" width="'.$size[0].'"
height="'.$size[1].'"';$idd++;?>" alt="Picture"><br><hr><a
href=index.php3?idd=<? echo
$idd.'&id='.$id.'&mid='.$mid.'&lng='.$lng;?>>next
>></a><?;}
else
{if($idd!=($r-1))
{$pidd=$idd-1;?><img
src="<?$size=getimagesize("$id/$cornerimage[$idd]"); echo
$id.'/'.$cornerimage[$idd].'" width="'.$size[0].'"
height="'.$size[1].'"';$idd++;?>" alt="Picture"><br><hr><a
href=index.php3?idd=<? echo
$pidd.'&id='.$id.'&mid='.$mid.'&lng='.$lng;?>><<
prev</a> <a href=index.php3?idd=<? echo
$idd.'&id='.$id.'&mid='.$mid.'&lng='.$lng;?>>next
>></a><?;}
else
{$pidd=$idd-1;?><img
src="<?$size=getimagesize("$id/$cornerimage[$idd]"); echo
$id.'/'.$cornerimage[$idd].'" width="'.$size[0].'"
height="'.$size[1].'"';$idd++;?>" alt="Picture"><br><hr><a
href=index.php3?idd=<? echo
$pidd.'&id='.$id.'&mid='.$mid.'&lng='.$lng;?>><<
prev</a> <?;}
}?>
</td>
</center>
</tr>
</table>
</font>
здесь cornerimage[] -массив имен картинок
id - имя директории
idd - номер элемента массива
данный метод позволяет выводить картинки
независимо от названий и типов файлов
Есть и даже не одна.
В первую очередь советую ознакомиться с
http://www.phplot.com
Также... можно пользоваться
менее громоздкой библиотекой от Евгения Панина.
http://phpclasses.upperdesign.com/browse.html/package/94
И посмотреть соответсвующий раздел в репозитории
http://phpclasses.upperdesign.com/browse.html/class/11
Ну и на последок вот сюда заглянуть, будет тоже весьма полезно:
http://www.hotscripts.com/PHP/Scripts_and_Programs/Graphs_and_Charts/
SY Slach
К примеру Вам нужно отправить письмо в КОИ-8R
Добавляем заголовки для
КОИ-8р
$extend_koi8r="\nContent-Type: text/plain;
charset=\"koi8-r\"\nContent-Transfer-Encoding: 8bit";
Конвертируем тело
и заголовок
$email_body=convert_cyr_string($email_body,'w','k');
$email_subject=convert_cyr_string($plain_subject,'w','k');
Отправляем
перекодированную почту
mail("адрес_получателя", "$email_subject",
$email_body, "From: Info
<адрес_отпрвителя>".$extend_koi8r);
Для других кодировок ищите в мануале convert_cyr_string
навеяно
http://phptalk.unet.ru/p/read.php?f=10&i=7429&t=7429&v=f
Итак был вопрос
.........
Есть у нас php скрипт, который
обращается к MYSQL БД.
Если мы впишем в скрипт, условно говоря, root
mysql'я,
то можем ли мы рассчитывать на безопасность действий (адекватность
и однозначность написанных операций) с БД?
Можем ли мы рассчитывать на
безопасное хранение пароля в пхп-скрипте?
........
1) Лучше создать
еще одного пользователя в базе mysql и урезать ему права.. -
2) Все
поключения к базе из PHP осуществлять через так называемые конфигурационные
файлы. Отсюдова подробнее.
Итак для доступа в mySQL через PHP создаем
файлы дополнительные (конфигурационные) файлы
setup.php & config.php
File setup.php
<?
$dbName="dbName";
$dbUser="dbuser";
$dbPass="dbuserpass";
$dbServer="dbserver";
$adminmail="твое\@мыло";
?>
enf of file
далее создаем файл config.php
File config.php
<?
function db_err($handle, $message) {
printf("%s: %d: %s\n",
$message, mysql_errno($handle),mysql_error($handle));
die();
}
function db_connect() {
global
$dbName,$dbUser,$dbPass,$dbServer;
$dbh =
mysql_connect($dbServer,$dbUser,$dbPass);
if(!$dbh) { db_err($dbh,
"mysql_connect"); }
$res = mysql_select_db($dbName);
if(!$res) {
db_err($dbh, "mysql_select_db"); }
return($dbh);
}
?>
end of file
потом выносим эти файлы за пределы сервера, и наконец
подключаем эти файлы в тех файлах где будем работать с базой.
<?
require("ваш_путь/setup.php");
require("ваш_путь/config.php");
?>
и в конечном итоге получаем красивый и вполне безопастный код.
$dbc=db_connect();
$query = "SELECT .................";
$result
= mysql_query($query,$dbc);
В конфигурационном файле сервера Apache, в контексте соответствующей
директивы <Directory> указать(или в .htaccess):
php_admin_value open_basedir /home/null/www/htdocs
php_admin_value
doc_root /home/null/www/htdocs
часто приходится хранить всякие везде-используемые данные/функции в отдельных
файлах, и потом подключать,
используя include[_once]/require[_once].
но эти файлы обычно не парсятся сервером, т.е. их можно смотреть через
браузер, этого мы и хотим избежать.
давать таким файлам расширение .php не
очень правильно, т.к. их можно вызвать через браузер, и,
хотя мы и не увидим
содержимое, но, наверняка, у нас начнут вылазить какие-либо ошибки PHP,
т.к.
код внутри файлов обычно расчитан на исполнеие в определенном окружении(наличие
коннекта к базе/
чтение файлов/определенные значения констант/переменных).
есть 2 выхода по сути похожих
1. поместить все .inc файлы за
пределами DOCUMENT_ROOT Apache
2. написать .htaccess чтобы запретить доступ
ко всем файлам с определенными расширениями
Пример.
<FilesMatch
"\.(inc|sql|...другие расширения...)$">
order deny,allow
# запретить
доступ отовсюду
deny from all
#разрешить доступ с вашего ip(если он у
вас, конечно, статический)
allow from <ваш ip>
</FilesMatch>
Я думаю, сейчас самое время перейти от слов к делу - сделать первый небольшой
скрипт. Возьмем для примера следующую задачу. Нужно сделать базу с книгами,
которые появились или скоро появятся в продаже, и которые вызывают интерес.
Для этого нам понадобятся: база (таблицы сделаем в MySQL), форма ввода,
процедура загрузки из текстового файла (на тот случай, если ранее список книг
лежал в файле - у меня дело именно так и обстоит), страница для вывода с
сортировкой по критериям и, как дополнительный прибамбас (его сделаем в самую
последнюю очередь), загрузка новостей с сайтов издательств с занесением
выбранных позиций в базу.
Цель проекта проста. Не упустить интересующее
чтиво.
Структура таблиц будет такой. Таблица описания книг BOOKS:
id int(5) - уникальный id autoincrement primary key - сначала хотел
сделать автора и название ключем, решил, что это будет неудобно, если решим
добавлять ссылочные таблицы)
author char(60) - автор
namebook text(100)
- название книги
series int(2) - id серии (если книга принадлежит серии) -
для серий отдельная таблица
edition int(2) - издание
year int(4) - год
издания
isbn char(20) - ISBN (интересно, 20 символов хватит?)
pages
int(4) - объем книги
when_create int(2) - номер квартала (за точку отсчета
возьмем I квартал 2000)
how int(4) - предположительная цена
status
int(1) - id статуса: обязательно заказать, посмотреть подробнее и т.п.
Для
начала хватит. Потом добавим серии книг, статусы, таблицу оглавлений и обложек
(в blob-ах), комментарии к книгам и список интернет-магазинов, в которых книга
была обнаружена.
Для создания таблицы нам понадобится создать базу данных в
MySQL (назовем ее тоже BOOKS) и в ней уже саму таблицу. Но сначала об установке
MySQL. Я опишу установку под WinNT (под *nix-ы его надо собирать - я пока это
проделывать не пробовал).
Процедура эта довольно проста. Надо забрать
дистрибутив с http://www.mysql.com, раскрыть zip,
запустить setup.exe. После окончания установки в каталоге MySQL-я будет лежать
файл my-example.cnf. Предполагается, что его надо будет скопировать в каталог
c:\ под именем my.cnf. Я этого не делал. Вместо этого, следуя Readme-файлу, я
запустил winmysqladmin.exe, выбрал закладку "my.ini Setup", указал директорию, в
которой живут поддиректории MySQL-я (у меня это C:/usr/local/mysql), выбрал
радиобаттон в секции "mysqld file" mysqld-nt (запуск MySQL-сервера как службы в
NT) и нажал на "Save Modification". После чего в WINNT-каталоге обнаружил файл
my.ini. Все. Осталось убедиться, что в списке служб появилась служба "mysql", и
выставить ей атрибут запуска (руками/автоматом).
Итак, заходим в каталог
(если вы, конечно, не внесли эту директорию в path-окружение) c:\mysql\bin (или
туда, куды вы установили MySQL; далее будем полагать, что mysql установлен в
c:\mysql) и запускаем mysqladmin с параметром (краткую справку по параметрам
mysqladmin-а я приведу в следующем шаге).
create
<имя база>.
В нашем случае
create books.
mysqladmin никакой мессагой нас не порадовал, но, зайдя в c:\mysql\data (там
по умолчанию mysql хранит базы данных, если не задано противное в конфигурации
сервера), можно с чувством глубокого удовлетворения обнаружить директорию books.
Это и есть наша база. Правда, директория пуста - мы ведь не создали в базе еще
ни одной таблицы. (Кстати, если вы решите удалить базу пудем удаления директории
- лучше откажитесь от этой затеи. Mysql хранит у себя информацию о существующих
базах. Для корректного удаления базы есть параметр у mysqladmin-а:
drop <имя базы>.
Создаем таблицу. Можно
зайти в mysql.exe и создать там, а можно скормить тектовый файл с командами для
mysql-я на вход exe-шнику. (При заходе с локальной машины mysql считает, что
пришел root со всеми полномочиями - о пользователях и полномочиях в mysql-е
поговорим позднее).
Итак, либо, зайдя в mysql, введите нижеследующую
последовательность команд, либо сохраните их в файле (например, books.sql) и
скажите
mysql < books.sql
А вот
содержимое books.sql:
connect books;
create table books (
id int(5) not null primary key auto_increment,
author char(60),
namebook varchar(100),
series int(2),
edition
int(2),
year int(4),
isbn char(20),
pages
int(4),
when_create int(2),
how int(4),
status
int(1)
);
Зайдя теперь в каталог
c:\mysql\data\books, вы обнаружите целых три файла: books.frm (структура
таблицы), books.myd (данные; сейчас он нулевой длины - insert-ов ведь не было!)
и books.myi (данные о ключах).
На последок небольшое пояснение по первой
строке (полю) в insert-е. По идее, параметр "not null" не нужен, раз "primary
key" говорим. Но есть мнение, что лучше все же его указать (я не готов это
утверждение как-либо комментировать). Auto_increment, соответственно,
присваивает одноименный атрибут полю, позволяя при insert-е автоматически
генерить цифру на единицу большую, чем в предыдущем insert-е.
Итак, база (и первая таблица в ней) созданы.
Напишем скрипт, который
будет формировать html-страницу с содержимым таблицы. Но сначала таблицу надо
заполнить содержимым. Так как форма ввода у нас еще не создана, то воспользуемся
методом из предыдущего шага - создадим sql-запрос на добавление записи в таблицу
и направим его (файл с запросом) на вход mysql.exe.
Вот этот скрипт:
connect books;
insert into books (
id,
author, namebook, series, edition, year, isbn,
pages, when_create, how,
status)
values (null, "Р. Яргер и др.",
"MySQL и mSQL. Базы данных для небольших предприятий
и Интернета",
0, 0, 2000, "5-93286-010-3", 557, 3,
170, 0),
(null, "Ларри УОЛЛ", "Программирование на
Perl",
0, 3, 2001, null, 1200, 5, null, 0);
Несколько замечаний по этому запросу. Во-первых, я не сказал "commit". В
данном случае это не обязательно, т.к. commit произойдет по окончанию скрипта
автоматически. Во-вторых, в качестве значения для ключевого поля id выбрано
значение null, что заставляет mysql присвоить (в силу параметра для поля
auto_increment) числовое значение, на единицу большее, чем максимальное из
существующих значений для этого поля в таблице. В-третьих, некоторые поля мы
"занулили" - потом заполним. И в-четвертых, этот запрос к sql-серверу отличается
от стандарта! Дело в том, что (как я уже говорил) mysql имеет некоторые отличия
от sql-стандарта. В частности, insert допускает такую сокращенную форму записи.
По правилам я бы должен был бы вместо одного insert-а с перечисленными через
запятую группами значений в values использовать два запроса. Но мы облегчили
себе жизнь. Вообще-то это, на мой взгляд, не лучшая практика - использовать
всякие "отклонения от нормы". По крайней мере страдает переносимость. Но нас
сейчас эта тема вряд ли должна волновать.
Теперь напишем скрипт для нашей
первой страницы. HTML-код пока использован по минимуму. Кстати, чуть не забыл.
Если вы используете (готовитесь использовать ;) PHP3, то в php3.ini в виндючем
каталоге раскомментируйте строчку
extension=php3_mysql.dll
Для PHP4
(его ini-файл кличут php.ini) ничего делать не надо, т.к. поддержка mysql в 4-й
версии встроенная.
А теперь обещанный скрипт:
<html><body>
<table border=1>
<?php
$db_name="books"; //база данных
$table="books"; //таблица
$host="localhost"; //хост
$user=""; //логин (при
коннекте к локальному хосту логин и пароль не нужен - нас итак пустят! ;)
$pass=""; //password
//законнектимся - получаем link-идентификатор или вывод номера и текста
ошибки
//с последующим прерыванием работы скрипта (die())
$link=mysql_connect($host,$user,$pass) or
die(mysql_errno($link).mysql_error($link));
//выбираем базу данных BOOKS,
созданную нами ранее
$db=mysql_select_db($db_name,$link) or
die(mysql_errno($link).mysql_error($link));
//выберем данные
$result=mysql_query("SELECT * FROM ".$table, $link) or
die(mysql_errno($link).mysql_error($link));
//сформируем заголовок таблицы
результатов выборки
$th=explode("#","ID#Автор#Название
книги#Серия#Ред.#Год#ISBN#Стр.#Когда#Цена#Статус");
echo
"<tr><th>",implode("</th><th>",$th),"</th></tr>";
//выведем результаты в HTML-документ
while($data=mysql_fetch_row($result)) {
echo
"<tr><td>", implode("</td><td>",$data),
"</td></tr>";
}
//освободить выделенную под результат
выборки память
mysql_free_result($result);
mysql_close($link);
?>
</table>
</body></html>
Некоторые комментарии
(более подробно в следующих шагах).
Во-первых, даже в такой упрощенной форме
код работы с mysql избыточен. Т.к. мы работает с одной базой, да еще и делаем
единственный запрос, то вместо mysql_connect(), mysql_select_db() и
mysql_query() достаточно было вызвать mysql_db_query(). Эта функция при
необходимости выполнит коннекцию (в прочем, в этом она не одинока), выберет базу
данных и выполнит запрос к базе.
Во-вторых, mysql_close() тоже
необязательна, т.к. соединение с сервером будет автоматически закрыто при
окончании скрипта.
В-третьих, и уж конечно же в данном случае во
mysql_free_result() никакой необходимости. Освобождать память при единственном
запросе да еще такого незначительного объема... Здесь эта функция вызвана скорее
для демонстрации возможных операций с mysql на php, ну или, если хотите, для
порядка. ;)
В-четвертых, функции implode() и explode() относятся к
стринговым. Этой теме будет посвящен отдельный шаг (шаги). А пока: explode()
создает массив из фрагментов строки, разбирая ее как строку с разделителем,
указанном в первом параметре. Implode() делает обратную операцию. Эту пару я
применил для удобства - по-моему это проще, чем набирать строку в виде
"...текст</th><th>текст..." и уж тем более проще, чем делать кучу
echo с текстами, обрамленными тегами <th>/</th>.
И в-пятых,
сие чудо программистской мысли ;) выполняется как под 4-й версией php4, так и
под 3-ей.
Далее в программе: подробное описание функций работы с mysql,
форма для ввода записей, чтение (импорт) данных из файла и запись (экспорт) в
файл, index.php3.
Я не буду описывать подробно все изобилие типов MySQL. Я уверен, что это
лишнее. Дело в том, что в mysql-е числовые и текстовые группы типов очень
многочисленны. Отличаются типы в этих группах размером в байтах и возможными
модификаторами. Подробности можно посмотреть в мануале в директории Docs
каталога с mysql-ем в разделе "7.3 Column types". Там и английский знать особо
не нужно - смотрите на название и цифры длины! ;)
Здесь я сделаю обзор
самих групп типов данных - для быстрого введение.
MySQL поддерживает
следующие типы/группы типов данных:
Числовые. Возможные модификаторы:
UNSIGNED для объявления беззнаковости, ZEROFILL для заполнения лидирующих
пробелов нулями (имеется в виду внешний вид при выводе). Могут быть созданы как
целые (TINYINT, SMALLINT, INT, BIGINT и пр.), так и числа с плавающей точкой
(FLOAT, DOUBLE, REAL и пр.).
Строковые. Возможные модификаторы: BINARY для
объявления поля как бинарного (любые коды хранимых символов), NATIONAL -
модификатор по умолчанию, - использование набора символов для сортировки,
сравнения и пр. Занятный модификатор. Отвечает за конструкцию SET-группы: SET
CHARACTER SET character_set_name | DEFAULT, где character_set_name может
принимать значение cp1251_koi8.
Однако эти установки выставлены по
умолчанию. Выходит, без модификатора результат тот же, что и с ним. Я так понял,
что эти фишки для будущего использования. Модификатор для типа CHAR VARYING
создает строковое поле переменной длины.
BLOB-поля - поля для хранения
двоичных данных.
Типы данных, не попавшие в предыдущие три группы:
TIMESTAMP - поле хранит дату и время последнего изменения записи. Это
значит, что, добавив в таблицу поле типа TIMESTAMP (например, воспользовавшись
конструкцией ALTER TABLE table_name ADD COLUMN column_name TIMESTAMP), Вы, не
производя никаких изменений поля типа TIMESTAMP, будете в нем иметь время
последней операции с записью, влияющей на содержимое строки таблицы.
DATE,
TIME, DATETIME - поля хранения даты, времени, и того, и другого. Тут, я думаю
все ясно.
YEAR - поле, добавленное в версии 3.22, - для хранения года в
интервале с 1901 по 2155.
ENUM - поле, хранящее одно из значений, указанных
в списке при создании (модификации структуры) таблицы, например, ALTER TABLE
tab_name ADD COLUMN col_enum ENUM('Ага', 'Угу', 'Ну его нафиг'). Теперь
поместить в поле col_enum одно из перечисленных значений можно так:
INSERT
INTO tab_name SET col_enum='Ага'
или
UPDATE tab_name SET col_enum=3.
В последнем случае в col_enum будет значение 'Ну его нафиг'. Присвоение полю
значения не из списка (например, col_enum=7 или col_enum='format c:') запишет в
поле пустую строку (даже не 'NULL').
тип SET в отличии от типа ENUM
предназначен для хранения списка значений, например,
ALTER TABLE tab_name
ADD COLUMN col_set SET ('один','два','три','четыре')
Теперь изменим значение
поля:
UPDATE tab_name SET col_set='один' WHERE поле=значение
После
такого запроса col_set будет содержать значение 'один'.
UPDATE tab_name SET
col_set=15
Здесь col_set содержит значение 'один,два,три,четыре'. Да, именно
строку с set-значениями, разделенными запятыми. Цифра 15 - это двоичное 1111.
Каждый бит отвечает за свое значение в списке. Например: 1 - 'del', 10 -
'file1.txt', 11 - 'del,file1.txt' и т.д. Как и в случае с ENUM установка
недопустимого значения записывает в поле пустую строку.
Что такое разбивка на страницы? Самый простой пример - поисковые машины.
Вы даете команду на поиск в ответ на что сервер выдает
тысячи ссылок (и
прочая информация типа названия страницы, даты, и пр.).
Но находится данная
информация не на одной странице.
Она разбита на части. В этом примере вы
научитеть разбивать
результат поиска по базе данных на куски, чтобы
организировать
постарничный вывод.
Cоздадим файл default.phtml,
который содержит базовые фукнции. Вам надо
подправить параметры
(host/user/pass/base)
<?
// Глобальная переменная. Например,
нужна в функции коннекта.
$sock=false;
// новые функции
function sql($a) { return mysql_query($a); }
function sqlrows($a) {
return @mysql_num_rows($a); }
function sqlval($a,$b,$c) { return
@mysql_result(mysql_query($a),$b,$c); }
function sqlget($a) { return
@mysql_fetch_array($a); }
function sqlline($a) { return sqlget(sql($a)); }
function sqllast() { return mysql_insert_id(); }
// коннект к
серверу
function connect() {
global $sock;
$host="*****";
$user="*****";
$base="*****";
$pass="*****";
$sock=@mysql_connect($host,$user,$pass);
if ( ! $sock || !
@mysql_select_db($base,$sock))
die("Сервер временно не работает");
unset($host);
unset($user);
unset($base);
unset($pass);
}
// замена die()
function xdie($zapros="", $info="") {
die("</table></table></table></table><hr><h3>************
$info ***********<br><br>
SQL ERROR..... N".mysql_errno().":
".mysql_error()."</h3><pre>$zapros</pre><hr>");
}
?>
=== 2 ===
данный файл (create.phtml) создаст
таблицу limit_test и забьет в нее 500 строк
вида из разных строк.
<?
include("./default.phtml");
connect();
// удаляем
таблицу (на всякий случай)
sql("DROP TABLE limit_test");
// создаем
if (!sql("CREATE TABLE limit_test (id int, s char(100))"))
xdie("","Таблица не создана");
srand(time());
// создаем
запрос вида << ... VALUES (x,"xx"), (y,"yy"), ... (z,"zz") >>
$s="INSERT INTO limit_test VALUES ";
for ($i=0; $i<500; $i++) {
$s.="($i,\"";
$x=rand(1,100);
for ($j=0; $j<$x; $j++)
$s.=chr(rand(ord('a'),ord('z')));
$s.="\")";
if ($i+1<500) $s.=",";
}
// выполняем запрос, чтобы наполнить таблицу данными
if
(!sql($s)) xdie($s,"Таблица не заполнена");
?>
Done.
=== 3===
Собственно, сам файл (search.phtml), который выводит на
экран форму для поиска и
выводит найденные результаты по ?? штук на
страницу.
<body bgcolor=black text=white link=#9999cc
vlink=#cc9999><font face=arial>
<?
include("./default.phtml");
if (!isset($z)) $z="";
if
(isset($all)) $all=intval($all);
if (isset($start)) $start=intval($start);
if (isset($len)) $len=intval($len);
else $len=10;
echo "<form
action="http://phpclub.chat.ru/mysql/%24PHP_SELF"
method=get>
<input type=hidden name=z value=search>
Что ищем:
<input type=text name=s value='$s'>
Строк:
<input type=text
name=len value='$len' size=5>
<input type=submit value='
search '><br><br>
Спец. символы:
<font
color=#ff6666><b><big>_</big></b></font> -
заменяет 1 любую букву,
<font
color=#ff6666><b><big>%</big></b></font> -
заменяет любую последовательность букв.
Поиск '<b>%</b>' -
найдет все строки, поиск '<b>_</b>' - только строки,
состоящие
из 1 символа. Если поискать 'a', то, скорее всего, ничего
не будет найдено,
однако строки '%a%' точно найдутся.<br>
</form>";
switch
($z) {
case "search":
connect();
$query="SELECT s FROM
limit_test WHERE s LIKE '$s'";
if (!isset($start)) {
if (!(
$res=sql($query) )) xdie($query,"ошибка");
$start=0;
$all=sqlrows($res);
} else {
$query.=" LIMIT $start,$len";
if (!(
$res=sql($query) )) xdie($query,"ошибка");
}
echo "Запрос:
<font color=#00ff00>$query</font><br><br>";
for
($j=1; $j<=$len && $tmp=sqlget($res); $j++) {
echo ($start+$j).".
$tmp[s]<br>";
$stop--;
}
echo "<br>";
for ($i=1;
$i<=floor($all/$len); $i++)
echo "<a
href="../../tppmsgs/msgs0.htm#123" tppabs="http://phpclub.chat.ru/mysql/%24PHP_SELF?z=search&all=$all&len=$len&"."
"start=".(($i-1)*$len)."&s=".urlencode($s).">$i</a> ";
break;
}
?>
Сборка из исходников: при настройке исходников (./configure) надо обязательно
указать ключ
--with-pgsql=/path/to/pgsql/install
Установка из
RPM: надо установить пакет
php-pgsql.[version].rpm
По порядку:
1. PostgreSQL должен быть собран с ключами
--enable-locale --enable-multibyte. RPM'ы, как правило, собираются с этими
ключами, если вы собираете из исходников — не забудьте их указать!
2. У
пользователя, от лица которого работает сервер (обычно postgres) должна быть
установлена нужная локаль. Этого можно добиться, например, добавив в его файл
.bash_profile строки:
LANG=ru_RU.KOI8-R
export LANG
Если
нужной локали (например с кодировкой CP1251) в системе нет, то перед этим надо
проделать следующее:
$ localedef -c -i ru_RU -f CP1251 ru_RU.CP1251
3. После этого надо проинициализировать директорию, в которой будут
находиться базы данных, указав кодировку по умолчанию (можно, впрочем и не
указывать):
$ initdb -E KOI8
или, для любителей длинных ключей
$ initdb --encoding=KOI8
Учтите: начиная с версии 7.1 порядок
сортировки строк и разница между заглавными/строчными буквами задаётся именно
при этой инициализации в соответствии с установленной локалью, потом их изменить
нельзя. До версии 7.1 эти значения определялись локалью при запуске
postmaster'а, что могло привести к порче индексов по текстовым полям.
4.
Кодировку также можно указывать при создании отдельных баз:
$ createdb
-E win mustdie
5. Если все шаги проделаны верно, то сортировка, функции
upper()/lower(), операторы ILIKE и ~* должны работать правильно. Если не
работает хотя бы одна из этих функций — проверьте настройки.
Есть. Называется (сюрприз-сюрприз) phpPgAdmin, смотреть здесь: http://www.greatbridge.org/project/phppgadmin/projdisplay.php
Если неохота разбираться в тонкостях:
CREATE TABLE foo (
id
SERIAL,
...
);
и всё заработает.
Если есть желание
разобраться:
Для генерации «суррогатных» первичных ключей в PostgreSQL
используются «последовательности» (SEQUENCE). Вышеприведённый пример на самом
деле раскрывается в такую конструкцию:
CREATE SEQUENCE foo_id_seq;
CREATE TABLE foo (
id integer DEFAULT nextval('foo_id_seq'),
...
);
CREATE UNIQUE INDEX foo_id_key ON foo (id);
Если делать ту же
работу «вручную», то нагляднее всего (IMHO!) получается так:
CREATE SEQUENCE
foo_seq;
CREATE TABLE foo (
id integer NOT NULL DEFAULT
nextval('foo_seq'),
...,
PRIMARY KEY (id)
);
Если нужно (как
чаще всего и бывает), чтобы поле заполнялось автоматически, не надо указывать
его в команде INSERT вообще. При попытке вставить туда значение NULL или 0
возникнет ошибка.
Следует отметить: последовательность совершенно не
зависит от таблицы, при большом желании можно использовать одну и ту же
последовательность для генерации ключей в разных таблицах. Вообще, возможности
последовательностей в PostgreSQL значительно шире, чем auto_increment полей в
MySQL. Как обычно, читайте документацию. :]
Если для генерации ID используются SEQUENCE'ы (см. предыдущий вопрос), то вот
такой запрос:
SELECT currval('sequence_name');
выдаст последнее
значение, выбранное из последовательности sequence_name функцией nextval() в
текущем соединении с базой. Подчёркиваю: в разных, пусть даже одновременно
работающих, скриптах эта функция будет возвращать разные значения.
Если же в
текущем соединении функция nextval('sequence_name') не выполнялась, то
currval('sequence_name') вернёт ошибку.
Также можно использовать
функцию pg_getlastoid(), особенно если нужно получить не ID последней записи, а
какие-то другие поля.
Она возвращает значение oid — неявного системного поля
— последней вставленной записи.
Выбрать собственно ID записи можно следующим
запросом:
SELECT id FROM foo WHERE oid={$oid};
где $oid —
значение, полученное от pg_getlastoid().
Перед INSERT запросoм надо выполнить:
convert_cyr_string($query,"w","a");
После запроса на выборку SELECT выполнить преобразование:
convert_cyr_string($res['value_string'],"a","w");
Решение от
Vitali Nasonov
nasonov@carb.siobc.ras.ru
в настройках MSSQL: (на примере
MSSQL7/NT4):
Start -> Program -> MS SQL Server 7.0 -> Client
Network Utility ->
-> DB Library Options -> Automatic ANSI to OEM
Conversion (убрать
галочку)
Установка
Для того, чтобы иметь возможность писать документы в XML с
последующей трансформацией в HTML через XSLT вам нужно иметь PHP4 сконфигуренный
с поддержкой:
XML (--with-expat)
XSLT (--with-sablot=/usr/local)
Как использовать
Для начала надо ознакомиться с докой PHP по
использованию XSLT а также XSLT specification и XPath language.
Также
вам понадобиться использовать output буфферы чтобы перенаправить сгенеренный PHP
текст в XSLT процессор.
После этого вы можете написать простой скрипт:
<?
/* начинаем буффер */
ob_start()?>
<xml>
<title>Welcome to the world!</title>
<author>
<name>Ruslan</name>
<email>contact@ruslan.org</email>
</author>
<content>
Hello world form <?echo
$PHP_SELF?>!
<p/>
<?/* любой PHP код выводящий
<u>правильный</u> XML! */?>
Привет по русски!
<p/>
Для того что-бы использовать русский язык нужно перед
обработкой
преобразовать в UTF8 а после обработки обратно.
</content>
</xml>
<?
/* берем из буффера */
$text =
ob_get_contents();
ob_end_clean();
/* читаем XSL stylesheet */
$xsl
= join("", file("example.xsl"));
/* обрабатываем */
xslt_process(utf8_encode($xsl), utf8_encode($text), $result);
/* выводим
на экран результат */
echo utf8_decode($result);
//echo "<pre>" .
htmlspecialchars(utf8_encode($text)) . "</pre>";
?>
Используется следующий шаблон example.xsl:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output
indent="yes"
encoding="utf-8"
/>
<xsl:template
match="xml">
<html>
<xsl:apply-templates/>
</html>
</xsl:template>
<xsl:template match="title">
<font
size="+1"><xsl:apply-templates/></font>
</xsl:template>
<xsl:template match="author">
by <a
href="mailto:{email}">
<xsl:value-of
select="name"/>
</a>
</xsl:template>
<xsl:template match="content">
<blockquote>
<xsl:apply-templates/>
</blockquote>
</xsl:template>
<xsl:template match="p">
<p/>
</xsl:template>
</xsl:stylesheet>
После работы
которого на экран будет выводится следующее:
<?xml version="1.0"
encoding="utf-8"?><html>
<font size="+1">Welcome to the
world!</font>
by <a href="mailto:contact@ruslan.org">Ruslan</a>
<blockquote>
Hello world form /ruslan/xsltlib/example.php!
<p/>
Привет по русски!
<p/>
Для того что-бы
использовать русский язык нужно перед
обработкой преобразовать в UTF8 а
после обработки обратно.
</blockquote>
</html>
Зачем?
Это очень удобно, php генерит контент а xsl шаблон
создает HTML страничку(пожно WAP, TXT, etc). Вам не надо думать о том как это
выглядит, только о структуре данных, представленных в XML.
Есть одна
проблема: XSLT расширение PHP пока немножко глючное(или это у меня :-)).
p.s. Эта статья вместе с примером доступна по адресу: http://www.ruslan.org/dev/xslt-example.zip
В документе надо указать
<?xml version="1.0"
encoding="input-encoding"?>
где
input-encoding ::= CP1251 | KOI8-R
В stylesheet`е
<xsl:output method="xml|html|text"
encoding="output-encoding">
output-encoding ::= CP1251 | KOI8-R
Перекодирование производится с помощью библиотеки iconv
(iconv
--list)
Только для Linux/Unix платформ.
Взято из
http://www.gingerall.com/charlie-bin/get/webGA/act/sablot_faq.act
Added by Slach < slach@chel.ru
>
Также существует Path для Sablot 0.51 который можно применять и для
последующих версий (0.52 например).
Лежит по адресу
http://btp1da.phy.uni-bayreuth.de/ftp/pub/FreeBSD/ports/textproc/sablotron/files/rus-patch
Для win32 откомпилированный Sablot 0.51 с поддержкой win1251 лежит по
адресу
http://quake.ems.ru/files/sablot.win1251.zip
Added by Slach < slach@chel.ru
>
============== RU.XML ================
многие спрашивают, как
запустить sablotron на win32
с поддержкой русских кодировок.
осмелюсь
ответ дать в эху. бинарь под win32 на gingerall скомпилен без iconv. так что...
0. будем считать, что лежать файлы будут:
c:/usr/local/bin- бинари
c:/usr/local/include- include-файлы
c:/usr/local/lib- библиотеки в PATH
должен быть прописан c:/usr/local/bin сложный путь
--------------- 1.
скачиваем expat-
http://prdownloads.sourceforge.net/expat/expat-1.95.1.tar.gz
(в бинаре нет либ - так что компилим сами)
распаковываем, компилим:
lib/expat.dsp
expat.h ->/usr/local/include/expat.h
expat_1_95_1.dll->/usr/local/bin/expat.dll 3. скачиваем iconv -
ftp://ftp.ilog.fr/pub/Users/haible/gnu/libiconv-1.6.1.tar.gz
распаковываем, компилируем (нужен MSVC):
nmake -f Makefile.msvc DLL=1
MFLAGS=-MD include/iconv.h ->/usr/local/include/iconv.h
lib/iconv.lib->/usr/local/lib/iconv.lib
lib/iconv.dll->/usr/local/bin/iconv.dll 4. скачиваем sablotron - (бинарь
скомпилен без iconv'а, так что сами
делаем)
http://www.gingerall.com/perl/rd?url=sablot/Sablot-0.52.tar.gz
распаковываем, компилируем (нужен MSVC): простой путь
---------------
1. скачиваем expat-
http://prdownloads.sourceforge.net/expat/expat_win32bin_1_95_1.zip
ставим в /usr/local
expat_1_95_1.dll->c:/usr/local/bin/expat_1_95_1.dll 2. скачиваем бинарь
iconv от меня
http://protey.ru/xml/libiconv-1.6.1-win32bin.rar
ставим в
/usr/local
iconv.dll->c:/usr/local/bin/iconv.dll 3. скачиваем бинарь
sablotron от меня
http://protey.ru/xml/Sablot-0.52-win32bin.rar
ставим в
/usr/local
sabcmd.exe->c:/usr/local/bin/sabcmd.exe
sablot.dll->c:/usr/local/bin/sablot.dll тест
---------------
incl.xsl:
<?xml version="1.0"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="text"
encoding="koi8-r"
/>
<xsl:template name="alone">
<xsl:text>
</xsl:text>
<xsl:text>OK7</xsl:text>
<xsl:value-of
select="data/item"/>
</xsl:template> </xsl:stylesheet>
incl.xml:
<?xml version="1.0" encoding="cp1251"?>
<item>OK4-тест</item> sabcmd.exe incl.xsl incl.xml incl.out в
incl.out видим в koi8:
OK4-тест вот и все :)
Прежде всего объявляется вечная благодарность su1d'у ;) за терпение и
усидчивость... а также за то, что скомпилил php_gxslt под win32
1) качаем
libxslt
http://www.fh-frankfurt.de/~igor/projects/libxml/data/libxml2-2.4.10.win32.zip
http://www.fh-frankfurt.de/~igor/projects/libxml/data/libxslt-1.0.7.win32.zip
2) качаем iconv
http://www.fh-frankfurt.de/~igor/projects/libxml/data/iconv-1.7.win32.zip
3) кладем libxslt.dll libexslt.dll libxml2.dll iconv.dll в
c:\WinNT\system32\ причем libxml2.dll там наверняка уже лежит, потому что
поставляется вместе с php4.0.6... но там старая версия поэтому надо затирать
4) туда же кладем xsltproc.exe (это аналог sabcmd.exe)
5) идем сюда http://www.e-taller.net/dev/gxslt/
и качаем zip файлик с
extention
6) кладем php_gxslt.dll в c:/usr/local/php/extentions/
Тестовые файлы для проверки работоспособности...
====test.xml====
<?xml version="1.0" encoding="windows-1251"?>
<?xml-stylesheet
type="text/xsl" href="test.xsl"?>
<cookbook>
<recipe>
<name>Pasta Carbonara</name>
<difficulty>Easy</difficulty>
<time>25
minutes</time>
<rating>*****</rating>
<chef>Chef
Michele</chef>
<comments>This delicious Italian dish consists of
a blend
of pasta, bacon and eggs. Eat it morning, noon or
night! Єшяр
ЄхёЄ ш тёх Єръюх... шэЄхЁхёэю </comments>
</recipe>
<recipe>
<name>La Bistecca</name>
<difficulty>Difficult</difficulty>
<time>35
minutes</time>
<rating>*****</rating>
<chef>Chef
Nino</chef>
<comments>La Bistecca, Italian for 'steak', grilled
tender
in the summertime is my favorite dish!</comments>
</recipe>
<recipe>
<name>Pollo fritto</name>
<difficulty>Difficult</difficulty>
<time>45
minutes</time>
<rating>*****</rating>
<chef>Chef
Rita</chef>
<comments>Nothing says Italian like fried
chicken!</comments>
</recipe>
</cookbook>
====test.xml====
====test.xsl====
<?xml version="1.0"
encoding="windows-1251"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output
encoding="windows-1251" method="html" />
<xsl:template
match="/cookbook">
<head>
<title>What's Cooking at
WebReview</title>
</head>
<body bgcolor="white"
text="#000000" link="#ff8000"
vlink="#000000" alink="#ff0000">
<center>
<table bgcolor="white" border="0" cellpadding="0"
cellspacing="0">
<xsl:call-template name="recipes"/>
</table>
</center>
</body>
</xsl:template>
<xsl:template name="recipes">
<xsl:for-each select="recipe">
<tr>
<td
width="60%">
<font size="4"><xsl:value-of select="name"/>
</font>
<br/>
Rating: <xsl:value-of
select="rating"/>
<br/>
Preparation time: <xsl:value-of
select="time"/>
<br/>
Submitted By: <xsl:value-of
select="chef"/>
<br/>
Level: <xsl:value-of
select="difficulty"/>
<br/>
<xsl:value-of
select="comments"/><br/>
<hr/>
</td>
</tr>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
====test.xsl====
====libxslt.php====
<?php
$xml_file = "test.xml";
$xsl_file = "test.xsl";
// Open
each file and assign it to a filehandle.
$xml_handle = fopen($xml_file, "r")
or die("Can't open XML file!");
$xsl_handle = fopen($xsl_file, "r") or
die("Can't open XSL file!");
// Read in the file contents.
$xml_content
= fread($xml_handle, filesize($xml_file));
$xsl_content = fread($xsl_handle,
filesize($xsl_file));
$xsl_tfmtion= gxslt_process($xml_content,
$xsl_content,'CP1251');
echo $xsl_tfmtion;
$fl=fopen('text.html','w');
fwrite($fl,$xsl_tfmtion);
fclose($fl);
// Free up the processor
resources.
?>
====libxslt.php====
Всего наилучшего,
....
Slach
Пишите сюда! Тестируйте куски скриптов...
Балуйтесь короче ... :))
Заоодно проверьте защиту..
И что получаем?
Иногда необходимо заархивировать файл и получить архивированный контент в
переменную. Например перед тем, как отослать файл по электронной почте.
Для этого можно использовать недокументированную функцию shell_exec().
Она работает в версиях PHP, начиная с четвёртой. Её описание отсутствует в
документации, но кое-что можно прочитать в комментариях к функции exec()(http://www.php.net/manual/nl/function.exec.php).
Пример использования:
<?
$file = "file_to_zip.ext";
$zipfile=shell_exec("zip - ".$file);
?>
В результате
выполнения этого кода, файл file_to_zip.ext будет заархивирован архиватором
PKZIP и считан в переменную $zipfile.
Чем хорош такой способ ? А тем,
что не надо создавать временных файлов на диске. Вы получаете готовый
архивированный контент, который можно запихнуть в тело письма ввиде аттача :)
Если Вы, как и я, планируете использовать PKZIP, то он должен быть
установлен на сервере. Скачать UNIX-овую инсталляцию можно отсюда - http://www.pkware.com/shareware/pkzu251.html.
Ну и
естественно очень советую выполнить на сервере man zip - все ключи в мане
расписаны очень подробно :)
Ошибки данного типа говорят о том, что автор скрипта, вероятнее всего, где-то
опечатался. В общем виде выглядят примерно так:
Parse error: parse error
*описание ошибки* in *локальный путь до скрипта с ошибкой* on line *номер строки
с ошибкой*
Возможен и сокращённый вариант
Parse error: parse error in
*локальный путь до скрипта с ошибкой* on line *номер строки с ошибкой*
Основные проблемы при устранении таких ошибок сводятся к двум:
1) Найти
строку, на которую указывает интерпретатор (для пользователей Блокнота, или
любого редактора, который при автопереносе заменяет настоящий номер строки)
2) Найти строку, в которой РЕАЛЬНО произошла ошибка. Обычно это либо
заявленная в сообщении строка, либо одна из строк лежащих выше. Например
следующий код:
echo "Привет !"
// В РНР оказывается есть
коментарии !
// Ну нифига себе !
echo "Пока !";
Выдаст
ошибку: Parse error: parse error, expecting `','' or `';'' in * локальный путь *
on line 6, хотя реально ошибка допущена в первой же строчке ! (пропущена ; )
Ещё хуже дело обстоит с пропуском фигурных скобок.
Дело в том, что с
точки зрения PHP запись
for ($i==0; $i<10; $i++)
echo "I=";
КОД
echo $i;
}
Содержит ошибку в 5 строке, а именно - лишнюю
закрывающую скобку. Для интерпретатора код звучит примерно так:
1) Десять
раз печатаем echo "I=";
2) Выполняем КОД
2) Печатаем echo $i;
3) А
этто ещё что за } ?!
А ведь КОД может иметь не один десяток строк...
И совсем отдельная песня - кавычки. Во первых - кавычку можно
пропустить:
<? echo "Переменные:;
echo $a;
echo $b;
// Ну
нифига себе !
// А код может быть длинный !
echo $c;
echo $d;
echo "Пока !";
?>
Скрипт вызовет ошибку только в восьмой строке,
хотя пропустили кавычку вы в первой.
Во-вторых кавычки можно перепутать,
поскольку их в РНР два вида - " и ' :
<? echo "Переменные:';
echo $a;
echo $b;
// Ну нифига себе !
// А код может быть длинный !
echo
$c;
echo $d;
echo "Пока !";
?>
Скрипт опять вызовет ошибку
только в восьмой строке, хотя вы и закрыли кавычку - правда не ту, что открыли.
Ну и наконец, можно напечатать что-то вроде:
echo "<table
border="0" width="780" align="center">";
и головная боль вам обеспечена.
А правильно так:
1. echo '<table border="0" width="780"
align="center">';
Или так
2. echo "<table border=\"0\"
width=\"780\" align=\"center\">";
Вот вроде и всё.
Напоследок
несколько советов:
1) Используйте редакторы с подсветкой - незакрытые
кавычки они вам продемонстрируют.
2) Все циклы, операторы выбора и т.п.
оформляйте "лесенкой",
это позволит быстро найти пропущенную скобку.
3)
Будьте бдительны :)
@ - атавизм.
Для отладки действительно лучше использовать
error_reporting и перехватывать стандартный обработчик ошибок php.
Пример - кусок из моей бибилотеки.
if (DEBUG_MODE)
{
//All messages printed into browser window
// error_reporting(E_ALL
& ~E_NOTICE);
error_reporting(E_ALL);
}
else
{
error_reporting(0);
include_once 'classes/bavlog.php';
set_error_handler(bavErrorHandler);
/*!
override PHP's main error
handler function
this should NOT be called directly
*/
function
nmErrorHandler($errno, $errmsg, $errfile, $errline, $vars)
{
...
...
some analizer of error
}
}
А собственный вывод сообщений об
ошибках и отладочной информации
сделать не echo, print() а через
trigger_error().
Подробности об использовании собственного обработчика
есть в документации.
Указание @ перед функцией блокирует вывод сообщения об ошибке
Если
track_errors включен то последнее сообщение об ошибке сохраняется в
глобальной переменной $php_errormsg
Если написать в любом файле php:
(test.php3 заменить на свой)
<HR>
<img
src="/test.php3?=PHPE9568F35-D428-11d2-A769-00AA001ACF42">
<HR>
<img src="/test.php3?=PHPE9568F34-D428-11d2-A769-00AA001ACF42">
<HR>
<img
src="/test.php3?=PHPE9568F36-D428-11d2-A769-00AA001ACF42">
Получатся три
картинки, самая прикольная из них это последняя, человек с карандашами в зубах
:) наверное это один из авторов php :)
Закладки на сайте Проследить за страницей |
Created 1996-2024 by Maxim Chirkov Добавить, Поддержать, Вебмастеру |