Анемичный group php. Entity “фреймворк” для PHP из одного класса

Если вы занимались разработкой PHP последние несколько лет, то наверняка знаете о проблемах этого языка. Зачастую можно услышать, что это фрагментированный язык, инструмент для взломов, что он не имеет настоящей спецификации и т.д. Реальность же такова, что PHP сильно «вырос» в последнее время. Версия PHP 5.4 приблизила его к полной объектной модели и предоставила много новой функциональности.

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

Что такое PHP-FIG

PHP-FIG (PHP Framework Interop Group) - организованная группа разработчиков, цель которой находить способы совместной работы нескольких фрейморков.

Только представьте: сейчас вы поддерживаете проект на Zend Framework, которому понадобился модуль корзины магазина. Вы уже писали такой модуль для предыдущего проекта, который был на Symphony. Не делать же его снова? К счастью и ZendF и Symphony являются частью PHP-FIG, так что можно импортировать модуль с одного фреймворка в другой. Разве не здорово?

Давайте узнаем, какие фреймворки входят в PHP-FIG

Участники PHP-FIG

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

Текущие участники:

Что такое PSR?

PSR (PHP Standarts Recomendations) - стандартные рекомендации, результат работы PHP-FIG. Одни члены Группы предлагают правила для каждого PSR, другие голосуют в поддержку этих правил или за их отмену. Обсуждение проходит в Google Groups, а наборы PSR доступны на официальном сайте PHP-FIG.

Давайте рассмотрим некоторые PSR:

Первый шаг на пути объединения фреймворков - наличие общей структуры директорий, поэтому и был принят общий стандарт автозагрузки.

  1. Пространство имен (namespace) и класс должны иметь структуру \\(\)*.
  2. Каждое пространство имен должно содержать пространство верхнего уровня («Vendor Name»).
  3. Каждое пространство имен может иметь сколько угодно уровней.
  4. Каждый разделитель пространства имен конвертируется в DIRECTORY_SEPARATOR при загрузке.
  5. Каждый символ «_» в CLASS NAME конвертируется в DIRECTORY_SEPARATOR.
  6. К полностью определённому пространству имен и классу добавляется «.php» при загрузке.

Пример функции автозагрузки:

PSR-1 - Basic Coding Standart

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

  1. В файлах должны использоваться только теги
  2. В файлах должна использоваться только кодировка UTF-8 without BOM.
  3. Имена пространств и классы должны следовать PSR-0.
  4. Имена классов должны быть объявлены в нотации StudlyCaps.
  5. Константы класса должны быть объявлены в верхнем регистре, разделенные подчеркиваниями.
  6. Методы должны быть объявлены в нотации camelCase.

PSR-2 - Coding Style Guide

Это расширенные инструкции для PSR-1, описывающие правила форматирования кода.

  1. Код должен соответствовать PSR-1.
  2. Вместо табуляции должны использоваться 4 пробела.
  3. Не должно быть строгого ограничения на длину строки, рекомендуемая длина - до 80 символов.
  4. Должна быть одна пустая строка после объявления пространства имен.
  5. Скобки для классов должны открываться на следующей строке после объявления и закрываться после тела класса (то же самое для методов).
  6. Видимость методов и свойств должна быть обязательно определена (public, private).
  7. Открывающие скобки для управляющих структур должны находиться на той же строке, закрывающие скобки должны быть на следующей строке после тела структуры.
  8. Пробелы не ставятся после открывающихся круглых скобок методов управляющих структур и перед закрывающимися скобками.

PCR-3 - Logger Interface

В PCR-3 регулируется логгинг, в частности основные девять методов.

  1. LoggerInterface предоставляет 8 методов для логирования восьми RFC 5424 уровней (debug, notice, warning, error, critical, alert, emergency).
  2. Девятый метод log() принимает на вход уровень предупреждения первым параметром. Вызов метода с параметром уровня предупреждения должен возвращать такой же результат, как и вызов метода определенного уровня лога (log(ALERT) == alert()). Вызов метода с неопределённым уровнем предупреждения должен генерировать Psr\Log\InvalidArgumentException.

