проголосовало
4 пользователей

Вопросы по PHP программированию

PHP программирование →  Продается сайт w2.com.ua

Ко мне обратился мой товарищ с просьбой разместить объявление о продаже его детища. Долгое время он поддерживал данный ресурс своим сайтом и с него шел отличный трафик. Ниже объявление:


Добрый день, уважаемые читатели.

Продаю сайт http://w2.com.ua/

Долгое время я и команда единомышленников поддерживали его, за время существования с 2007 года, проект стал одним из самых посещаемых блогов об интернете в Украине.

Сейчас настало время, когда мы хотим сосредоточится на других проектах. А http://w2.com.ua/ отдать тому, кто сможет сделать его еще лучше.

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

О сайте

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

На сегодняшний день на сайте зарегистрировано более 10 тыс. пользователей.

Сайт посещает более 2500 человек в день (см. статистику Bigmir).

Технические требования: PHP, MySQL.

Цена

Я хочу получить за сайт $3000, цену готов обсуждать. Сайт приносит небольшой, но все же доход.

Основной проблемой является отсутствие времени. Из-за этого нет возможности плотнее работать с аудиторией. Брать интервью, выступать с аналитическими докладами на barcamp, привлекать новых авторов.

Как связаться

Mail — info@w2.com.ua
Телефон — +380 98 692 77 98 (на этот номер смс не приходят, только звонить)
Skype -andrei.vasiliadi

Спасибо за внимание!
Буду благодарен если Вы расскажете своим друзьям, кому проект может быть интересен, а он своим.
0

PHP программирование →  Асинхронность с помощью fastcgi_finish_request()

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

Главный критерий оптимизации для клиента — это скорость ответа (т.е. время, за которое Web сервер отвечает на запрос). Если не брать во внимание клиентскую оптимизацию, есть ряд практик, позволяющих быстрее генерировать ответ клиенту (по сути без оптимизации внутренностей).

Одна из распространенных практик — это переводить необязательную для ответа часть логики в асинхронную обработку. Для этой задачи применяются очереди сообщений.

Если Вы счастливый обладатель связки PHP + PHP-FPM, то существует более простой (хотя и несколько ограниченный) подход для реализации асинхронности. После сборки патча php-fpm, Вам станет доступна функция:

fastcgi_finish_request();

После ее вызова из скрипта, php-fpm получает сигнал о завершении запроса (т.е. отправляет ответ Web серверу), но сам скрипт не завершается. Т.е. вся логика, которая находится после вызова этой функции будет выполнена на фоне.

Для примера рассмотрим задачу отправки письма (зачастую, весьма медленный процесс):

$to = $_POST['to'];
$body = $_POST['body'];
$subject = $_POST['subject'];

if ( $to && $body && $subject )
{
        echo 'Ваше письмо успешно отправлено';
        # После этой инструкции посетителю уйдет ответ
        fastcgi_finish_request();
        # Сама отправка будет выполнена на фоне
        mail($to, $subject, $body);
}
else
{
        echo 'Вы не ввели все необходимые данные';
}

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

Вам приходилось пользоваться fastcgi_finish_request(), и если да, то в каких случаях?
1

PHP программирование →  Переход от php4 к php5 (Статические члены класса. Исключения, определённые пользователем. Пространства имен)

Начало:
http://php5.com.ua/blog/php-programming/133.html
http://php5.com.ua/blog/php-programming/134.html
http://php5.com.ua/blog/php-programming/135.html

Статические члены класса


Статические члены и статические методы могут использоваться для реализации того, что в ООП называется «методы класса» и «переменные класса».

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

Пример: методы класса и переменные класса
<?php
class calculator {
  static public $pi = 3.14151692;

  static public function add($x,$y) {
    return $x + $y;
  }
}

$s = calculator::$pi;
$result = calculator::add(3,7);
print("$result");
?>

Исключения — это общепринятый подход к обработке ошибок и неожиданных ситуаций в таких языках как Java и C++; в PHP5 перехват исключений реализован с помощью пары «try» — «catch».

Пример: Исключения
<?php class foo {

  function divide($x,$y) {
    if($y==0) throw new Exception("деление на ноль недопустимо");
    return $x/$y;
  }
}

$x = new foo();

try {
  $x->divide(3,0);  
} catch (Exception $e) {
    echo $e->getMessage();
    echo "\n<br />\n";
    // Какие-нибудь драконовские меры
}
?>


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

Исключения, определённые пользователем


Для обработки непредвиденных проблем в ваших программах вы можете определить ваши собственные исключения. Всё, что вам нужно — это просто дополнить (extend) класс Exception, определив конструктор класса и метод getMessage.

