Магия PHP

David: Magic OOP

Ага, вот эти ребята, сейчас я покажу Вам настоящую магию из мира PHP.

Вместо предисловия. Об авторах языка

Точнее о траве которую курили разработчики, ну как так можно именовать функции? Ну возьмем для примера функции для работы со строками:

  • str_replace( ищем строку $search, заменяем на $replace, в строке $subject [, итого поменяли &$count ] )
  • strpos( в строке $haystack , ищем $needle [, пропускаем $offset символов] )
  • substr_replace( в строке $string , заменям на $replacement , с позиции $start [, $length ])
  • nl2br( изменяем строку $string [, это $is_xhtml ] )

Как мы видим это очень мрачно, а если брать массивы – в одном месте у нас функция возвращает результат, в другом – работает по ссылке… брр…

Благодаря отсутвию стандартов даже в самом языке, мы имеем некий дискомфорт при работе с данным языком. Да и другие косятся…

PHP это неправильный язык программирования

Эту сказку я частенько слышу. Решил я написать какой-то такой наглядный код, чтобы сразу было понятно, PHP — это ого-го-го :)

Решил, и написал – на Ruby пару классов, которые будут представлять из себя обертку для строк и масивов. Данные классы включают в себя лишь часто используемые функции (по моему скромному мнению), а вызов остальных возложил на рефлексию.

Массив – oArray

Данный класс включает в себя стандартные функции.

 » Перечень функций

  • array_diff — Вычислить расхождение в массивах
  • array_fill — Заполнить массив определенным значением
  • array_filter — Применяет фильтр к массиву, используя функцию обратного вызова
  • array_flip — Поменять местами значения массива
  • array_key_exists — Проверить, присутствует ли в массиве указанный ключ или индекс
  • array_keys — Выбрать все ключи массива
  • array_map — Применить функцию обратного вызова ко всем элементам указанных массивов
  • array_pop — Извлечь последний элемент массива
  • array_product — Вычислить произведение значений массива
  • array_push — Добавить один или несколько элеметов в конец массива
  • array_rand — Выбрать одно или несколько случайных значений из массива
  • array_reverse — Возвращает массив с элементами в обратном порядке
  • array_search — Осуществляет поиск данного значения в массиве и возвращает соответствующий ключ в случае удачи
  • array_shift — Извлечь первый элемент массива
  • array_slice — Выбрать срез массива
  • array_splice — Удалить последовательность элементов массива и заменить её другой последовательностью
  • array_sum — Вычислить сумму значений массива
  • array_unique — Убрать повторяющиеся значения из массива
  • array_unshift — Добавить один или несколько элементов в начало массива
  • array_values — Выбрать все значения массива
  • sort — Отсортировать массив
  • rsort — Отсортировать массив в обратном порядке
  • natsort — Отсортировать массив, используя алгоритм “natural order”
  • natcasesort — Отсортировать массив, используя алгоритм “natural order” не принимая во внимание регистр символов
  • ksort — Отсортировать массив по ключам
  • krsort — Отсортировать массив по ключам в обратном порядке
  • implode — Объединяет элементы массива в строку

А так же немного полезной отсебячины:

  • to_url — Обертка для http_build_query
  • clear — Убрать пустые элементы массива
  • odd — Оставить лишь нечетные элементы
  • even — Оставить лишь четные элементы
  • size — Врапер для функции sizeof

Для всех функций вида array_* сей префикс я убрал (ведь мы и так знаем, что работает с массивом), остальный функции – на совести метода __call и рефлексии.

Строка – oString

Данный класс включает в себя стандартные функции.

 » Перечень функций

  • addslashes — Экранирует спецсимволы в строке
  • count_chars — Возвращает информацию о символах, входящих в строку
  • crc32 — Вычисляет CRC32 для строки
  • crypt — Необратимое шифрование (хэширование)
  • explode — Разбивает строку на подстроки
  • html_entity_decode — Преобразует HTML сущности в соответствующие символы
  • htmlentities — Преобразует символы в соответствующие HTML сущности
  • htmlspecialchars_decode — Преобразует специальные HTML-сущности обратно в соответствующие символы
  • htmlspecialchars — Преобразует специальные символы в HTML сущности
  • ltrim — Удаляет пробелы из начала строки
  • md5 — Возвращает MD5 хэш строки
  • money_format — Форматирует число как денежную величину
  • nl2br — Вставляет HTML код разрыва строки перед каждым переводом строки
  • number_format — Форматирует число с разделением групп
  • parse_str — Разбирает строку в переменные
  • rtrim — Удаляет пробелы из конца строки
  • sha1 — Возвращает SHA1 хэш строки
  • sprintf — Возвращает отформатированную строку
  • str_pad — Дополняет строку другой строкой до заданной длины
  • str_repeat — Возвращает повторяющуюся строку
  • str_replace — Заменяет строку поиска на строку замены
  • str_ireplace — Регистро-независимый вариант функции str_replace()
  • str_word_count — Возвращает информацию о словах, входящих в строку
  • strip_tags — Удаляет HTML и PHP тэги из строки
  • stripslashes — Удаляет экранирование символов, произведенное функцией addslashes()
  • strstr — Находит первое вхождение подстроки
  • stristr — Регистро-независимый вариант функции strstr()
  • strpos — Возвращает позицию первого вхождения подстроки
  • stripos — Возвращает позицию первого вхождения подстроки без учета регистра
  • strrpos — Возвращает позицию последнего вхождения символа
  • strripos — Возвращает позицию последнего вхождения подстроки без учета регистра
  • strrev — Переворачивает строку
  • strtolower — Преобразует строку в нижний регистр
  • strtoupper — Преобразует строку в верхний регистр
  • substr_count — Возвращает число вхождений подстроки
  • substr_replace — Заменяет часть строки
  • substr — Возвращает подстроку
  • trim — Удаляет пробелы из начала и конца строки
  • ucfirst — Преобразует первый символ строки в верхний регистр
  • ucwords — Преобразует в верхний регистр первый символ каждого слова в строке
  • wordwrap — Выполняет перенос строки на данное количество символов с использованием символа разрыва строки