Так же как и PSR-0, PSR-4 предоставляет улучшенные методы автозагрузки

  1. Термин «класс» относится к классам, интерфейсам, трейтам и другим похожим структурам
  2. Полностью определённое имя класса имеет следующую форму: \(\)*\
  3. При загрузке файла, соответствующему полностью определённому имени класса:
  • Непрерывная серия одного или более ведущих пространств имен, не считая ведущего разделителя пространства имен, в полностью определенном имени класса соответствует по крайней мере одной «корневой директории».
  • Имена директорий и поддиректорий должны соответствовать регистру пространства имен.
  • Окончание полного имени класса соответствует имени файла с окончанием.php. Регистр имени файла обязан соответствовать регистру окончания полного имени класса.
  • Реализация автозагрузчика не должна бросать исключения, генерировать ошибки любого уровня и не обязана возвращать значение.

Заключение

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

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

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

В 2009 году разработчики нескольких фреймворков договорились о создании сообщества PHP Framework Interop Group (PHP-FIG) , которое бы вырабатывало рекомендации для разработчиков. Важно подчеркнуть, что речь не идет о ISO-стандартах , более правильно говорить о рекомендациях. Но так как создавшие PHP-FIG сообщество разработчики представляют крупные фреймворки, то их рекомендации представляют серьёзный вес. Поддержка PSR (PHP standart recommendation) стандартов позволяет обеспечивать совместимость, что облегчает и ускоряет разработку конечного продукта.

Всего на момент написания статьи существует 17 стандартов, причем 9 из них являются утвержденными, 8 находятся в стадии проекта, активно обсуждаются, 1 стандарт не рекомендован к использованию.

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

PSR-1. Основной стандарт кодирования

Он представляет собой наиболее общие правила, такие как, например, использование тегов PHP , кодировка файлов, разделения места объявления функции, класса и места их использования, именование классов, методов.

PSR-2. Руководство по стилю кода

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

PSR-3. Интерфейс протоколирования.

Этот стандарт разработан для того, чтобы обеспечить (журналирование) логирование в приложениях, написанных на PHP .

PSR-4. Стандарт автозагрузки

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

PSR-6. Интерфейс кеширования

Кэширование используется для повышения производительности системы. И PSR-6 позволяет стандартно сохранять и извлекать данные из кэша, используя унифицированный интерфейс.

PSR-7. Интерфейс HTTP-сообщений

При написании мало-мальски сложных сайтов на PHP , почти всегда приходиться работать с HTTP заголовками . Конечно, язык PHP предоставляет нам уже готовые возможности для работы с ними, такие как суперглобальный массив $_SERVER , функции header() , setcookie() и т.д., однако их ручной разбор чреват ошибками, да и не всегда можно учесть все нюансы работы с ними. И вот, чтобы облегчить работу разработчику, а также сделать единообразным интерфейс взаимодействия с HTTP протоколом был принят данный стандарт. Более подробно об этом стандарте я расскажу в одной из следующих статей.

PSR-11. Интерфейс контейнера

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

PSR-13. Гипермедиа ссылки

Данный интерфейс призван облегчить разработку и использование прикладных программных интерфейсов (API ).

PSR-14. Интерфейс простого кэширования

Является продолжением и улучшением стандарта PSR-6

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

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

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

Перейдем к конкретной «ходовой» задаче - объектная прослойка для работы с базами данных в PHP. Решений великое множество, начиная от PDO и заканчивая многоуровневыми (и, на мой взгляд, не совсем уместными в PHP) ORM движками.

Большинство этих решений перекочевали в PHP из других платформ. Но зачастую авторы не учитывают особенности PHP, которые позволили бы резко упростить как написание, так и использование портируемых конструкций.
Одной из распространенных архитектур для данного класса задач является паттерн Active Record. В частности, по этому шаблону строятся так называемые Entity (сущности), в том или ином виде использующиеся в ряде платформ, начиная от персистентных бинов в EJB3 заканчивая EF в.NET.

Итак, построим подобную конструкцию для PHP. Соединим между собой две клёвые штуки - готовую библиотеку ADODB и слаботипизированность и динамические свойства объектов языка PHP.
Одной из многочисленных фич ADODB является так называемая автогенерация SQL запросов для вставки (INSERT) и обновления (UPDATE) записей на основе ассоциативных массивов с данными.
Собственно нет ничего военного взять массив, где ключи - имена полей а значения - соответственно, данные и сгенерировать строку SQL запроса. Но ADODB делает это более интеллектуально. Запрос строится на основе структуры таблицы, которая предварительно считывается с схемы БД. В результате во-первых, в sql попадают только существующие поля а не всё подряд, во-вторых, учитывается тип поля - для строк добавляются кавычки, форматы дат могут формироваться на основе timestamp если ADODB видит оный вместо строки в передаваемом значении и т.д.