Пример: Исключения, определённые пользователем

<?php
class WeirdProblem extends Exception {

   private $data;

   function WeirdProblem($data) {
        parent::exception();
        $this->data = $data;
    }

    function getMessage() {
        return $this->data . " вызвало какое-то странное исключение!";
    }
}
?>


Потом, для возбуждения определённого вами исключения используйте конструкцию throw new WeirdProblem($foo); если исключение происходит внутри блока try{}, то PHP5 передаст управление в «catch»-блок для обработки.

Пространства имён


В целях удобства классы и функции могут быть сгруппированы в пространства имён (namespaces).

Примечение: разработчики отказались от поддрежки этой возможности.

Пример: Пространство имён
<?php
namespace Math {

  class Complex {
    //...код...
    function __construct() {
      print("привет");
    }
  }
}

$m = new Math::Complex();
?>

Обратите внимание на синтаксис использования именного пространства для обозначения класса, объект которого мы создаём. Пример практического применения: создание одноимённых классов в разных именных пространствах; при этом классы делают отличную друг от друга работу (имея одинаковый интерфейс).
1

PHP программирование →  Переход от php4 к php5 ( Абстрактные классы. __set и __get)

Начало:
http://php5.com.ua/blog/php-programming/133.html
http://php5.com.ua/blog/php-programming/134.html

Абстрактные классы


Абстрактным называется класс, который может использоваться только как базовый (то есть создавать объекты этого класса нельзя). Как и в любом нормальном базовом классе, в абстрактном классе вы можете определять методы и переменные.

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

Пример: Абстрактные классы
<?php
abstract class foo {
  protected $x;

  abstract function display();

  function setX($x) {
    $this->x = $x;
  }
}


class foo2 extends foo {
  function display() {
    // Код
  }
}
?>

__call

С PHP5 вы можете реализовать в классе специальный метод __call(), как метод для «отлова» всех нереализованных в данном классе методов. Метод __call (если он определён) вызывается при попытке вызвать недоступный или несуществующий метод.

Пример: __call
<?php
class foo {

  function __call($name,$arguments) {
    print("Вызывали? Я -  $name!");
  }
}

$x = new foo();
$x->doStuff();
$x->fancy_stuff();
?>

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

Пример: Перегрузка методов с помощью __call
<?php
class Magic {

  function __call($name,$arguments) {
    if($name=='foo') {
      if(is_int($arguments[0])) $this->foo_for_int($arguments[0]);
      if(is_string($arguments[0])) $this->foo_for_string($arguments[0]);
    }
  }

  private function foo_for_int($x) {
    print("у, смотрите, целое число!");
  }

  private function foo_for_string($x) {
    print("у, смотрите, строка!");
  }
}

$x = new Magic();
$x->foo(3);
$x->foo("3");
?>

__set и __get


Но это ещё не всё, теперь вы можете определить методы __set и __get для «отлова» всех попыток изменения или доступа к неопределённым (или недоступным) переменным.

Пример: __set и __get
<?php
class foo {

  function __set($name,$val) {
    print("Привет, вы попытались присвоить значение $val переменной $name");
  }

  function __get($name) {
    print("Привет, вы пытались обратиться к $name");
  }
}

$x = new foo();
$x->bar = 3;
print($x->winky_winky);
?>

В PHP5 вы сможете «сказать» методу, что он должен получить в качестве аргумента объект определённого типа.

Пример: указание типов
<?php
class foo {
  // код ...
}

class bar {
  public function process_a_foo(foo $foo) {
   // Ещё какой-нибудь код
  }
}

$b = new bar();
$f = new foo();
$b->process_a_foo($f);
?>

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

Продолжение:
http://php5.com.ua/blog/php-programming/146.html
2

PHP программирование →  Переход от php4 к php5 (Дескрипторы Private, Public и Protected. Интерфейсы)

Начало здесь: http://php5.com.ua/blog/php-programming/133.html

Дескрипторы Private, Public и Protected


В PHP4 все методы и переменные внутри объекта были доступны извне, другими словами все методы и переменные всегда были открытыми. В PHP5 вводится три дескриптора для осуществления контроля над доступом к переменным и методам: Public, Protected и Private.

* Public (открытый): Метод/переменная доступны из любого места в коде.
* Private (закрытый): Закрытые методы или переменные доступны только внутри класса.
* Protected (защищённый): Защищённые методы или переменные доступны только внутри класса, где они были объявлены и из его производных классов.

Пример: Public, protected and private

<?php
class foo {
  private $x;

