Разработка многозадачных приложений на PHP V5 (исходники). Разработка многозадачных приложений на PHP V5 (исходники) Спешный listing php

До настоящего момента я упоминал о двух разных подходах к созданию шаблонов PHP:

  • внедрение HTML в код PHP;
  • включение файлов в страницу.

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

Вторая схема во многих ситуациях оказывается гораздо удобнее первой. Тем не менее, хотя структура «заголовок -- основная часть -- колонтитул» (см. главу 9)

хорошо подходит для структурирования относительно малых сайтов с четко определенным форматом, с увеличением объемов и сложности проекта эти ограничения проявляются все заметнее. Попытки решения этих проблем привели к разработке новой схемы применения шаблонов, более сложной по сравнению с двумя первыми, но и обладающей существенно большей гибкостью. В этой схеме разделяются два главных компонента web-приложения: дизайн и программирование. Подобное деление обеспечивает возможность параллельной разработки (web-дизайн и программирование) без необходимости постоянной координации на протяжении всего рабочего цикла. Более того, оно позволяет в будущем модифицировать один компонент, не влияяна работу другого. В следующем разделе я покажу, как устроена одна из таких схем «нетривиальных шаблонов». Следует помнить, что эта схема существует не только в PHP. Более того, она появилась задолго до PHP и в настоящее время используется в нескольких языках, включая PHP, Perl и Java Server Pages. To, что описано в этой главе, -- не более чем адаптация этой схемы применительно к PHP.

Нетривиальная система шаблонов

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

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

Листинг 12.1. Пример шаблона

:::::{page_title}:::::

Welcome to your default home page. {user_name}!

Обратите внимание на три строки (page_title, bg_color и userjiame), заключенные в фигурные скобки ({ }). Фигурные скобки имеют особый смысл при обработке шаблонов -- заключенная в них строка интерпретируется как имя переменной, вместо которого подставляется ее значение. Дизайнер строит страницу по своему усмотрению; все, что от него потребуется, -- включать в соответствующие места документа эти ключевые строки. Конечно, программисты и дизайнеры должны заранее согласовать имена всех переменных!

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

class template {

VAR $files = array();

VAR $variables = array();

VAR $openi ng_escape = "{";

VAR $closing_escape = "}";

В массиве $files хранятся идентификаторы файлов и содержимое каждого файла. Атрибут $variables представляет собой двухмерный массив для хранения файлового идентификатора (ключа) и всех соответствующих переменных, обрабатываемых в схеме шаблонов. Наконец, атрибуты $opening_escape и $closing_escape задают ограничители для частей шаблона, которые должны заменяться системой. Как было показано в листинге 12.1, в наших примерах в качестве ограничителей будут использоваться фигурные скобки ({ }). Впрочем, вы можете изменить два последних атрибута и выбрать ограничители по своему усмотрению. Главное -- проследите за тем, чтобы эти символы не использовались для других целей.

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

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

    В процессе регистрации содержимое файла сохраняется в массиве с ключом, однозначно идентифицирующим этот файл. Метод register_file() открывает и читает содержимое файла, имя которого передается в качестве параметра. Код этого метода приведен в листинге 12.2.

    Листинг 12.2. Метод регистрации файла