Теперь зайдем со стороны PHP.
Представим такой класс (упрощенно).

Class Entity{ protected $fields = array(); public final function __set($name, $value) { $this->fields[$name] = $value; } public final function __get($name) { return $this->fields[$name]; } }

Передавая внутренний массив библиотеке ADODB мы можем автоматически генерировать SQL запросы для обновления записи в БД данным объектом, При этом, не нужны громоздкие конструкции маппинга полей таблиц БД на поля объекта сущности на основе XML и тому подобного. Нужно только чтобы имя поля совпадало со свойством объекта. Поскольку то, как именуются поля в БД и поля объекта, для компьютера значения не имеет, то нет никаких причин чтобы они не совпадали.

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

Представим, что у нас такая табличка:

CREATE TABLE `users` (`username` varchar(255) , `created` date , `user_id` int(11) NOT NULL AUTO_INCREMENT, PRIMARY KEY (`user_id`))
Тип БД не имеет значения - ADODB обеспечивает переносимость для всех распространенных серверов БД.

Создадим класс сущности Пользователь, на основе класса Entity

/** * @table=users * @keyfield=user_id */ class User extends Entity{ }

Собственно и все.
Используется просто:

$user = new User(); $user->username="Вася Пупкин"; $user->created=time(); $user->save(); //сохраняем в хранилище // загрузим опять $thesameuser = User::load($user->user_id); echo $thesameuser ->username;

Таблицу и ключевое поле указываем в псевдоаннотациях.
Также можем указать представление (к примеру, view =usersview) если, как это часто бывает, сущность выбирается на основе своей таблицы с приджойнеными или вычисляемыми полями. В этом случае выбираться данные будут из представления а обновляться будет таблица. Кому не нравятся такие аннотации могут переопределить метод getMetatada() и указать параметры таблицы в возвращаемом массиве.

Что еще полезного представляет класс Entity в данной реализации?

Например, мы можем переопределить метод init(), который вызывается после создания экземпляра Entity, чтобы инициализировать дату создания по умолчанию.
Или перегрузить метод afterLoad(), который автоматически вызывается после загрузки сущности из БД, чтобы преобразовать дату в timestamp для дальнейшего более удобного использования.
В результате получим не намного более сложную конструкцию.

/** * @table=users * @view=usersview * @keyfield=user_id */ class User extends Entity{ protected function init() { $this->created = time(); } protected function afterLoad() { $this->created = strtotime($this->created); } }

Также можно перегрузить методы beforeSave и beforeDelete и другие события жизненного цикла где можно, например, выполнить валидацию перед сохранением или какие нибудь другие действия - например, убрать за собой картинки из аплоада при удалении пользователя.

Загружаем список сущностей по критерию (по сути условия для WHERE).
$users = User::load("username like "Пупкин" ");
Также класс Entity позволяет выполнить произвольный, «нативный» так сказать SQL запрос. Например, мы хотим вернуть список пользователей с какими нибудь группировками по статистике. Какие конкретно поля вернутся, не имеет значения (главное чтобы там было user_id, если есть необходимость дальнейшей манипуляции сущностью), нужно только знать их наименования чтобы обратится к выбранным полям. При сохранении сущности, как очевидно из вышеприведенного, тоже не надо заполнять все поля, какие будут присутствовать в объекте сущности, те и пойдут в БД. То есть нам не нужно создавать дополнительные классы для произвольных выборок. Примерно как анонимные структуры при выборке в EF только здесь это тот же класс сущности со всеми методами бизнес-логики.

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

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

Кому это может быть полезно? Разумеется, не прокачанным разрабам, которые считают что использование чего то проще доктрины - не солидно, и не перфекционистам, уверенным, что если решение не вытягивает миллиард обращений к Бд в секунду то это не решение. Судя по форумам, перед многими обычными разработчиками, работающими над обычными (коих 99.9%) проектами рано или поздно возникает проблема найти простой и удобный объектный способ для доступа к БД. Но сталкиваются с тем, что большинство решений либо неоправданно наворочены, либо являются частью какого-либо фреймворка.

P.S. Вынес решение из фреймворка отдельным проектом

PHP в полной мере можно назвать «народным языком веб-программирования», очень сложно найти другой такой язык, который бы мог на равных соперничать с ним по уровню своей популярности. Я решил поближе узнать людей стоящих за его разработкой, ответить на острые вопросы, обсудить последние новинки, и даже попробовать заглянуть в будущее Интернета. Для этого мы встретились с легендарными участниками PHP Core Team , которые непосредственно курируют разработку этого языка и заслужили репутацию признанных мировых экспертов в области веб-технологий.