  public function public_foo() {
    print("Это открытый метод");
  }

  protected function protected_foo() {
    $this->private_foo(); //Всё правильно, мы можем вызывать закрытые методы, потому что мы находимся в том же классе
    print("Это защищённый метод");
  }

  private function private_foo() {
    $this->x = 3;
    print("Это закрытый метод");
  }
}

class foo2 extends foo {
  public function display() {
    $this->protected_foo();
    $this->public_foo();
    // $this->private_foo();  // Неправильно! В базовом классе метод закрыт
  }
}

$x = new foo();
$x->public_foo();
//$x->protected_foo();  //Неправильно, защищённые методы могут вызываться только из того же класса или
//его производных классов
//$x->private_foo();    //Неправильно, закрытые методы могут быть вызваны только в классе, где они были объявлены

$x2 = new foo2();
$x2->display();
?>


Совет разработчикам: Переменные класса всегда следует делать закрытыми, прямой доступ к переменным — не очень хорошая практика в ООП, лучше всего для доступа/изменения переменных класса определять специальные методы.

Интерфейсы



Как вы знаете, PHP4 поддерживает наследование классов синтаксисом «class foo extends parent». В PHP4 И в PHP5 класс может наследовать только один класс, то есть множественное наследование не поддерживается. Интерфейсом называется класс, в котором не реализуется ни один метод, определяются только названия методов и набор передаваемых им параметров. Впоследствии классы могут 'реализовывать' сколь угодно много интерфейсов, показывая тем самым, что тот или иной класс реализует методы, определённые в интерфейсе.

Пример: Интерфейсы

<?php
interface displayable {
  function display();
}

interface printable {
  function doprint();
}

class foo implements displayable,printable {
  function display() {
    // код
  }

  function doprint() {
    // код
  }
}
?>


Использование интерфейсов полезно для более удобного чтения и понимания кода: прочитав объявление класса, мы увидим, что класс реализует интерфейсы displayable и printable; это означает, что класс должен иметь методы display() и doprint(). Как эти методы реализованы — значения не имеет, главное — уже из объявления класса, вы знаете, что можете вызывать эти методы.

Продолжение:
http://php5.com.ua/blog/php-programming/135.html
http://php5.com.ua/blog/php-programming/146.html
2

PHP программирование →  Переход от php4 к php5

Переход к PHP5


Краткий обзор возможностей PHP по материалам PHP 5 beta 3.
PHP, фактически, является самым распостраненным языком для Web программирования. В достижении этого статуса он прошел множество этапов, от простого языка для Web программирования который уступал многим (php3), до сегодняшнего быстрого мощного и расширяемого (PHP4). Тем более приятно, что PHP не стоит на месте и продолжает развиваться оставаясь таким-же простым для начинающих и предоставляя все больше возможностей более квалифицированным разработчикам.

Введение