    function register_file($file_id, $file_name) {

    // с ключом $file_id. $this->

    // Работа с файлом завершена, закрыть его.

    Параметр $file_id содержит идентификатор -- «псевдоним» для последующих операций с файлом, упрощающий последующие вызовы метода. Идентификатор используется в качестве ключа для индексирования массива $files. Пример регистрации файла:

    // Включить класс шаблона

    include("tempiate.class"):

    $template = new template:

    // присвоив ему псевдоним "home"

    $template->

    Регистрация переменных

    После регистрации файлов необходимо зарегистрировать все переменные, которые будут интерпретироваться особым образом. Метод register_variables() (листинг 12.3) работает по тому же принципу, что и register_file(), -- он читает имена переменных и сохраняет их в массиве $variables.

    Листинг 12.3. Метод регистрации переменнных

    function register_vanables($file_id, $variable_name) {

    // Попытаться создать массив,

    $input_variables - explode(".", $variable_name);

    // Перебрать имена переменных

    while (Iist($value) = each($input_variables)) :

    // Присвоить значение очередному элементу массива

    $this->variables $this->variables[$file_id] = $value:

    В параметре $file_id передается ранее присвоенный псевдоним файла. Например, в предыдущем примере файлу homepage.html был присвоен псевдоним home. Обратите внимание -- при регистрации имен переменных, которые должны особым образом обрабатываться в файле homepage.html, вы должны ссылаться на файл по псевдониму! В параметре $variable_name передаются имена одной или нескольких переменных, регистрируемых для указанного псевдонима. Пример:

    // Включить класс шаблона include("tempiate.class");

    // Создать новый экземпляр класса $template = new template;

    // Зарегистрировать файл "homepage.html",

    // присвоив ему псевдоним "home" $template->register_file("home", "homepage.html");

    // Зарегистрировать несколько переменных

    $template->register_variablest"home", "page_title.bg_color,user_name");

    Обработка файла

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

    Листинг 12.4. Метод обработки файла

    $varcount = count($this->variables[$file_id]);

    $keys = array_keys($this->files):

    // Если файл $file_id существует в массиве

    If ((in_array($file_id. $keys)) && ($varcount > 0)) :

    // Сбросить $x $x = 0:

    while ($x < sizeof($this->variables[$file_id])) :

    // Получить имя очередной переменной $string = $this->variables[$file_id][$x];

    // указанного имени переменной.GLOBAL $$string:

    $needle = $this->opening_escape.$string.$this->closing_escape;

    // Выполнить замену.

    $this->files[$file_id] = str_replace($needle.

    $this->files[$file_id]);

    // Увеличить $х $x++;

    Сначала мы проверяем, присутствует ли указанное имя файла в массиве $this->files. Если файл был зарегистрирован, мы также проверяем, были ли для него зарегистрированы переменные, и если были -- значения этих переменных подставляются в содержимое $file_id. Пример:

    // Включить класс шаблона include("template. class") ;

    $page_title = "Welcome to your homepage!";

    $bg_color = "white"; $user_name = "Chef Jacques";

    // Создать новый экземпляр класса

    $template = new template;

    // Зарегистрировать файл "homepage.html",

    II присвоив ему псевдоним "home"

    $template->register_file("home", "homepage.html");

    // Зарегистрировать несолько переменных

    $template->register_variables("home", "page_titie, bg_color, user_name");

    $template->file_parser("home");

    Поскольку переменные page_title, bg_color и user_name были зарегистрированы, значения каждой переменной (присвоенные в начале сценария) подставляются в страницу homepage.html, хранящуюся в массиве files (атрибуте объекта-шаблона). На этом предварительная подготовка завершается, остается лишь вывести полученный шаблон в браузере. Эта операция рассматривается в следующем разделе.

    Вывод файла

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

    файла создается отдельный метод, приведенный в листинге 12.5, однако в зависимости от ситуации вывод также может интегрироваться с методом f i I e_parser().

    Листинг 12.5. Метод вывода файла в браузере

    function pnnt_file($file_id) {

    // Вывести содержимое файла с идентификатором

    $file_id print $this->files[$file id];

    Все очень просто -- при вызове print_file() содержимое файла, представленного ключом $file_id, передается в браузер.

    В листинге 12.6 приведен пример использования класса template.

    Листинг 12.6. Пример использования класса template

    // Включить класс шаблона, include("tempiate.class");

    // Присвоить значения переменным

    $page_title = "Welcome to your homepage!";

    $bg_color = "white"; $user_name = "Chef Jacques":

    // Создать новый экземпляр класса $template= new template;

    // Зарегистрировать файл "homepage.html" с псевдонимом "home"

    $template->register_file("home", "homepage.html");

    // Зарегистрировать переменные

    $template->register_variables("home", "page_title, bg_color.user_name");

    $template->file_parser("home");

    // Передать результат в браузер

    $template->print_file("home");

    Если бы шаблон, приведенный в листинге 12.1, хранился в файле homepage.html в одном каталоге со сценарием из листинга 12.6, то в браузер был бы направлен следующий код HTML:

    :::::Welcome to your homepage!:::::

    Welcome to your default home page, Chef Jacques!

    You have 5 MB and 3 email addresses at your disposal.

    Как видно из приведенного примера, все зарегистрированные переменные были заменены соответствующими значениями. При всей своей простоте класс tempi ate

    обеспечивает стопроцентное разделение уровней программирования и дизайна. Полный код класса template приведен в листинге 12.7.

    Листинг 12.7. Полный код класса template

    class template {

    VAR $files = array();

    VAR $variables = array();

    VAR $opening_escape = "{";

    VAR $closing_escape = "}" ;

    // Функция: register_file()

    // Назначение: сохранение в массиве содержимого файла.

    // определяемого идентификатором $file_id

    function register_file($file_id. $file_name) {

    // Открыть $file_name для чтения или завершить программу

    // с выдачей сообщения об ошибке.

    $fh = fopen($file_name, "r") or die("Couldn"t open $file_name!");

    $file_contents = fread($fh, filesize($file_name));

    // Присвоить содержимое элементу массива

    // с ключом $file_id. $this->files[$file_id] = $file_contents;

    // Работа с файлом завершена, закрыть его.

    } // Функция: register_variables()

    // Назначение: сохранение переменных, переданных

    // в параметре $variable_name. в массиве с ключом $file_id.

    function register_variables($file_id, $variable_name) {

    // Попытаться создать массив.

    $input_variables = explode(".", $vahable_name);

    // Перебрать имена переменных

    while (list(, $value) = each($input_variables)) :

    // Присвоить значение очередному элементу массива $this->variables $this->variables[$file_id] = $value:

    } // Функция: file_parser()

    // Назначение: замена всех зарегистрированных переменных

    // в файле с идентификатором $file_id

    function file_parser($file_id) {

    // Сколько переменных зарегистрировано для данного файла?

    $varcount = count($this->variables[$file_id]):

    // Сколько файлов зарегистрировано?

    $keys = array_keys($this->files):

    // Если файл $file_id существует в массиве $this->files

    // и с ним связаны зарегистрированные переменные

    if ((in_array($file_id. $keys)) && ($varcount > 0)) :

    // Сбросить $х $x - 0;

    // Пока остаются переменные для обработки...

    while ($x < sizeof($this->variables[$file_id])) :

    // Получить имя очередной переменной

    $string = $this->variables[$file_id][$x];

    // Получить значение переменной. Обратите внимание:

    // для получения значения используется конструкция $$.

    // Полученное значение подставляется в файл вместо

    // указанного имени переменной.

    GLOBAL $$string;

    // Построить точный текст замены вместе с ограничителями

    $needle = $this->opemng_escape.$string.$this->closing_escape;

    // Выполнить замену.

    $this->files[$file_id] = str_replace($needle, $$string,

    $this->files[$file_idj);

    // Увеличить $х $x++;

    // Функция: print_file()

    // Назначение: вывод содержимого файла,

    // определяемого параметром $file_id

    function print_file($file_id) {

    // Вывести содержимое файла с идентификатором $file_id

    print $this->files[$file_id];

    Расширения класса template

    Конечно, класс tempi ate обладает весьма ограниченными возможностями, хотя для проектов, создаваемых на скорую руку, он вполне подходит. Объектно- ориентированные схемы хороши тем, что они позволяют легко наращивать функциональность, не беспокоясь о возможных нарушениях работы существующего кода. Допустим, вы решили создать новый метод, который будет загружать значения для последующей замены из базы данных. Хотя такой метод устроен чуть сложнее, чем метод file_parser(), производящий простую замену глобальных переменных, его реализация на базе SQL состоит из нескольких строк и легко инкапсулируется в отдельном методе. Более того, мы создадим нечто подобное в проекте адресной книги, завершающем эту главу.

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

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

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

    В следующей статье затронута тема использования шаблонов применительно к Java Server Pages:

    Кроме того, описанная схема построения шаблонов используется в нескольких библиотеках PHP, среди которых наибольший интерес представляют следующие:

    • PHPLib Base Library: http://phplib.netuse.de ;
    • Richard Hayes"s Template Class: http://www.heyes-computing.net ;
    • Fast Template: http://www.thewebmasters.net/php .
    Недостатки системы шаблонов

    Хотя рассмотренная система шаблонов справляется со своей главной задачей -- полным разделением дизайна и программирования, она не лишена недостатков. Некоторые из этих недостатков перечислены ниже.

    Необоснованные надежды на «идеальное решение»

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

    Снижение быстродействия

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

    Ориентация дизайна на PHP

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

    Проект: Адресная книга на PHP

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

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

    Прежде всего, необходимо решить, какие данные и в каком формате будут храниться в адресной книге. Конечно, оптимальным носителем информации в данном случае является база данных, поскольку это упростит такие полезные операции, как поиск и сортировка данных. В своем примере я воспользуюсь СУБД MySQL. Определение таблицы выглядит следующим образом:

    mysql>CREATE table addressbook (

    last_name char(35) NOT NULL,

    first_name char(20) MOT NULL,

    tel char(20) NOT NULL,

    email char(55) NOT NULL);

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

    Теперь я возьму на себя роль дизайнера и займусь созданием шаблонов. Для этого проекта нужны два шаблона. Код первого, «родительского» шаблона book.html приведен в листинге 12.8.

    Листинг 12.8. Основной шаблон адресной книги book.html

    :::::{page_title}:::::

    Address Book: {letter}

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

    A |

    B |

    C |

    D |

    E |

    F |

    G |

    H |

    I |

    J |

    K |

    L |

    M |

    N |

    O |

    P |

    Q |

    R |

    S |

    T |

    U |

    V |

    W |

    X |

    Y |

    Z

    {rows.addresses}

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

    В странице встречаются три имени переменных, заключенных в ограничители: page_title, letter и rows_addresses. Смысл первых двух переменных очевиден: текст в заголовке страницы и буква адресной книги, использованная для выборки текущих адресных данных. Третья переменная относится к дополнительному шаблону (листинг 12.9) и определяет файл конфигурации таблицы, включаемый в основной шаблон. Файлы конфигурации таблиц используются в связи с тем, что в сложных страницах может быть одновременно задействовано несколько шаблонов, в каждом из которых данные форматируются в виде таблиц HTML. Шаблон rows.addresses (листинг 12.9) выполняет вспомогательные функции и вставляется в основной шаблон book.html. Вскоре вы поймете, почему это необходимо.

    Листинг 12.9. Вспомогательный шаблон rows.addresses

    {last_name},{first_name}

    {telephone}

    {email}

    В листинге 12.9 встречаются четыре переменных, заключенных в ограничители: last_name, first_name, telephone и emal. Смысл этих переменных очевиден (см. определение таблицы addressbook). Следует заметить, что этот файл состоит только из табличных тегов строк (

    ...
    ...
    , форматирование HTML будет обработано правильно. Чтобы вы лучше поняли, как работает этот шаблон, взгляните на рис. 12.1 -- на нем изображена копия страницы адресной книги. Затем проанализируйте листинг 12.10, содержащий исходный текст этой страницы. Вы увидите, что содержимое файла rows.addresses многократно встречается в странице.

    Если вы еще используете функцию opendir() для листинга папок в PHP, то прочтите как можно гораздо проще, и быстрее это сделать с помощью функции glob(). Glob это гораздо грамотное, вы убедитесь, посмотрев примеры использования glob() в php.

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

    Введение

    Вот пример получения некоторой информации из папки, используя традиционную функцию opendir().

    $dir = "/etc/php5/"; // Open a known directory, and proceed to read its contents if (is_dir($dir)) { if ($dh = opendir($dir)) { while (($file = readdir($dh)) !== false) { echo "filename: $file: filetype: " . filetype($dir . $file) . "\n"; } closedir($dh); } }

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

    $dir = "/etc/php5/*"; // Open a known directory, and proceed to read its contents foreach(glob($dir) as $file) { echo "filename: $file: filetype: " . filetype($file) . ""; }

    Разве это не намного легче? Хотите узнать, как работает данный способ? Если да, то давайте разберемся с этим.

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

    Первый аргумент glob() php

    Первый аргумент функции glob поддерживает шаблон. Это означает, что вы можете ограничить область поиска несколькими каталогами или определенным типом файлов. Давайте предположим, что у вас есть сайт, который позволяет пользователям загружать изображения в их собственную папку в папке userimages. В этих папках еще папки с названиями HD и TN. HD - для высокого разрешения (полноразмерных фотографий), и TN для их превью. Давайте предположим, что вы хотите перебрать все превью пользователей в папке TN и вывести имена всех файлов. Это потребует php код значительного размера, если бы использовали open_dir(), однако с glob() в php это решается легко.

    Foreach(glob("userImages/*/TN/*") as $image) { echo "Filename: " . $image . "
    "; }

    Этот скрипт пройдет по пути userimages/любая папка/TN/любой файл (папка) и вернет листинг папок соответствующих шаблону phpфункции glob().

    Filename: userImages/username1/TN/test.jpg Filename: userImages/username1/TN/test3.jpg Filename: userImages/username1/TN/test5.png Filename: userImages/username2/TN/subfolder Filename: userImages/username2/TN/test2.jpg Filename: userImages/username2/TN/test4.gif Filename: userImages/username3/TN/styles.css

    Мы можем указать более конкретно и включить расширение фала в шаблон glob():

    Foreach(glob("userImages/*/TN/*.jpg") as $image) { echo "Filename: " . $image . "
    "; }

    Теперь результатом будут jpg файлы:

    Filename: userImages/username1/TN/test.jpg Filename: userImages/username1/TN/test3.jpg Filename: userImages/username2/TN/test2.jpg

    Но что же делать, если вы хотите запросить jpg и gif, исключая все остальные файлы? Или вывести только имена папок? В этом случае нам поможет второй аргумент.

    Второй аргумент glob() php

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

    GLOB_MARK : Добавляет слеш к каждому возвращаемому каталогу.

    GLOB_NOSORT : Возвращает файлы так, как они появляются в каталоге (без сортировки).

    GLOB_NOCHECK : Возвращает шаблон поиска в случае отсутствия совпадений с шаблоном.

    GLOB_NOESCAPE : Обратные слеши не экранируют метасимволы.

    GLOB_BRACE : Расширяет {а, Ь, с} для совпадения с "a", "b", или "c" (расширяет область поиска).

    GLOB_ONLYDIR : Возвращение только записей папки, совпадающих с шаблоном.

    GLOB_ERR : Остановка по ошибки чтения (например нечитаемые каталоги), по умолчанию ошибки игнорируются.

    Как видите, наше требование может удовлетворить аргумент GLOB_BRACE:

    Foreach(glob("userImages/*/TN/{*.jpg,*.gif}", GLOB_BRACE) as $image) { echo "Filename: " . $image . "
    "; }

    Этот пример вернет нам:

    Filename: userImages/username1/TN/test.jpg Filename: userImages/username1/TN/test3.jpg Filename: userImages/username2/TN/test2.jpg Filename: userImages/username2/TN/test4.gif

    Если мы хотим получить только имена подпапок, то используем GLOB_ONLYDIR:

    Foreach(glob("userImages/*/TN/*", GLOB_ONLYDIR) as $image) { echo "Filename: " . $image . "
    "; }

    Filename: userImages/username2/TN/subfolder

    Еще пример использования glob в PHP

    Этот способ был доступен, начиная, с PHP 4.3, однако, как ни странно, им не пользуются часто. Раньше я не пользовался таким способом, теперь я всегда использую glob() во время загрузки плагинов в мою рабочую среду:

    Foreach(glob("includes/plugins/*.php") as $plugin) { include_once($plugin); }

    Вот и все! Надеюсь, вам понравилось. Дайте знать, если есть какие-то вопросы по поводу php glob!

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

    Немного о безопасности Можно сделать ограниченный доступ к панели управления (чтобы самому управлять из одного места) или «всемирный», чтобы из любого места можно было управлять.

    Первый случай безопасный - никто не влезет, если за рабочий ПК не сядет. Во втором случае адрес, где стоит ПО надо держать в секрете, плюс предусмотрена установка пароля на вход в панель управления. Чтобы Ваш секретный адрес не «просочился» при переходах по ссылкам на сторонние сайты (из объявлений) сделано следующее:

    • В каждой внешней ссылке стоит такой атрибут rel="noreferrer"
    • Чтобы referer передавался только в пределах одного домена в head стоит тэг:
    • Все внешние ссылки идут через «очиститель referer»: http://nullrefer.com/?http://free.da...
    Результат автоматизации 24 часа 7 дней в неделю все вновь появившиеся в ЦПО объявления досматриваются с интервалом в пару-тройку минут. В результате чего неугодные (по критериям, заданным пользователем) отправляются в раздел «заблокировано». Точно никогда не считал, но примерно из 100 заблокированных штук 90 - 95 заблокированы не зря. Из ста «чистых» по мнению ПО в среднем менее одного «плохого».

    Что я называю «плохими объявлениями»? Всё что ведёт на мобильные подписки, всё что предлагает «скачать», просто скачать или «скачать файл» без какой-либо конкретики вообще, всё что предлагает «смотреть видео», опять же без каких-либо подробностей, всё что ведёт совсем не туда, о чём указано в заголовке и тексте объявления, любые упоминания казино в странах, где это запрещено законом.

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

    Стало меньше и воровства в виде неосознанных подписок даже без карты «МегаФона»!

    А причём здесь карта «МегаФона»?

    To-do lists are a great way to keep track of your daily tasks. In this tutorial, we will build our own to-do list using PHP, MySQL, and AJAX. This tutorial assumes that you have a basic understanding of HTML, PHP, MySQL, and JavaScript.

    We will be using the following files throughout this tutorial. You can download them using the link below. Feel free to use an alternative structure, but remember to change your file paths from those in the example code.

    Main Index File

    The first thing we need to do is lay out the structure for our main index page (index.php ). This application will only have one page and we will use AJAX to add and delete to-do items. Open the index.php file and add the following code.

    Simple To-Do List

    Note: For the sake of time, we will not cover styling in this tutorial. A CSS file has been included in the source files.

    Connecting to the MySQL Database

    We need to set up a MySQL database for storing our to-do items. The easiest way to do this is trough a server-side tool called phpMyAdmin . The tools comes pre-installed on most web hosts and is bundled with local development services such as WampServer and XAMPP. We will be setting up one table with the name of ‘tasks’ and the following columns in this order: ‘id’, ‘task’, ‘date’, ‘time’. Be sure to set the id column to auto-increment (there should be a checkbox labeled ‘A_I’).

    After creating the new table, we need to connect our project to the database. Open connect.php and add the following code to the file. Be sure to substitute your database details for the ‘username’, ‘password’, and ‘database_name’ fields. Save the file when you are done.

    Explaining the Code
    PHP has a mysql_connect() function that creates a connection to the MySQL server. The server variable should remain set to ‘localhost’ unless your database is hosted on a different server than the project files. In that case, substitute this value for the MySQL server’s IP address. Once the connection has been made, the mysql_select_db() function selects a specific database from the server.

    Now that we have created our connect.php file, we need to add it to the main index file. Add the following code to index.php and save the change.

    Simple To-Do List

    Adding a New To-Do Item

    The next thing we want to do is create a way to add items to our to-do list. To do this, we will use a form and submit the results to the database. Add the following code to index.php and save the change.

    Simple To-Do List

    Note: Notice that the form does not have action and method attributes. These are typically used to submit data to another file via a post or get request. We will be using AJAX to submit our form, so we will not be defining either of these attributes. For more information on AJAX, check out this article from W3Schools .

    Open index.php in your web browser and have a look. At this point, you should see a large white rectangle where the to-do items will be displayed and a text field for adding new items to the list.

    We need to set up a way for the form to communicate with the database. Using jQuery, let’s send our new to-do item via a post request to the add-task.php file. From there, our item will be formatted and saved to the database. Add the following to the index.php file directly after the closing tag.

    Explaining the Code
    The script above intercepts the text field value on form submit and sends it to add-task.php using the $.post() jQuery method. The add-task.php file then sends back confirmation of the newly added item, so it can be added to the list. The beautiful thing is that all of this happens without refreshing the page!

    Now that our form is sending the new to-do item to add-task.php , we need to tell that file what to do with the information. Open add-task.php and add the following code. Remember to save the file.