Итак, сегодня на мои вопросы отвечают ведущие разработчики из PHP Core Team — (Andrei Zmievski), (Stas Malyshev), (Ilia Alshanetsky).

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

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

Если же говорить об истории моего прихода в программирование, то я начал ещё в школе, с и с программ, опубликованных в журнале «Техника — Молодёжи ». Хотя поначалу это нельзя было назвать программированием — я в основном просто вносил программы, напечатанные в журнале, в память машины и смотрел, что получается. Но потом мне захотелось самому научиться заставлять эту сложную (по тем временам) машину делать то, что я хочу, и я стал разбираться — самостоятельно и с помощью старших — как же это всё работает. Участвовал в кружках, просиживал часами в библиотеке за чтением иностранных журналов, писал программы для своего удовольствия, а потом — и за деньги. Оказалось, что заставлять компьютеры приносить пользу мне нравится, и к моей большой удаче, такое умение пользуется неплохим спросом сегодня на рынке труда.

Перечислить всё, что на меня повлияло на этом пути, будет трудно, но самый большой эффект на меня, наверное, оказали книги, в частности работы , («Мифический человеко-месяц») и (The Inmates Are Running the Asylum — в русском переводе «Психбольница в руках пациентов»).

АЗ: Уже 5 лет я живу в Сан-Франциско и считаю, что это самый красивый город в Америке. Работаю в компании . Хоть это относительно и молодой стартап, у нас уже где-то 110-120 сотрудников. Самые разные фирмы по всему миру используют наш продукт для мониторинга своих бизнес-систем и для быстрого нахождения проблем. Есть у нас и крупные клиенты, например, такие как Netflix, Priceline и другие.

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

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

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

ИА: Я живу и работаю в Торонто, Канада.

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

К сожалению, по мере роста данного проекта на Perl, мне всё больше не нравилась непоследовательность этого языка, и вот «замученная» мною хостинговая компания, которая обслуживала меня в то время, однажды сама предложила попробовать новый для того времени PHP. Этот язык сразу же понравился, потому что он был лучше структурирован и ближе по своему синтаксису к моему любимому Си. Отличная онлайн-документация — завершила мой быстрый и окончательный переход на него.


Илья Альшанетский (Ilia Alshanetsky)

Я настолько активно стал пользоваться PHP 3, что постепенно стали появляться собственные наработки, расширявшие его возможности, которые стал регулярно предлагать в IRC-канале его создателю Расмусу. Патчей и исправлений от меня было так много, что ему это быстро надоело, и он дал мне прямой CVS-доступ к репозиторию проекта. С тех пор было очень много чего написано и сделано, мне даже довелось быть релиз-менеджером (PHP release master) для его популярных версий 4.3, 5.1 и 5.2.

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

Как вы попали в PHP Core Team, какой путь для этого прошли?

АЗ: Позвольте, отвечу на своём примере, но сначала немного истории. Я начал работать с PHP где-то в 1998 году, тогда это был PHP 3, одна из ранних версий. Мы переписывали большой проект с другого языка на PHP, и мне нужно было найти поддержку теперь уже почти забытого . Я не нашёл такой библиотеки, но мне очень понравилось что у PHP была отличная документация и API, поэтому я решил написать своё расширение. Когда закончил, сразу отправил его в почтовую рассылку PHP. А они неожиданно для меня решили добавить его к следующему релизу языка.

Впоследствии мне дали доступ к CVS, и я стал чинить баги, писать больше разных функций и т.д. К концу 1999 г. я был одним из самых активных членов группы, и тогда предложил организовать первый съезд разработчиков PHP в Израиле, чтобы обсудить будущее языка, и включил меня в эту рассылку. Так что никакого голосования не было, просто так получилось, что я сразу попал в PHP Core Team .


Расмус Лердорф (Rasmus Lerdorf), создатель PHP

Такое доверие и открытость мотивировали меня работать больше и больше над кодом PHP. После WDDX я работал над session-модулем, потом написал кучу функций для работы с массивами, затем решил, что PHP надо иметь регулярные выражения подобные Perl, поэтому создал PCRE модуль. К тому времени PHP 4 уже давно вышел, но я меня очень раздражали некоторые проблемы с тем как работали (или вернее не работали) объекты и классы. По этому поводу у меня были долгие переписки с Andi и Zeev, которые создали , и из этого вылилась принципиально новая поддержка Object-Oriented Programming в тогда новом PHP 5.