PHP, фактически, является самым распостраненным языком для Web программирования. В достижении этого статуса он прошел множество этапов, от простого языка для Web программирования который уступал многим (php3), до сегодняшнего быстрого мощного и расширяемого (PHP4). Тем более приятно, что PHP не стоит на месте и продолжает развиваться оставаясь таким-же простым для начинающих и предоставляя все больше возможностей более квалифицированным разработчикам. В предверьи выхода PHP5 появляется множество информации о улучшениях в PHP 5, включая информацию от самих разработчиков. Например, замечательная статья от одного из авторов Zend Engine — Zeev Suraski (http://phpclub.ru/detail/article/2004-01-07) и её перевод на phpclub.ru очень помогут в понимании тонкостей изменения работы с объектами. Существуют, конечно, и общие обзоры возможностей PHP5, сделанные как отечественными так и зарубежными авторами. В своем обзоре я попытался дать наиболее полное представление о изменениях в PHP5, на сколько это возможно. Эта статья также является в некотором роде «отчетом о проделанной работе», поскольку обзор каждого изменения собровождался детальным его изучением и попыткой использовать на практике.

На этом заканчиваем введение и приступаем к основной части.

Новые уровни доступа private и public

В PHP5 добавлены новые модификаторы уровня доступа для переменных классов. Как и во многих других языках программирования, они носят названия private, protected и public.

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

Protected — расширение области private, добавляющее к ней возможность обращаться к переменной из классов-потомков.

Public — расширяющий protected модификатор, задающий наиболее широкую область доступа. К возможности использовать переменную в классах-потомках, добавляется возможность обращаться к переменной непосредственно из другого кода. Строго говоря, public не является новой областью доступа. Ранее в PHP все переменные классов являлись public переменными.

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

Аналогично, private/protected/public мидификаторы применяются к методам класса. Методы, объявленные без модификатора, являются public методами.

Если метод или переменная переопределяются в классе-наследнике, то уровень доступа должен быть таким-же или выше. Например, protected метод в классе-потомке можно сделать public, но нельзя private.

Для примера рассмотрим классы NewClass и NewClass1.

class NewClass {
// new PHP5 modifiers
private $myPrivateVar = 'myPrivateVar';
protected $myProtectedVar = 'myProtectedVar';
public $myPublicVar = 'myPublicVar';
// old PHP declaration
var $myVar = 'myVar';
}

class NewClass1 extends NewClass {
function getProtectedVar() {
return $this->myProtectedVar;
}
}


NewClass содержит несколько переменных с разными областями доступа. NewClass1 используется для тестирования областей видимости, связанных с наследованием.

Создаем объекты классов:

$c = new NewClass();
$c1 = new NewClass1();


Обращаемся к переменным:
print $c->myPrivateVar;

Непосредственное обращение к private переменной приводит к ошибке.
print $c->myProtectedVar;

Непосредственное обращение к protected переменной приводит к ошибке.
print $c->myPublicVar;

Обращение к public переменной возвращает её значение.
print $c->myVar;

Обращение к переменной, объявленной в старом стиле, равносильно обращению к public переменной.
print $c1->myPrivateVar;

Private переменная не была унаследованна классом NewClass1. Обращение к ней равнозначно обращению к необъявленной переменной.
print $c1->myProtectedVar;

Protected переменная была унаследованна и непосредственное обращение к ней приводит к ошибке. Для проверки, что она была унаследованна вместе с начальным значением, можно вызвать «print $c1->getProtectedVar();».
print $c1->myPublicVar;
Public переменная была унаследованна и обращение к ней возвращает её значение.

Продолжение:
http://php5.com.ua/blog/php-programming/134.html
http://php5.com.ua/blog/php-programming/135.html
http://php5.com.ua/blog/php-programming/146.html
2

PHP программирование →  Кто поедет из Киева на конфу по php в Москве?

8-9 октября 2009 г. в Москве пройдет 8-я международная конференция PHPCONF 2009.

Я бы съездил.

Подробнее здесь: http://www.phpconf.ru/
3

PHP программирование →  Парсим линки на PHP

Такое всегда должно быть под рукой:
$url = "http://artlebedev.kiev.ua/";
$input = @file_get_contents($url) or die('Could not access file: ' . $url);
$regexp = "<a\s[^>]*href=(\"??)([^\" >]*?)\\1[^>]*>(.*)<\/a>";
if(preg_match_all("/$regexp/siU", $input, $matches)) {
   foreach($matches as $match) {
      # $match[2] = link address
      # $match[3] = link text
   }
}


have fun:)
1

PHP программирование →  Хранение иерархических данных в БД

Модифицированный прямой обход дерева.


Рассмотрим один из методов хранения деревьев. Как правило деревья приходится доставать рекурсивно, что может быть медленно, поэтому рассматривать этот метод не будем. Очень хотелось бы свести к миниму количество запросов к БД, а в идеале к одному запросу:)

Пройдем по нашему дереву горизонтально. Начнем с корня ('Food') и допишем 1 слева. Следующий узел 'Fruit', напишем рядом 2. Таким образом, мы будем ходить вдоль краев дерева и дописывать числа слева и справа каждого узла. Последним, будет номер, справа узла 'Food'. Ниже можно посмотреть на наше пронумерованное дерево со стрелками, указывающими направление обхода.



Мы назовем эти цифры левой и правой (например, левое значение 'Food' — 1, правое — 18). Как видите, эти цифры определяют связь между узлами дерева. Посколькоу 'Red' имеет цифры 3 и 6, он является потомком вершины 1-18 'Food'. В то же время, мы можем сказать, что все вершины у которых левые значения больше 2, а правые меньше 11 являются потомками 2-11 'Fruit'. Таким образом, структура дерева хранится в в левом и правом значениях вершины. Этот метод кругового обхода дерева и подсчета вершин называется 'модифицированный прямой обход дерева'.

Прежде чем продолжить, давайте посмотрим, как это будет храниться у нас в БД:


Слова 'left' и 'right' являются зарезервированными в MySql, поэтому для обозначения столбцов в таблице стоит выбрать другие имена, например, 'lft' и 'rgt' или брать в обратные кавычки. Так же, стоит обратить внимание на то, что нам больше не нужен столбец 'parent'. У нас имеются lft и rgt значения для хранения древовидной структуры.

Получение дерева