А так же немного полезной отсебячины:

  • add — Конкатенация строк
  • insert — Вставка строки в строку
  • size — Врапер для функции strlen

Для всех функций вида str_* и str* сей префикс был убран.

Так же выделил функции для работы с URL – и запихнул их в отдельный класс (oUrl):

  • parse_url
  • urlencode
  • urldecode

Слайды

Теперь приведу пример использования сего творения:

oArray()                   // создаем пустой массив
        ->range(0,100,10)  // врапер для  range
        ->size()           // врапер для  sizeof
        ;

Как Вам? Даю еще пищу для мозга:

oArray('module', 'controller', 'action')                // создаем массив из элементов                      =>  array('module', 'controller', 'action') 
        ->combine(oArray('default', 'index', 'index'))  // врапер для  array_combine                        =>  array('module'=>'default', 'controller'=>'index', 'action'=>'index') 
        ->to_url()                                      // врапер для   http_build_query возвращает oUrl    =>  module=default&controller=index&action=index
        ->insert('http://domain.com/?')                 // добавляем кусочек строки в начало              =>  http://domain.com/?module=default&controller=index&action=index
        ->parse()                                       // врапер для  parse_url возвращает oArray
        ->host                                          // возвращает array['host']                                   =>  domain.com
        ;

И еще:

oString("It's my way")
        ->replace('my','your')    // str_replace        => "It's your way"
        ->sub(0,  8)              // substr             => "It's you"
        ->pad(11, '.')            // str_pad            => "It's you..."
        ->repeat(2)               // str_repeat         => "It's you...It's you..."
        ->explode('...')          // получаем oArray => array('It's you','It's you', '')
        ->clear()                 // удаляем пустые элементы
        ->merge(array('Yes','No'), array('Maybe'))  // array_merge => array('It's you','It's you', 'Yes','No','Maybe')
        ->implode(';')            // => It's you;It's you;Yes;No;Maybe
        ->get()                   // => 
        ;

Объект – oObject

Даже обычный класс можно улучшить – добавив ему хитрые гетеры/сетеры для свойств объекта (я это подсмотрел в RoR):

class MyClass extends Object_Object {
    // это действительно protected свойство
    protected $_protected;
    
    // для данных полей можно определить гетеры/сетеры
    protected $title;
    protected $description;
    
    // public свойство без гетеров/сетеров
    public    $data;
    
    /**
     * Сеттер для свойства title
     *
     * @param string $value
     * @return mixed
     */
    function setTitle($value) {
        $this->title = ucfirst($value);
    }
    
    /**
     * Геттер для свойства title
     *
     * @return mixed
     */
    function getTitle() {
        return $this->title . '!!!';
    }
}

$MyClass = new MyClass();
$MyClass -> title = 'article title';

echo $MyClass -> title;

В результате сей махинации мы получим следующий результат:

Article title!!!

Как видим – подобный класс даже имеет право на существование ;)

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

Downloadlast versionoObject

Заключение

P.S. Данные классы не претендуют на жизнь в реальных проектах, они предназначены дабы развеять миф о каком-то неправильном PHP, а так же послужат неплохим материалом для изучения начинающими программистами…

10 thoughts on “Магия PHP”

  1. убери словосочетание “магия ООП” везде, где ты его употребляешь, т.к. это магия, но вовсе не ООП, а рефлексии.

  2. В классе MyClass перемешаны стили объявления protected переменных.
    Думаю в общем из этих классов будут использованы не более 5-8 функций, остальные очень редко. И легче все таки вызвать одну функцию str_len чем, создавать объект класса для ее вызова, так и быстрее и надежней и более независимо от наличия данного класса в проекте. Минус, надо будет всей команде переучиться на использование данного класса.
    Я бы выкинул из этого класса все функции, которые не используются и переименовал класс, в что то более относящееся к предметной области и задачи.

  3. В ПХП действительно отсутствует дизайн языка…. и это сильно удручает… никакой системы в именовании функций.
    Интересная РУБИфикация получилась… но себя все равно не обманешь. Большинство вкусностей руби в пхп не реализуемы.

  4. class MyClass extends Object_Object {
      public function __call($name, array $args) {
        И тут парсим метод и protected свойство дочернего класса
      }
    }
  5. Брррр а зачем тогда определены методы setTitle?

  6. @korzhik:
    Это конкретная реализация гетера/сетера для поля title, т.к. в PHP нет реализации гетера/сетера для конкретного поля, то я сделал этот функционал в классе Object_Object…

  7. То что никаких обёрточных классов не нужно, это совершенно очевидный факт, но всё же
    непонятно, чем конкретно “плохи” названия функций, зачем их переименовывать?

  8. мне кажется дело не в названиях, а в путанице аргументов, сам не раз прибегаю к мануалу..
    Сделали бы везде – функция(ЧТО, ОТКУДА, …), а довольно часто бывает (ОТКУДА, ЧТО, …) в этом и путаница

Comments are closed.