После этого я работал в основном над кодом для и самим Zend Engine, также сделал новый tokenizer-модуль. С 2003 года вместе с Расмусом, и там я запустил проект по поддерже Unicode в PHP, но это — для другого раза...

Что, по вашему мнению, есть такого в PHP, что сделало его столь популярным?

АЗ: Так получилось, что в данный момент я пишу проект на C++ и Python, так что отвечу исходя из этого сравнительного опыта, смотря как бы с этой «другой колокольни».

Для меня главное, что PHP обладает богатым и обширным API, с помощью которого можно расширить язык во многих, даже подчас неожиданных направлениях. С другой стороны, я часто слышу от людей, насколько легко им было начать пользоваться PHP и как им нравится, что можно написать сайт или программу за считанные часы. Вот вам и суть PHP: он одновременно сложный и простой, старомодный и современный, оригинальный и заимствующий идеи извне — он просто очень универсален.

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

СM: Один из главных уроков, мне кажется, состоит в том, что безопасность кода — это не качество, которое можно привить внешне, независимо от остального кода. Забота о безопасности должна быть повседневной частью работы, с самой первой минуты, начиная с дизайна и до выпуска готового продукта. В PHP было предпринято несколько попыток добавить средства безопасности «извне» — но опыт показал, что эти попытки, без постоянной бдительности со стороны программиста, обречены на провал. Платформа может только помочь ему следить за безопасностью кода, но не может гарантировать эту безопасность без усилий с его стороны.

Поэтому главный совет будет следующим — никогда не доверять никаким внешним данным, или данным, контроль над которыми возможен извне. 99% проблем в безопасности происходят оттого, что допущения, сделанные о входных данных, оказываются неверными, и когда впоследствии происходит атака, то код ведёт себя не так, как это задумал сам разработчик. Поэтому развивайте у себя привычку спрашивать себя всегда — «что, если этот параметр изменить неожиданным образом? Что, если этот аргумент применить не так, как предполагалось?» И тестируйте свой код соответственно.

Следующая моя рекомендация — вместо проверки «нет ли в данных чего-то недозволенного», превентивно преобразуйте данные так, чтобы они были гарантировано такими, как надо. Так будет гораздо проще избежать ошибок. Также не полагайтесь на то, что заботу о безопасности возьмут на себя другие части кода — так, например, если вы делаете динамический запрос к базе данных, всегда самостоятельно убеждайтесь, что параметры и запрос генерируются и фильтруются таким образом, что sql injection невозможна — даже если вы уверены, что данные где-то ещё фильтруются (например, на уровне фреймворка). Тогда, если внешний код изменят таким образом, что в вашу процедуру вдруг попадут нефильтрованые данные, уязвимости всё равно не возникнет.

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

В общем, браузер окончательно станет полноправной частью веб-инфраструктуры, в связи с чем часть обязанностей, исполняемых сейчас сервером, перейдёт на сторону клиента. Поэтому я бы посоветовал людям, работающий сейчас с PHP, заодно следить за новейшими достижениями в области Javascript, HTML5, CSS3 и т.п.

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

Действующие лица:


Андрей Змиевский , один из кураторов PHP Project , разработчик Zend Engine, создатель проектов и , соавтор популярного учебника , автор реализаций Unicode и OOP в PHP. В свободное время увлекается спортом, пивоварением на дому, готовкой. Очень любит много читать и путешествовать.

Стас Малышев , участник PHP Project с 2000 года, релиз-менеджер версии PHP 5.4, участник многих OpenSource-проектов. В свободное время интеллектуальными играми (спортивная версия «Что? Где? Когда?», «Брейн-ринг») и айкидо.

Илья Альшанетский , эксперт в области безопасности и один из старейших разработчиков PHP, глава , релиз-менеджер версий PHP 4.3, 5.1, 5.2, создатель форумного движка , активный участник множества OpenSource-проектов. и на тему безопасности веб-программирования.

p.s.: Обещаю, что в новом 2013 году выложу ещё множество своих VIP-интервью с ведущими мировыми разработчиками, — пусть какая-то конкретика пока будет секретом.

1. GROUP BY one key

This function works as GROUP BY for array, but with one important limitation: Only one grouping "column" ($identifier) is possible.