Если нам необходимо получить дерево, использующее таблицу с левыми и правыми значениями, то нам для начала нужно будет определиться с узлами, которые нам необходимы. Например, если нам нужен узел 'Fruit' со всеми своими детьми, нам будет достаточно выбрать записи с левыми значениями от 2 до 11.

В таком случае SQL запрос может выглядеть так:
SELECT * FROM tree WHERE lft BETWEEN 2 AND 11;

В результате мы получим:


Все дерево одним запросом. Для того что бы отобразить дерево упорядоченным, как делала это рекурсивная функция добавим в запрос ORDER BY. Если добавлять и удалять записи в таблице, то их порядок нарушится. Поэтому зададим сортировку по левым значениям.

SELECT * FROM tree WHERE lft BETWEEN 2 AND 11 ORDER BY lft ASC;


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

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

You know that all children of that node have a right value that is less than the right value of the parent, so by comparing the right value of the current node with the last right node in the stack, you can see if you're still displaying the children of that parent. Вы знаете, что все дети, что узел имеет право ценность, которая является меньше, чем стоимость права родителей, так что, сравнив права значение текущего узла с последним право узла в стек, можно увидеть, если вы все еще выводить детей этого родителя.

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

<?php
function display_tree($root) {
   // retrieve the left and right value of the $root node
   $result = mysql_query('SELECT lft, rgt FROM tree '.
                          'WHERE title="'.$root.'";');
   $row = mysql_fetch_array($result);

   // start with an empty $right stack
   $right = array();

   // now, retrieve all descendants of the $root node
   $result = mysql_query('SELECT title, lft, rgt FROM tree '.
                          'WHERE lft BETWEEN '.$row['lft'].' AND '.
                          $row['rgt'].' ORDER BY lft ASC;');

   // display each row
   while ($row = mysql_fetch_array($result)) {
       // only check stack if there is one
       if (count($right)>0) {
           // check if we should remove a node from the stack
           while ($right[count($right)-1]<$row['rgt']) {
               array_pop($right);
           }
       }

       // display indented node title
       echo str_repeat('  ',count($right)).$row['title']."\n";

       // add this node to the stack
       $right[] = $row['rgt'];
   }
}
?>


Если запустить этот код, то получим дерево, которое мы получали раньше при помощи рекурсии. Функция получилась на много проще, как если бы писалась рекурсивно и использует только 2 запроса для построения дерева.

Путь к узлу


С этим новым алгоритмом, мы также должны найти новые пути, чтобы получить путь к определенному узлу. Чтобы получить этот путь, нам понадобится список всех предков этого узла. С нашей новой структурой таблицы работы будет не так и много. Если посмотреть, например, на узел 4-5 'Cherry', можно увидеть, что все левые значения предков меньше 4, а все правые — больше 5.

Чтобы получить всех предков, построим следующий запрос:

SELECT title FROM tree WHERE lft < 4 AND rgt > 5 ORDER BY lft ASC;


Как и в предыдущем запросе, мы должны использовать ORDER BY для сортировки узлов.
Запрос вернет:

+-------+
| title |
+-------+
| Food  |
| Fruit |
| Red   |
+-------+


Сейчас мы только объединили записи для получения пути к 'Cherry'.

Подсчет потомков



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

Каждый потомок инкрементирует правое значение узла начиная с 2, тогда количество потомков расчитывается по формуле:

$descendants = ($right$left - 1) / 2;


Исходя из этой простой формулы можно сказать, что 2-11 'Fruit' имеет 4 потомка и что 8-9 'Banana' просто чаилд и не родитель.
1

PHP программирование →  Оптимизируем расположение контента

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

Следующие функции решают эту это проблему:


/**
* Get path for image by ID
* Returns path like /1/2/12 when id = 12
*
* @param int $id
*/

if ( ! function_exists('getPathById')) {
        function getPathById($id) {
                $f1 = $id % 10;
                $f2 = floor(($id % 100) / 10);
                $path = '/' . $f1 . '/' . $f2 . '/' . $id;
                return $path;
        }
}

if ( ! function_exists('makeDirsForID')) {
        function makeDirsForID($id, $path) {
                $f1 = $id % 10;
                if (!file_exists($path . '/' . $f1)) {
                        @mkdir($path . '/' . $f1);
                }
                $f2 = floor(($id % 100) / 10);
                if (!file_exists($path . '/' . $f1 . '/' . $f2)) {
                                @mkdir($path . '/' . $f1 . '/' . $f2);
                }
        }
}

Надеюсь, все понятно и помогло:)
1
←  сюда    туда  →
1 2