Function arrayUniqueByIdentifier(array $array, string $identifier) { $ids = array_column($array, $identifier); $ids = array_unique($ids); $array = array_filter($array, function ($key, $value) use($ids) { return in_array($value, array_keys($ids)); }, ARRAY_FILTER_USE_BOTH); return $array; }

2. Detecting the unique rows for a table (twodimensional array)

This function is for filtering "rows". If we say, a twodimensional array is a table, then its each element is a row. So, we can remove the duplicated rows with this function. Two rows (elements of the first dimension) are equal, if all their columns (elements of the second dimension) are equal. To the comparsion of "column" values applies: If a value is of a simple type , the value itself will be use on comparing; otherwise its type (array , object , resource , unknown type) will be used.

The strategy is simple: Make from the original array a shallow array, where the elements are implode d "columns" of the original array; then apply array_unique(...) on it; and as last use the detected IDs for filtering of the original array.

Function arrayUniqueByRow(array $table = , string $implodeSeparator) { $elementStrings = ; foreach ($table as $row) { // To avoid notices like "Array to string conversion". $elementPreparedForImplode = array_map(function ($field) { $valueType = gettype($field); $simpleTypes = ["boolean", "integer", "double", "float", "string", "NULL"]; $field = in_array($valueType, $simpleTypes) ? $field: $valueType; return $field; }, $row); $elementStrings = implode($implodeSeparator, $elementPreparedForImplode); } $elementStringsUnique = array_unique($elementStrings); $table = array_intersect_key($table, $elementStringsUnique); return $table; }

It"s also possible to improve the comparing, detecting the "column" value"s class, if its type is object .

The $implodeSeparator should be more or less complex, z.B. spl_object_hash($this) .

3. Detecting the rows with unique identifier columns for a table (twodimensional array)

This solution relies on the 2nd one. Now the complete "row" doesn"t need to be unique. Two "rows" (elements of the first dimension) are equal now, if all relevant "fields" (elements of the second dimension) of the one "row" are equal to the according "fields" (elements with the same key).

The "relevant" "fields" are the "fields" (elements of the second dimension), which have key, that equals to one of the elements of the passed "identifiers".

Function arrayUniqueByMultipleIdentifiers(array $table, array $identifiers, string $implodeSeparator = null) { $arrayForMakingUniqueByRow = $removeArrayColumns($table, $identifiers, true); $arrayUniqueByRow = $arrayUniqueByRow($arrayForMakingUniqueByRow, $implodeSeparator); $arrayUniqueByMultipleIdentifiers = array_intersect_key($table, $arrayUniqueByRow); return $arrayUniqueByMultipleIdentifiers; } function removeArrayColumns(array $table, array $columnNames, bool $isWhitelist = false) { foreach ($table as $rowKey => $row) { if (is_array($row)) { if ($isWhitelist) { foreach ($row as $fieldName => $fieldValue) { if (!in_array($fieldName, $columnNames)) { unset($table[$rowKey][$fieldName]); } } } else { foreach ($row as $fieldName => $fieldValue) { if (in_array($fieldName, $columnNames)) { unset($table[$rowKey][$fieldName]); } } } } } return $table; }

Похожие статьи

  • Как узнать свой КПД в World Of Tanks?

    КПД в World of Tanks - это коэффициент полезного действия игрока, польза которую вы принесли команде за бой. В расчет КПД входит нанесенный дамаг, убитая техника, засветы, помощь команде. Как поднять КПД в World of Tanks? В этой статье мы...

  • Теплоход сура. И двигается, и рулит

    В 19 веке и первой половине двадцатого столетия наши реки бороздили колесные пассажирские и буксирные суда. Этим летом в первый рейс по Волге отправится современный колесник. Однако это вовсе не дань моде на ретро. Небольшой по размерам и...

  • Крымский мост: кто на самом деле топит украинские порты?

    12:29 — REGNUM ИА REGNUM продолжает знакомить читателей с объектами инфраструктуры Украины. А ключевой элемент инфраструктуры любой страны, имеющей выход к морю, — порты. Инфраструктуры не только транспортной, но и экономической,...

  • Интернет- мешает нормально жить

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

  • Медленно работает интернет

    Интернет на вашем мобильном более уязвим к внешним условиям, чем ноутбуки и компьютеры. Сигнал во многом зависит от зон покрытия 2G и 3G, Wi-Fi точек, мощности станций-трансляторов, погодных условий и вашей личной кармы. Очень часто...

  • InstallPack скачать бесплатно русская версия

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