PHP: Структуры данных — Manual
Change language: EnglishBrazilian PortugueseChinese (Simplified)FrenchGermanJapaneseRomanianRussianSpanishTurkishOther
- Введение
- Установка и настройка
- Предопределённые константы
- Примеры
- Коллекция — Интерфейс Collection
- Хешируемое — Интерфейс Hashable
- Ds\Hashable::equals — Определяет, равен ли текущий экземпляр переданному объекту
- Ds\Hashable::hash — Возвращает скалярное значение для использования в качестве значения хеша
- Последовательность — Интерфейс Sequence
- Ds\Sequence::allocate — Выделение памяти под указанную вместимость
- Ds\Sequence::apply — Обновление всех значений применением к ним переданной callback-функции
- Ds\Sequence::capacity — Возвращает текущую вместимость
- Ds\Sequence::contains — Проверяет, содержатся ли в коллекции заданные значения
- Ds\Sequence::filter — Создаёт новую последовательность из элементов, выбранных с помощью заданной callback-функции
- Ds\Sequence::find — Поиск индекса по значению
- Ds\Sequence::first — Возвращает первый элемент коллекции
- Ds\Sequence::get — Возвращает значение по индексу
- Ds\Sequence::insert — Вставляет значения по указанному индексу
- Ds\Sequence::join — Склеивает все значения в строку
- Ds\Sequence::last — Возвращает последнее значение коллекции
- Ds\Sequence::map — Возвращает результат применения callback-функции ко всем значениям коллекции
- Ds\Sequence::merge — Возвращает результат добавления всех заданных значений в коллекцию
- Ds\Sequence::pop — Удаляет и возвращает последнее значение
- Ds\Sequence::push — Добавляет значения в конец последовательности
- Ds\Sequence::reduce — Схлопывает коллекцию до одного значения используя callback-функцию
- Ds\Sequence::remove — Удаляет и возвращает значение по индексу
- Ds\Sequence::reverse — Переворачивает текущую коллекцию
- Ds\Sequence::reversed — Возвращает перевёрнутую копию коллекции
- Ds\Sequence::rotate — Перематывает последовательность на заданное число значений
- Ds\Sequence::set — Заменяет значение по указанному индексу
- Ds\Sequence::shift — Удаляет и возвращает первое значение
- Ds\Sequence::slice — Возвращает под-коллекцию из заданного диапазона
- Ds\Sequence::sort — Сортирует коллекцию
- Ds\Sequence::sorted — Возвращает отсортированную по значению копию коллекции
- Ds\Sequence::sum — Возвращает сумму всех значений коллекции
- Ds\Sequence::unshift — Добавляет значения в начало последовательности
- Вектор — Класс Vector
- Ds\Vector::allocate — Выделяет память под указанную вместимость
- Ds\Vector::apply — Обновляет все значения, применяя к ним переданную callback-функцию
- Ds\Vector::capacity — Возвращает текущую вместимость
- Ds\Vector::clear — Удаляет все значения
- Ds\Vector::__construct — Создаёт новый экземпляр
- Ds\Vector::contains — Проверяет, содержится ли в векторе заданные значения
- Ds\Vector::copy — Возвращает поверхностную копию вектора
- Ds\Vector::count — Возвращает количество элементов вектора
- Ds\Vector::filter — Создаёт новый вектор из элементов, выбранных с помощью заданной callback-функции
- Ds\Vector::find — Поиск индекса по значению
- Ds\Vector::first — Возвращает первый элемент вектора
- Ds\Vector::get — Возвращает значение по индексу
- Ds\Vector::insert — Вставляет значения по указанному индексу
- Ds\Vector::isEmpty — Проверяет, пуст ли вектор
- Ds\Vector::join — Склеивает все значения в строку
- Ds\Vector::jsonSerialize — Возвращает вектор в JSON-представлении
- Ds\Vector::last — Возвращает последнее значение вектора
- Ds\Vector::map — Возвращает результат применения callback-функции ко всем значениям вектора
- Ds\Vector::merge — Возвращает результат добавления всех заданных значений в вектор
- Ds\Vector::pop — Удаляет и возвращает последнее значение
- Ds\Vector::push — Добавляет значения в конец вектора
- Ds\Vector::reduce — Уменьшает вектор до одного значения, используя callback-функцию
- Ds\Vector::remove — Удаляет и возвращает значение по индексу
- Ds\Vector::reverse — Переворачивает текущий вектор
- Ds\Vector::reversed — Возвращает перевёрнутую копию вектора
- Ds\Vector::rotate — Перематывает вектор на заданное число значений
- Ds\Vector::set — Заменяет значение по указанному индексу
- Ds\Vector::shift — Удаляет и возвращает первое значение
- Ds\Vector::slice — Возвращает подвектор из заданного диапазона
- Ds\Vector::sort — Сортирует вектор
- Ds\Vector::sorted — Возвращает отсортированную по значению копию коллекции
- Ds\Vector::sum — Возвращает сумму всех значений коллекции
- Ds\Vector::toArray — Преобразует коллекцию в массив (array)
- Ds\Vector::unshift — Добавляет значения в начало вектора
- Двухсторонняя очередь — Класс Deque
- Ds\Deque::allocate — Выделяет память под указанную вместимость
- Ds\Deque::apply — Обновляет все значения, применяя callback-функцию к каждому значению
- Ds\Deque::capacity — Возвращает текущую вместимость
- Ds\Deque::clear — Удаляет все значения из двухсторонней очереди
- Ds\Deque::__construct — Создаёт новый экземпляр
- Ds\Deque::contains — Проверяет, содержится ли в двухсторонней очереди заданные значения
- Ds\Deque::copy — Возвращает поверхностную копию коллекции
- Ds\Deque::count — Возвращает количество элементов двухсторонней очереди
- Ds\Deque::filter — Создаёт новую двухстороннюю очередь из элементов, выбранных с помощью заданной callback-функции
- Ds\Deque::find — Поиск индекса по значению
- Ds\Deque::first — Возвращает первый элемент двухсторонней очереди
- Ds\Deque::get — Возвращает значение по индексу
- Ds\Deque::insert — Вставляет значения по указанному индексу
- Ds\Deque::isEmpty — Проверяет, пуста ли двухсторонняя очередь
- Ds\Deque::join — Склеивает все значения в строку
- Ds\Deque::jsonSerialize — Возвращает коллекцию в JSON-представлении
- Ds\Deque::last — Возвращает последнее значение двухсторонней очереди
- Ds\Deque::map — Возвращает результат применения callback-функции ко всем значениям двухсторонней очереди
- Ds\Deque::merge — Возвращает результат добавления всех заданных значений в двухстороннюю очередь
- Ds\Deque::pop — Удаляет и возвращает последнее значение
- Ds\Deque::push — Добавляет значения в конец двухсторонней очереди
- Ds\Deque::reduce — Уменьшает коллекцию до одного значения, используя callback-функцию
- Ds\Deque::remove — Удаляет и возвращает значение по индексу
- Ds\Deque::reverse — Переворачивает текущую двухстороннюю очередь
- Ds\Deque::reversed — Возвращает перевёрнутую копию двухсторонней очереди
- Ds\Deque::rotate — Перематывает двухстороннюю очередь на заданное число значений
- Ds\Deque::set — Заменяет значение по указанному индексу
- Ds\Deque::shift — Удаляет и возвращает первое значение
- Ds\Deque::slice — Возвращает подочередь из заданного диапазона
- Ds\Deque::sort — Сортирует двухстороннюю очередь
- Ds\Deque::sorted — Возвращает отсортированную по значению копию двухсторонней очереди
- Ds\Deque::sum — Возвращает сумму всех значений двухсторонней очереди
- Ds\Deque::toArray — Преобразует двухстороннюю очередь в массив (array)
- Ds\Deque::unshift — Добавляет значения в начало двухсторонней очереди
- Коллекция пар ключ-значение — Класс Map
- Ds\Map::allocate — Выделяет необходимое количество памяти под требуемую вместимость
- Ds\Map::apply — Обновление всех значений применением к ним переданной callback-функции
- Ds\Map::capacity — Возвращает текущую вместимость
- Ds\Map::clear — Удаляет все значения из коллекции
- Ds\Map::__construct — Создаёт новый экземпляр
- Ds\Map::copy — Возвращает поверхностную копию коллекции
- Ds\Map::count — Возвращает количество элементов коллекции
- Ds\Map::diff — Создаёт новую коллекцию пар с элементами, ключей которых нет в другой коллекции пар
- Ds\Map::filter — Создаёт новую коллекцию пар из элементов, выбранных с помощью заданной callback-функции
- Ds\Map::first — Возвращает первый элемент коллекции
- Ds\Map::get — Возвращает значение по ключу
- Ds\Map::hasKey — Проверяет, содержит ли коллекция заданный ключ
- Ds\Map::hasValue — Проверяет, содержит ли коллекция заданное значение
- Ds\Map::intersect — Создаёт новую коллекцию пар, созданную пересечением с другой коллекцией пар
- Ds\Map::isEmpty — Проверяет, пуста ли коллекция
- Ds\Map::jsonSerialize — Возвращает коллекцию в JSON-представлении
- Ds\Map::keys — Возвращает набор ключей коллекции
- Ds\Map::ksort — Сортирует текущую коллекцию по ключам
- Ds\Map::ksorted — Возвращает копию коллекции, отсортированной по ключам
- Ds\Map::last — Возвращает последнюю пару коллекции
- Ds\Map::map — Возвращает результат применения callback-функции ко всем значениям коллекции
- Ds\Map::merge — Возвращает результат добавления всех заданных элементов в коллекцию
- Ds\Map::pairs — Возвращает последовательность, содержащую все пары коллекции
- Ds\Map::put — Установка значения по заданному ключу
- Ds\Map::putAll — Связывает с коллекцией все пары ключ-значение из объекта класса traversable или массива
- Ds\Map::reduce — Уменьшает коллекцию до одного значения, используя callback-функцию
- Ds\Map::remove — Удаляет и возвращает значение по ключу
- Ds\Map::reverse — Переворачивает текущую коллекцию
- Ds\Map::reversed — Возвращает перевёрнутую копию коллекции
- Ds\Map::skip — Возвращает пару по индексу позиции
- Ds\Map::slice — Возвращает подмножество коллекции из заданного диапазона
- Ds\Map::sort — Сортирует коллекцию по значениям
- Ds\Map::sorted — Возвращает отсортированную по значению копию коллекции
- Ds\Map::sum — Возвращает сумму всех значений коллекции
- Ds\Map::toArray — Преобразует коллекцию в array
- Ds\Map::union — Создаёт новую коллекцию пар из элементов двух коллекций
- Ds\Map::values — Возвращает последовательность значений коллекции
- Ds\Map::xor — Создаёт новую коллекцию пар из элементов, которые есть в одной из коллекций, но не в обеих одновременно
- Пара — Класс Pair
- Набор — Класс Set
- Ds\Set::add — Добавляет значения в набор
- Ds\Set::allocate — Выделяет память под указанную вместимость
- Ds\Set::capacity — Возвращает текущую вместимость
- Ds\Set::clear — Удаляет все значения из коллекции
- Ds\Set::__construct — Создаёт новый экземпляр класса
- Ds\Set::contains — Проверяет, содержится ли в коллекции заданные значения
- Ds\Set::copy — Возвращает поверхностную копию коллекции
- Ds\Set::count — Возвращает количество элементов коллекции
- Ds\Set::diff — Создаёт новый набор с элементами, которых нет в другом наборе
- Ds\Set::filter — Создаёт новый список из элементов, выбранных с помощью заданной callback-функции
- Ds\Set::first — Возвращает первый элемент коллекции
- Ds\Set::get — Возвращает значение по индексу
- Ds\Set::intersect — Создаёт новый набор, созданный пересечением с другим набором
- Ds\Set::isEmpty — Проверяет, пуста ли коллекция
- Ds\Set::join — Склеивает все значения в строку
- Ds\Set::jsonSerialize — Возвращает коллекцию в JSON-представлении
- Ds\Set::last — Возвращает последнее значение коллекции
- Ds\Set::merge — Возвращает результат добавления всех заданных значений в набор
- Ds\Set::reduce — Уменьшает коллекцию до одного значения, используя callback-функцию
- Ds\Set::remove — Удаляет все заданные значения из набора
- Ds\Set::reverse — Переворачивает текущую коллекцию
- Ds\Set::reversed — Возвращает перевёрнутую копию коллекции
- Ds\Set::slice — Возвращает поднабор из заданного диапазона
- Ds\Set::sort — Сортирует коллекцию
- Ds\Set::sorted — Возвращает отсортированную по значению копию коллекции
- Ds\Set::sum — Возвращает сумму всех значений коллекции
- Ds\Set::toArray — Преобразует коллекцию в массив (array)
- Ds\Set::union — Создаёт новый набор из элементов текущего и переданного наборов
- Ds\Set::xor — Создаёт новый набор из значений, которые есть в одном из наборов, но не в обоих одновременно
- Стек — Класс Stack
- Ds\Stack::allocate — Выделяет память под указанную вместимость
- Ds\Stack::capacity — Возвращает текущую вместимость
- Ds\Stack::clear — Удаляет все значения из коллекции
- Ds\Stack::__construct — Создаёт новый экземпляр класса
- Ds\Stack::copy — Возвращает поверхностную копию коллекции
- Ds\Stack::count — Возвращает количество элементов коллекции
- Ds\Stack::isEmpty — Проверяет, пуста ли коллекция
- Ds\Stack::jsonSerialize — Возвращает коллекцию в JSON-представлении
- Ds\Stack::peek — Возвращает значение с вершины стека
- Ds\Stack::pop — Удаляет и возвращает значение с вершины стека
- Ds\Stack::push — Добавляет значения в стек
- Ds\Stack::toArray — Преобразует коллекцию в массив (array)
- Очередь — Класс Queue
- Ds\Queue::allocate — Выделяет память под указанную вместимость
- Ds\Queue::capacity — Возвращает текущую вместимость
- Ds\Queue::clear — Удаляет все значения
- Ds\Queue::__construct — Создаёт новый экземпляр
- Ds\Queue::copy — Возвращает поверхностную копию очереди
- Ds\Queue::count — Возвращает количество элементов очереди
- Ds\Queue::isEmpty — Проверяет, пуста ли коллекция
- Ds\Queue::jsonSerialize — Возвращает коллекцию в JSON-представлении
- Ds\Queue::peek — Возвращает значение из начала очереди
- Ds\Queue::pop — Удаляет и возвращает значение из начала очереди
- Ds\Queue::push — Добавляет значения в очередь
- Ds\Queue::toArray — Преобразует коллекцию в массив (array)
- Очередь с приоритетом — Класс PriorityQueue
There are no user contributed notes for this page.
Эффективные структуры данных для PHP 7 / Хабр
PHP имеет всего одну структуру данных для управления всем.array
— сложный, гибкий, гибридный, сочетает в себе поведение list
и linked map
. Но мы используем его для всего, потому что PHP придерживается прагматичного подхода: иметь предельно правильный, здравый и реалистичный способ решения проблемы, исходящий из практических, а не теоретических рассуждений. array
позволяет делать работу, хотя о нем и так много рассказывают на лекциях по информатике. Но, к сожалению, с гибкостью приходит и сложность.Последний релиз PHP вызвал большое оживление в сообществе. Мы не могли дождаться того, чтобы начать использовать новые возможности и почувствовать вкус ~2х прироста производительности. Одна из причин, почему это случилось — структура array
была переработана. Но массивы все также придерживаются принципа «оптимизировано для всего; оптимизировано для ничего», еще не все идеально, есть возможности для совершенствования.
А что насчет структур данных SPL?К сожалению… они ужасны. Раньше, до PHP7, они предлагали _некоторые_ преимущества, но сейчас мы дошли до точки, когда использование SPL не имеет практического смысла.
Почему мы не можем просто поправить и улучшить их?Да, мы могли бы, но я считаю, что их дизайн и реализация настолько бедны, что лучше бы найти более современную замену.
«SPL data structures are horribly designed.»
— Anthony Ferrara
Введение:
php-ds
— расширение для PHP7, добавляющее структуры данных. Этот пост кратко охватывает поведение, производительность и преимущества каждой из них. Также в конце вы найдете список ответов на ожидаемые вопросы.Github: https://github.com/php-ds
Пространство имен: Ds\
Интерфейсы: Collection
, Sequence
, Hashable
Классы: Vector
, Deque
, Stack
, Queue
, PriorityQueue
, Map
, Set
Collection
(Коллекция)Collection
— это базовый интерфейс, охватывающий общую функциональность: foreach
, echo
, count
, print_r
, var_dump
, serialize
, json_encode
, и clone
.Sequence
(Последовательность)Sequence
описывает поведение элементов, организованных в единый, линейный размер. В некоторых языках такая структура назвается List
(список). Подобен array
, который использует инкрементальные ключи, за исключением некоторых особенностей:- Значения всегда должны быть индексированы как
[0, 1, 2, …, size - 1]
- Извлечение или добавление приводит к обновление индекса всех последовательных значений
- Поддерживает доступ к значениям только из индекса
[0, size - 1]
Варианты использования
- Везде, где вы бы хотели использовать
array
как список (без ключей) - Более эффективная альтернатива
SplDoublyLinkedList
иSplFixedArray
Vector
(Вектор)Vector
представляет собой Sequence
, объединяющую значения в непрерывный буфер, увеличивающийся и уменьшающийся автоматически. Это наиболее эффективная последовательная структура данных, поскольку индекс элемента является прямым отражением его индекса в буфере, и увеличение вектора никак не повлияет на производительность.Сильные стороны
- Очень маленькое потребление памяти
- Очень быстрые итерации
get
,set
,push
иpop
имеют сложностьO(1)
Недостатки
insert
,remove
,shift
andunshift
имеют сложностьO(n)
Структурой номер один в Photoshop были Вектора.
— Sean Parent, CppCon 2015
Deque
(Двусвязная очередь)Deque
(произносится как «deck») — это последовательность значений, объединенных в непрерывный буфер, увеличивающийся и уменьшающийся автоматически. Название является общепринятым сокращением от «double-ended queue». Используется внутри Ds\Queue
.Два указателя используется для отслеживания головы и хвоста. Наличие указателей позволяет изменять конец и начало буфера без необходимости перемещать другие элементы для освобождения места. Это делает shift
и unshift
настолько быстрым, что даже Vector
не может конкурировать с этим.
Доступ к значению по индексу требует вычисления соответствующей позиции в буфере: ((head + position) % capacity)
.
Сильные стороны
- Очень маленькое потребление памяти
get
,set
,push
,pop
,shift
иunshift
имеют сложностьO(1)
Недостатки
insert
,remove
имеют сложностьO(n)
- Емкость буфера должна иметь степень двойки (
2ⁿ
)
Следующий бенчмарк показывает общее затраченное время и память, используемую для операции
push
2ⁿ случайных чисел. array
, Ds\Vector
и Ds\Deque
отрабатывают быстро, но SplDoublyLinkedList
стабильно показывает результат более чем в 2 раза хуже.SplDoublyLinkedList
выделяет память для каждого значения по отдельности, поэтому и происходит ожидаемый рост по памяти. array
и Ds\Deque
при своей реализации выделяют память порционно для поддержания достаточного объема для 2ⁿ элементов. Ds\Vector
имеет фактор роста 1.5, что влечет за собой увеличение количества выделений памяти, но меньший расход в целом.
Следующий бенчмарк показывает время, затраченное на unshift
единственного элемента в последовательности значений размером 2ⁿ. Время, требующееся на установку значений не учитывается.
На графике видно, что array_unshift
имеет сложность O(n)
: всякий раз, когда объем выборки удваивается, растет и время, необходимое для unshift
. Это объясняется тем, что каждый числовой показатель в диапазоне [1, size - 1]
должен быть обновлен.
Но и Ds\Vector::unshift
также O(n)
, так почему же он намного быстрее? Имейте ввиду, что array
хранит каждое значение в bucket
вместе с его ключем и хэшем. Поэтому приходится проверять каждый элемент и обновлять хэш, если индекс является числовым. На самом деле array_unshift
выделяет новый массив для этого и заменяет старый, когда все значения скопированы.
В векторе же индекс значения — это прямое отображение его индекса в буфере, поэтому все, что нам нужно сделать — сдвинуть каждое значение в диапазоне [1, size — 1] вправо на одну позицию. Делается это при помощи всего одной операции memmove
.
Ds\Deque
и SplDoublyLinkedList
в свою очередь очень быстры, потому что на время для unshift
значения не влияет размер выборки, т.е. его сложность будет O(1)
.
На следующем тесте видно сколько памяти используется при 2ⁿ pop
операций. Другими словами при изменении размера от 2ⁿ до нуля
Интересно тут то, что array
всегда держит выделенную память, даже если его размер существенно уменьшается. Ds\Vector
and Ds\Deque
позволяют в два раза уменьшить выделяемые ресурсы, если их размер падает ниже четверти своего текущего потенциала. SplDoublyLinkedList
освобождает память после каждого удаления из выборки, поэтому мы можем наблюдать линейное снижение.
Stack
(Стек)Стек — является коллекцией, организованной по принципу «последним пришёл — первым вышел» или «LIFO» (last in — first out), позволяющей получить доступ только к значению на вершине структуры. Вы можете думать о нем как об оружейном магазине с динамической емкостью.
Ds\Stack
использует внутри себя Ds\Vector
.
SplStack
наследуется от SplDoublyLinkedList, поэтому производительность будет эквивалентна сравнению Ds\Vector
to SplDoublyLinkedList
из предыдущих тестов. Посмотрим на время, необходимое для выполнения 2ⁿ pop
-операций, изменения размера от 2ⁿ до нуля.
Queue
(Очередь)Очередь — тип данных с парадигмой доступа к элементам «первый пришел — первый вышел» («FIFO», «First In — First Out»). Такая коллекция позволяет получить доступ к элементам в порядке их добавления. Ее название говорит само за себя, представьте себе структуру как линию людей, стоящих в очереди на кассу в магазине.
Ds\Queue
использует внутри себя Ds\Deque
. SplQueue
наследуется от SplDoublyLinkedList
, поэтому производительность будет эквивалентна сравнению Ds\Deque
с SplDoublyLinkedList
, показанному в предыдущем бенчмарке.
PriorityQueue
(Очередь с приоритетом)Очередь с приоритетом очень похожа на простую очередь. Элементы помещаются в очередь с указанным приоритетом и значение с наивысшим приоритетом всегда будет в передней части. Прямой перебор очереди с приоритетом очень деструктивен, это будет последовательный вызов операций
pop
, что является очень затратной операцией.Реализация очереди с приоритетом использует max-heap.
Принцип «первый пришел — первый вышел» сохраняется для значений с одинаковым приоритетом, так что группа значений с равным приоритетом можно рассматривать как обычную очередь.
А что же с производительностью? Следующий бенчмарк показывает время и память, требующиеся для операции push
2ⁿ случайных чисел со случайным приоритетом в очередь. Те же случайные числа будут использоваться для каждого из тестов. В тесте для Queue
также генерируется случайный приоритет, хотя он и не используется.
Это, наверное, самый значимый из всех бенчмарков. Ds\PriorityQueue
работает более чем в два раза быстрее чем SplPriorityQueue
и использует только 5% от его памяти — это в 20 раз более эффективное решение по памяти.
Но как? Как может получиться настолько большая разница, когда SplPriorityQueue
использует аналогичную внутреннюю структуру? Все сводится к тому, как хранятся значения в паре с приоритетом. SplPriorityQueue
позволяет использовать любой тип значения для использования в качестве переменной, это приводит к тому, что в каждой паре приоритет занимает 32 байта.
Ds\PriorityQueue
поддерживает только целочисленные приоритеты, поэтому каждой паре выделяется 24 байта. Но это все еще недостаточная разница для объяснения результата.
Если вы посмотрите на исходный код SplPriorityQueue::insert
, то заметите, что он инициализирует массив для хранения пары значение-приоритет.
Т.к. массив имеет минимальную емкость 8, то для каждой пары на самом деле выделяется zval + HashTable + 8 * (Bucket + hash) + 2 * zend_string + (8 + 16) byte string payloads
= 16 + 56 + 36 * 8 + 2 * 24 + 8 + 16
= 432 байта (64 бит).
«Так… почему же массив?»
SplPriorityQueue
использует ту же внутреннюю структуру SplMaxHeap
, которая требует от значения быть типом zval
. Очевидный (но неэффективный) способ создания zval
-пары, т.к. zval
сам используется как array
.Hashable
Интерфейс, позволяющий объектам быть использованными в качестве ключей. Это альтернатива
spl_object_hash
, который детерминирует объект в хэш, базирующийся на его handle:
. Это означает, что два объекта, которые считались бы равными при сравнении, не имели бы равный хэш, т.к. они не являются одним и тем же экземпляром.Hashable
вводит только два метода: hash
и equals
. Многие другие языки поддерживают это изначально: в Java — hashCode
и equals
, или в Python ___hash___
и __eq__
. Было несколько RFC, добавляющих подобное поведение и в PHP, но ни один из не был принят.
Все структуры, будут возвращать spl_object_hash
, если ключи объектов, хранящиеся в них не реализуют в себе Hashable
.
Структуры данных, работающие с интерфейсом Hashable
: Map
и Set
.
Map
(Ассоциативный массив)Map
является последовательной коллекцией пар ключ-значение, практически идентичной array
в аналогичном контексте. Ключи могут быть любого типа, единственное условие — уникальность. При повторном добавлении ключа значения заменяются.Как и в array
, порядок вставки сохраняется.
Сильные стороны
- Производительность и эффективность использования памяти практически идентичны
array
- Автоматическое освобождение памяти при уменьшении размера
- Ключи и значения могут быть любого типа, включая объекты
- Поддерживает работу с объектами, реализующими интерфейс
Hashable
put
,get
,remove
иcontainsKey
имеют сложностьO(1)
Недостатки
- Не может быть преобразован в
array
при наличии ключей-объектов - Нет возможности получить доступ к значениям по индексу (позиции)
Следующий бенчмарк показывает, что производительности и эффективности по памяти между
array
и Ds\Map
идентичны. Однако, array
всегда будет держать выделенную память, когда Ds\Map
, в свою очередь, освободит память при падении размера ниже четверти своего потенциала.Set
(Множество)Set
— коллекция уникальных значений. Учебники скажут вам, что в структуре Set
значения неупорядочены, если реализация не предусматривает иное. Возьмем для примера Java, java.util.Set
— это интерфейс с двумя основными реализациями: HashSet
и TreeSet
. HashSet
обеспечивает сложность O(1)
для add
и remove
, a TreeSet
обеспечивает сортированный набор данных, но сложность add
и remove
возрастает до O(log n)
.Set
использует ту же внутреннюю структуру, что и Map
, также основываясь на array
. Это означает, что Set
может быть отсортирован за время O(n * log(n))
когда это понадобится, в остальном он такой же простой как Map
и array
.
Сильные стороны
add
,remove
иcontains
имеют сложностьO(1)
- Поддерживает работу с объектами, реализующими интерфейс
Hashable
- Поддерживает любой тип значений (
SplObjectStorage
поддерживает только объекты). - Имеет эквивалент поразрядных логических операций (
intersection
,difference
,union
,exclusive or
)
Недостатки
- Не поддерживает
push
,pop
,insert
,shift
илиunshift
get
имеет сложностьO(n)
если есть удаленные значения до момента индексации, в ином случае —O(1)
Следующий бенчмарк показывает время, затраченное на добавление 2ⁿ новых экземпляров
stdClass
. Он показывает, что Ds\Set
немного быстрее, чем SplObjectStorage
, и использует примерно в половину меньше памяти.Распространенным способом создания массива с уникальными значениями является
array_unique
, который создает новый array
, содержащий только уникальные значения. Но важно иметь ввиду, что значения в массиве не индексируются, in_array
является линейным поиском со сложность O(n)
. array_unique
работает только со значениями, без учета ключей, каждая проверка на наличие значения массива — линейный поиск, что даем нам в сумме сложность O(n²)
по времени и O(n)
по потреблению памяти.Ответы на ожидаемые вопросы и мнения
Есть ли тесты?
Сейчас около 2600 тестов. Вполне возможно, что некоторые тесты являются избыточными, но я предпочел бы косвенно проверить одну и ту же вещь дважды, чем не проверять совсем.
Документация? Справочник по API?
На момент написания этой статьи пока еще нет полной документации, но она появится вместе с первым стабильным релизом.
Однако, существуют некоторые хорошо документированные файлы-заглушки.
Можем ли мы посмотреть как устроены бенчмарки? Есть что-то о них?
Все бенчмарки прогонялись на стандартном билде
PHP 7.0.3
на 2015 Macbook Pro. Результаты могут отличаться в зависимости от версии и платформы.Почему
Stack
, Queue
, Set
и Map
— не интерфейсы? Я не верю, что есть необходимость в какой-либо альтернативной реализации. 3 интерфейса и 7 классов — это хороший баланс между прагматизмом и специализацией.
Когда мне использовать
Deque
вместо Vector
? Если вы точно знаете, что не будете использовать
shift
и unshift
, используйте Vector
. Для удобного тайпхинтинга можно указать в качестве типа Sequence
.Почему все классы являются финализированными?
Дизайн API
php-ds
применяет парадигму «Composition over inheritance.Структуры SPL являются хорошим примером того, как наследование может быть использовано не по назначение. Например, SplStack
расширяет SplDoublyLinkedList
, который поддерживает произвольный доступ по индексу, shift
и unshift
— так что технически это не Стек.
Фреймворк Java-коллекций также имеет несколько интересных случаев, когда наследование порождает двусмысленность. ArrayDeque
имеет три метода добавления элементов: add
, addLast
и push
. Это не плохо, т.к. ArrayDeque
имплементирует Deque
и Queue
, что объясняет одновременное наличие addLast
и push
. Однако, все три метода сразу, делающие одно и тоже, вызывают путаницу и непоследовательность.
Старый java.util.Stack
расширял java. util.Vector
, тем самым заявляя, что „более полный и последовательный набор операций LIFO обеспечивается интерфейсом Deque
и его реализациями“, но Deque
включает в себя методы addFirst
и remove(x)
, которые не должны быть часть stack
структуры по API.
Просто потому, что эти структуры имеют непересекающиеся методы не значит, что мы не можем так делать.
На самом деле, это справедливое замечание, но я по-прежнему считаю, что композиция больше подходит для построения структур данных. Они предназначены быть самодостаточными, подобно
array
. Вы не можете отнаследоваться от array
, он вынуждает вас разрабатывать собственные API вокруг себя, используя его только для хранения фактических данных.Наследование также вызвало бы лишние сложности во внутренней реализации.
Зачем нужен еще и
ds
класс в глобальном пространстве имен? Он обеспечивает альтернативный синтаксис:
Почему нет связного списка
(Linked List)?Класс
LinkedList
на самом деле появился первым, это казалось хорошим стартом. Но в итоге я решил удалить его, когда понял, что он не сможет конкурировать с Vector
или Deque
при любом раскладе. Две основные причины возможной поддержки: распределение накладных расходов и локальность ссылок.В связном списке мы добавляем или убираем зарезервированную память для элемента структуры (node) всякий раз, когда значение добавляется или удаляется. Нода содержит в себе два указателя (в случае с двусвязным списком), чтобы ссылаться на предыдущую и последующую ноды. Обе структуры, Vector
и Deque
, выделяют буфер памяти заранее, поэтому нет необходимости делать это настолько часто. Они также не нуждаются в дополнительных указателях, чтобы знать какое значение до и какое после, тем самым снижаются накладные расходы.
Будет ли связный список использовать меньше памяти, т.к. там нет буфера?
Только когда коллекция очень мала. Верхней границей количества памяти для
Vector
будет (1. 5 * (size - 1)) * zval
байт, не менее *10 * zval*. В двусвязном списке же будет использоваться (size * (zval + 8 + 8))
. Поэтому связный список будет использовать меньше памяти, чем Vector
только тогда, когда его размер меньше 6 элементов.Окей… связный список использует больше памяти, но почему он медленный?
Узлы связного списка обладают плохой пространственной локальность. Это означает, что физическое расположение узла в памяти может быть далеко от прилегающих узлов. Таким образом итерации по связному списку скачут по памяти вместо использования кэша процессора. Значительное преимущество
Vector
и Deque
: элементы физически находятся рядом друг с другом.»Несмежность данных в структурах является корнем всех зол производительности. Конкретно, пожалуйста, скажите нет связным спискам»
«Нет почти ничего вреднее из того что вы можете сделать чтобы убить все плюсы современных микропроцессоров, чем использовать связный список»
— Chandler Carruth (CppCon 2014)
PHP — это язык для веб-разработки — производительность не важна.
Производительность не должна быть вашим главным приоритетом. Код должен быть последовательным, ремонтопригодным, надежным, предсказуемым, безопасным и легко понимаемым. Но это не означает, что производительность «не важна».
Мы тратим много времени, пытаясь уменьшить размер своих ассетов, делаем сравнительный анализ фреймворков и придумываем бессмысленные микро-оптимизации:
Но в конечном итоге двухкратный прирост производительности, который приносит с собой PHP7 почему-то всех взбудоражил. Абсолютно для всех это — одно из главных преимуществ для перехода с PHP5.
Эффективный код позволяет снизить нагрузку на наши сервера. уменьшить время ответа наших API и веб-страниц и снижает время работы наших утилит для разработки. Высокая производительность важна, но поддерживаемость кода все же стоит во главе.
Обсуждения: Twitter, Reddit, Room 11
Исходный код: github.com/php-ds
Бенчмарки: github.com/php-ds/benchmarks
Структура проекта для PHP — CodeRoad
Я новичок в PHP и хочу знать структуру каталогов для проектов php. У меня есть опыт работы в Java, а в java у нас src содержит java исходных файлов, WEB-INF содержит lib и jsp страницу. Есть ли у нас подобная стандартная структура каталогов в PHP? Кроме того, есть ли у нас слои в php, как у нас есть слои в java (например, веб, сервис, DAO слоев)
Я просмотрел несколько ссылок. Но каждый давал разные ответы.
Не уверен, что мы можем сравнить эти два языка. Я просто хочу придерживаться некоторых стандартов.
Заранее спасибо.
php directory structureПоделиться Источник javafan 29 октября 2013 в 02:47
5 ответов
- Структура репозитория для проекта android
У меня есть проект android с версией SVN. У меня есть три проекта eclipse в моем хранилище. Библиотечный проект, проект бесплатной версии, проект платной версии. Моя текущая структура репозитория такова: repository/ branches/ tags/ trunk/ freeversion/ paidversion/ library/ Есть ли лучшая структура. ..
- Правильное решение / структура проекта для Silverlight приложений
Я унаследовал решение, которое использует Silverlight. Я нахожу, что есть проекты, которые являются почти точными клонами других проектов, с той лишь разницей, что клон-это проект Silverlight. Например, это структура проекта и папок проекта, не являющегося Silverlight: MyCompany.Entities -…
26
Нет. PHP — это то, что вы делаете из этого. Это могут быть очень простые плоские файлы, или как вам угодно.
Тем не менее, существует несколько согласованных стандартов кодирования, но нет «enforcement» из указанных стандартов. Они называются PSR (рекомендация по стандартам PHP). Здесь есть предыстория: http:/ / net.tutsplus.com / tutorials/php/psr-huh/
Вы можете просмотреть стандарты один за другим здесь: http://www.php-fig.org/psr/
Большинство основных фреймворков следуют этим стандартам, и если вы собираетесь использовать один из них, вам будет легче плыть по течению.
Опять же, каждый фреймворк, проект, плагин, программа и т. д. имеют разные макеты с разными структурами проекта. Общая структура-это что-то вроде этого:
-framework_dir
-public_html
-js
-img
-css
-index.php
-protected/private
-controllers
-models
-views
-etc
Затем они используют файл .htaccess
для блокировки доступа к защищенным каталогам. Опять же, это просто общее представление, которое я видел в нескольких фреймворках. Если вы делаете личный проект, просто используйте то, что вам удобно. Каждый фреймворк предоставит вам другую библиотеку или способ доступа к данным. Там нет «layers», но опять же каждый фреймворк имеет объекты, которые обрабатывают различные области (email, база данных, кэш, http, журналы и т. д.). Потому что есть десятки популярных, это просто до вас, чтобы найти то, что соответствует вашей философии или проекту. Посмотрите несколько 5-минутных видеороликов в блоге, посмотрите, что такое jives, а затем дайте ему тестовый запуск в течение нескольких дней. Если вам это не нравится, переключитесь на другое.
Поделиться Tim Withers 29 октября 2013 в 03:04
9
С изобретением Composer у людей теперь есть центральное место для регистрации своих проектов для потребления миром, и другие люди теперь могут смотреть на эту кодовую базу и видеть сходство.
Результат таков: https://github.com/php-pds/skeleton
Короче говоря:
If a package has a root-level directory for ...
... then it MUST be named:
command-line executables bin/
configuration files config/
documentation files docs/
web server files public/
other resource files resources/
PHP source code src/
test code tests/
Настоящий стандарт не содержит никаких дополнительных рекомендаций относительно того, какие каталоги должны существовать ниже src
или public
.
Задача организовать исходные файлы PHP внутри любого из этих каталогов по — прежнему остается за вами, но есть предложения, изложенные в этой статье, с которыми я бы согласился: либо Сортировать по типу (контроллер, сущность, служба), либо Сортировать по функции (пользователь, логин, корзина, каталог, статья, комментарий) — последняя сохраняет весь код, принадлежащий одной функции, в каталоге (или нескольких подкаталогах), что часто кажется лучшей организацией файлов.
При Организации по типу вы обнаружите, что довольно часто прыгаете между каталогами, а также не получаете хорошего представления о том, что такое код — у вас всегда будет «Controller»,, но редко «StampCollection».
Поделиться Sven 22 февраля 2017 в 14:16
4
Я склонен использовать структуру папок на основе функций для своих бэкенд-проектов. Каждая функциональная папка имеет свой собственный контроллер, менеджер и файл маршрутов. Это хорошо работает для api-бэкендов. Это выглядит примерно так https://blog.nikolaposa.in.rs/2017/01/16/on-structuring-php-projects/
Например, у нас есть функция клиента с CustomerController, CustomerRepository, CustomerRoutes,..
Моя структура папок выглядит следующим образом:
- build/
-- phpdox.xml
-- phpmd.xml
-- phpunit.dist.xml
- config/
- public/
-- .htaccess
-- index.php
-- assets/
- src/
-- Customer/
--- CustomerController.php
--- CustomerRepository.php
--- Customer.php
--- customer.routes.php
- tests/
- vendor/
composer.json
.gitignore
Поделиться Gudgip 13 июля 2018 в 12:43
- Структура проекта в Meteor
Я начинаю создавать веб-приложение с meteor. Что касается документации meteor, то она очень гибка в том, как структурировать файлы в приложении, но я хочу сделать лучшую структуру проекта для дальнейшего обслуживания. Существует ли какая-либо стандартная структура проекта, на которую я могу…
- Структура проекта для Django приложения
Я новичок в Django и использую Pycharm из IntelliJ в качестве своего IDE. При наборе текста: $ django-admin startproject mysite создается следующая структура проекта: mysite/ manage.py mysite/ __init__.py settings.py urls.py wsgi.py Это не совсем имеет смысл, поскольку файлы settings.py, urls.py и…
3
К сожалению (или нет?), вы очень свободны с PHP. Все зависит от тебя.
Вот моя структура:
framework/
controllers/
models/
configs/
files/
templates/
themes/
tmp/
index.php
init.php
.htaccess
Вы можете управлять доступом через файл. htaccess.
Поделиться Mr. B. 29 октября 2013 в 03:16
1
Для библиотеки я использую следующую структуру . .. плюс я включил рекомендации, которые я еще не использую (пока)
PROJECT ROOT
|--composer.json
|--README.md
|--docs //for documentation files
|--tests //for Unit Tests
|--vendor //for external libraries (if everything isn't included through composer)
|--examples //examples of the library being used
|--config //any configuration files you may have
|--src //where the library's actual code "lives"
|--php //php source code, classes, any other scripts
|--View //html views, but actually php files that output html
|--Style //contains .css files
|--Script //contains .js files
|--Res //contains other deliverable resource files. Could be mp3 files, json etc
В настоящее время я использую только composer.json
, README.md
и src
среди корневых файлов. Но я, вероятно, буду использовать другие, как я описал, когда дойду до этого момента.
Я ни в коем случае не думаю, что это «correct». И эта настройка работает только потому, что у меня есть маршрутизатор php на каждый запрос. С .htaccess
, .css
, чтобы вы могли маршруту файла /src/Style/requested_file.css
.
Я хотел, чтобы корень проекта был очищен, и я добился этого. PHP Fig не имеет PSR для структур каталогов… это мне известно. Я надеялся , что PSR-4, autoloader будет иметь некоторые стандарты, но… не совсем, что касается структуры каталогов.
Вы можете посмотреть на laravel , wordpress , PHP Mailer и другие библиотеки php, чтобы увидеть примеры и посмотреть, что вам может понравиться больше всего
Поделиться Reed 29 июня 2019 в 15:12
Похожие вопросы:
CUDA Структура Проекта
Шаблон и примеры cppIntegration в CUDA SDK (версия 3.1) используют внешние интерфейсы для связи вызовов функций из кода хоста с кодом устройства. Однако комментарий Тома здесь указывает на то, что…
Структура папок для проекта PHP
Я решил полностью переписать свой старый проект PHP с нуля. Раньше у меня был один файл для каждой страницы,а теперь я хотел бы использовать подход MVC pattern с одной точкой входа. Сам проект…
Файловая структура для проекта PHP
Моя файловая структура: /holiday/admin/list.php /holiday/includes/functions.php # common functions /holiday/index.php # / is the document root # /holiday/ is a self-contained sub-directory # There…
Структура репозитория для проекта android
У меня есть проект android с версией SVN. У меня есть три проекта eclipse в моем хранилище. Библиотечный проект, проект бесплатной версии, проект платной версии. Моя текущая структура репозитория…
Правильное решение / структура проекта для Silverlight приложений
Я унаследовал решение, которое использует Silverlight. Я нахожу, что есть проекты, которые являются почти точными клонами других проектов, с той лишь разницей, что клон-это проект Silverlight….
Структура проекта в Meteor
Я начинаю создавать веб-приложение с meteor. Что касается документации meteor, то она очень гибка в том, как структурировать файлы в приложении, но я хочу сделать лучшую структуру проекта для…
Структура проекта для Django приложения
Я новичок в Django и использую Pycharm из IntelliJ в качестве своего IDE. При наборе текста: $ django-admin startproject mysite создается следующая структура проекта: mysite/ manage.py mysite/…
Django — AngularJs Структура Проекта
После нескольких дней исследований мне еще предстоит решить, какая структура лучше всего подходит для проектов AngularJs с Django.Many, доступных на GitHub, и учебников в сети с использованием…
Структура проекта для golang, docker, gradle
Я только начинаю с Go (golang) и хочу создать новую структуру папок проекта для проекта, который будет построен с Gradle и развернут в образе Docker. Я изо всех сил пытаюсь определить, как может…
Структура проекта для компонентной архитектуры в AngularJS 1. 5
Какова стандартная структура папок проекта, которой я должен следовать для создания компонентного проекта в AngularJS 1.5?
Структуры данных(на примере PHP SPL) | by Alexander Shogenov
Процесс разработки связан, в основном, с извлечением, получением и обработкой данных из разных источников, таких как базы данных, файлы, API и т.д. Очень много времени разработчики на организацию, получение, перемещение и обработку данных.
В рамках этой статьи я буду рассматривать язык PHP для того, чтобы, как минимум, я сам понимал, о чём говорю. PHP — язык простой для понимания большинству и, я думаю, что у программистов, работающих на других языках, не возникнет проблем с пониманием данного материала. Можно было бы просто абстрактно описать о структурах данных, но хочется более осязаемого материала.
Чаще всего для представления данных в PHP используют массив. Однако в некоторых случаях массивы не подходят для решения задач. Где-то не хватает производительности, где-то слишком много памяти “кушает”, и поэтому требуются более подходящие структуры данных.
Библиотека SPL — является частью ядра(начиная с пятой версии PHP) и содержит набор интерфейсов, классов структур данных, итераторов и функций, с помощью которых можно значительно упростить себе жизнь и повысить качество кода.
- SplDoublyLinkedList
- Двусвязные спискиSplStack
- СтекSplQueue
- ОчередьSplHeap
- КучаSplMaxHeap — Сортировка кучи по убыванию
- SplMinHeap — Сортировка кучи по возрастанию
- SplPriorityQueue — Приоритетные очереди
- SplFixedArray — Массив с ограниченной длиной
- SplObjectStorage — Хранилище объектов
SplDoublyLinkedList — двусвязный список. Каждый узел такого списка хранит ссылку на предыдущий и на следующий за ним узел. Представьте, что вы находитесь в очереди и при этом можете видеть только человека перед вами и позади вас. Это аналогия отношения связи между элементами в SplDoublyLinkedList. Вставка элемента в список соответствует ситуации, когда кто-то влез в очередь, а вы вдруг забыли, кто стоял перед вами (и этот кто-то забыл о вас). Двусвязный список позволяет эффективно обходить и добавлять большие наборы данных без необходимости повторного хеширования.
SplQueue и SplStack очень похожи на SplDoublyLinkedList. Обе эти структуры, по сути, представляют собой двусвязные списки с разными флагами итераторов(IT_MODE_LIFO — Last In First Out — последним пришёл, первым ушёл; и IT_MODE_FIFO — First In First Out — первым пришёл, первым ушёл), которые регулируют порядок обработки узлов и что делать с этими элементами после того, как они будут обработаны. Ещё одно отличие между этими структурами заключается в том, что интерфейс SplQueue содержит более интуитивно понятные методы enqueue() и dequeue() в отличие от методов push() и pop() у SplStack.
SplHeap — куча, представленная в виде бинарного дерева, каждый узел которого имеет не более двух дочерних узлов. Это абстрактный класс, требующий расширения с определением метода compare(), позволяющего выполнять сортировку в реальном времени при вставке новых узлов в дерево.
SplMaxHeap и SplMinHeap — конкретные реализации абстрактного класса SplHeap. SplMaxHeapреализует метод compare() таким образом, чтобы дерево было отсортировано в порядке убывания значений узлов, а SplMinHeap — в порядке возрастания значений.
SplPriorityQueue — очередь, похожая на SplHeap, но в отличие от SplHeap сортировка осуществляется на основании значения свойства priority (приоритет), заданного для каждого узла.
SplFixedArray — массив фиксированной длины, индексами которого могут быть только целые числа. Эти ограничению обеспечивают более высокую скорость обработки массива, которая достигается, в том числе, благодаря тому, что в SplFixedArray нет хеширования ключей элементов при их добавлении (в отличие от обычных массивов).
SplObjectStorage — хранилище объектов, предоставляет интерфейс для сопоставления объектов к данным, либо может быть использовано в качестве контейнера для множества объектов. Позволяет использовать объект в качестве ключа ассоциативного массива и связать его с некоторыми данными.
— — —
Официальная документация по SPL http://php.net/manual/ru/book.spl.php
Кстати, если претендуешь на вакансию уровня серьёзнее, чем junior, есть вероятность, что об этом спросят на собеседовании. А ты теперь это знаешь! Не благодари.
— —
Много полезного на mynrg.ru
___________
Я — программист!
Шутеечки в Дневнике программиста
Чат Клуб программистов
Ядро, структура сайта, MVC
Дополнение к уроку:
MVC — Модель, Вид (представление), Контроллер. Правила следующие:— В Модели и Контроллере отсутствует вывод информации на экран.
— В Виде мы допускаем PHP в размере необходимом для вывода информации на экран. То есть это будут условные конструкции, циклы, сопутствующие функции обработки вроде htmlspecialchars (о котором будет в следующих уроках).
У нас есть код, не читай ответа ниже ответьте как разделить его:
$x = 1;
echo $x;
Ответ очень прост, первую часть мы помещаем в наш контроллер, а вторую в вид.
Наш сайт делится на разделы (Модули, — это не модели!), а внутри разделов страницы. Разделы — это объединённые по смыслу и общему контенту нескольких страниц сайта. Хочу заметить, что в разделе может быть и одна лишь страница. Если мы создаём модуль «новости», то у нас будут страницы: вывод свежих новостей, вывод всех новостей, страница для чтения определённой новости. Если у нас игра, то это отдельный модуль game, в котором присутствуют 2 страницы: главная страница с игрой, и страница с gameover.
В каждом модуле есть основная (главная) страница и называется main , в ней находится код по открытию раздела. В модуле GAME главной страницей будет игра, а вывод результатов как дополнительная страница. Главная страница main, значит у нас создаются main.php и main.tpl в папке модуля game (в случае рассмотрения раздела сайта game).
Давайте на примере GAME рассмотрим какие файлы мы должны создать:
1) Папки модуля GAME:
/modules/game/
/skins/default/game/
2) Игра состоит из двух страниц: битва и результат, значит мы создаём main. php и gameover.php
/modules/game/main.php
/skins/default/game/main.tpl
/modules/game/gameover.php
/skins/default/game/gameover.tpl
3) В адресной строке открываем главную страницу БЕЗ УКАЗАНИЯ page=main , потому что если мы не укажем page=main, он определится автоматически в файле variables.php . Итого мы получаем 2 страницы:
/index.php?module=game
/index.php?module=game&page=gameover
4) Чтобы работал модуль, его необходимо прописать в variables.php в переменной допустимых модулей. Страницы мы не прописываем, так как это будет тема отдельного урока.
Сама суть разделов очень простая, сгруппировать и упростить работу с нашим кодом, согласитесь, ведь когда надо поработать с разделом «игра» мы не будем перебирать сотни файлов в поисках нужных, мы всегда знаем, что вся игра полностью находится в папке модуля game.
Ещё одна ошибка учеников — если форма авторизации находится на главной странице, то обработчик формы должен быть в index.php или variables. php. Это не так. Авторизация и кнопка выхода относятся к разделу (модулю) cab (кабинет) или user (пользователь) или login. Называйте как хотите, но суть остаётся прежней, именно в этом модуле должен располагаться код авторизации и код выхода в разных файлах. Чтобы форма отправляла данные на указанную страницу модуля достаточно в теге FORM для атрибута action указать путь к этой странице на примере авторизации:
<form action="/index.php?module=cab&page=auth" method="post">
С exit ещё проще, так как не надо никаких данных заполнять, а достаточно переправить пользователя на отдельную страницу, то мы пишем обычной ссылкой:
<a href="/index.php?module=cab&page=exit">Выход</a>
В архивы самые внимательные заметили, что index.php в конце не закрывает PHP блок, так же он не закрыт в variables, и в .php файлах в модулях. Это сделано умышленно и именно так надо писать .php файлы все. Закрываем PHP блок только в том случае, когда следом идёт вывод HTML в этом же ФАЙЛЕ.
Под каждым уроком есть 10 тестов, которые помогут Вам закрепить пройденный материал.Один из тестов будет развивать Вашу логику и интеллект!
Чтобы получить доступ к тестам — авторизируйтесь!
Тесты урока:
Приступить к тесту
{«147»:{«id»:»147″,»lesson»:»17″,»type»:»yesno»,»title»:»»,»text»:»index.php — единая точка входа, в которой прописаны все настройки? index.tpl — единый файл-шаблон, в котором прописан head, шапка и подвал сайта. Верно?»,»answer_type»:»Int»,»answer»:»0″,»variables»:{«0″:»»},»group»:»lvl1″,»course»:»2″},»148″:{«id»:»148″,»lesson»:»17″,»type»:»yesno»,»title»:»»,»text»:»Надо ли писать error_reporting в каждой странице модуля?»,»answer_type»:»Int»,»answer»:»1″,»variables»:{«0″:»»},»group»:»lvl1″,»course»:»2″},»149″:{«id»:»149″,»lesson»:»17″,»type»:»yesno»,»title»:»»,»text»:»Надо ли в каждой странице модуля (main.tpl, contacts.tpl) прописывать шапку сайта, подвал и т.д. зная, что это же продублировано в index.tpl?»,»answer_type»:»Int»,»answer»:»1″,»variables»:{«0″:»»},»group»:»lvl1″,»course»:»2″},»150″:{«id»:»150″,»lesson»:»17″,»type»:»yesno»,»title»:»»,»text»:»Чтобы избежать дублирования мы подключаем index. tpl с содержанием шапки и футера внутри наших страницах модуля (main.tpl, contacts.tpl)?»,»answer_type»:»Int»,»answer»:»1″,»variables»:{«0″:»»},»group»:»lvl1″,»course»:»2″},»151″:{«id»:»151″,»lesson»:»17″,»type»:»radio»,»title»:»»,»text»:»Укажите неправильное описание структуры нашего сайта:»,»answer_type»:»Int»,»answer»:»2″,»variables»:{«0″:»В папке libs будут храниться наши функции сайта, а в папке config — настройки сайта»,»1″:»Файл index.php — главное ядро сайта, которое распределяет работу сайта, а variables.php — страница по работе с переменными нашего сайта (модернизация и обработка)»,»2″:»Выполняя домашку и расширяя наш сайт мы должны отредактировать variables.php указав новые модули и страницы, а так же index.php указав подключение новых файлов вроде авторизации»,»3″:»Все утверждения правильные»},»group»:»lvl1″,»course»:»2″},»152″:{«id»:»152″,»lesson»:»17″,»type»:»radio»,»title»:»»,»text»:»Что является грамотной структурой страницы-модуля согласно нашего движка:»,»answer_type»:»Int»,»answer»:»0″,»variables»:{«0″:»Определённый раздел сайта выделяем в модуль, в котором размещаем страницы модуля»,»1″:»Модули только для очень значимого функционала, остальное размещается в static»,»2″:»Модуль разделяется на Вид, Контроллер и Модель (MVC)»,»3″:»В skins мы размещаем контроллер, а в папке modules — ВИД»},»group»:»lvl1″,»course»:»2″},»153″:{«id»:»153″,»lesson»:»17″,»type»:»input»,»title»:»»,»text»:»Укажите имена файлов с расширениями через запятую для главной страницы модуля. Указать надо: имя Контроллера,имя Вида. Без пробела»,»answer_type»:»Full»,»answer»:»main.php,main.tpl»,»variables»:{«0″:»»},»group»:»lvl1″,»course»:»2″},»154″:{«id»:»154″,»lesson»:»17″,»type»:»input»,»title»:»»,»text»:»Введя в браузере site.ru\/index.php?module=game у меня запустится обрабатываться скрипт. Укажите ВСЕ пути файлов участвующие в обработке данной страницы с расширением .php и .tpl в порядке их обработки PHP-интерпретатором через запятую и без пробелов между запятыми. Напоминаю, что правильный полный путь для index.php: .\/index.php, а для default.php — .\/libs\/default.php»,»answer_type»:»Full»,»answer»:».\/index.php,.\/config.php,.\/libs\/default.php,.\/variables.php,.\/modules\/game\/main.php,.\/skins\/default\/index.tpl,.\/skins\/default\/game\/main.tpl»,»variables»:{«0″:»»},»group»:»lvl1″,»course»:»2″},»155″:{«id»:»155″,»lesson»:»17″,»type»:»yesno»,»title»:»»,»text»:»В index.php у нас находится управляющее ядро сайта, которое говорит какие файлы необходимо подключить и в каком порядке. Достаточно ли у Вас знаний сейчас вносить правки в этот файл?»,»answer_type»:»Int»,»answer»:»1″,»variables»:{«0″:»»},»group»:»lvl1″,»course»:»2″},»156″:{«id»:»156″,»lesson»:»17″,»type»:»radio»,»title»:»»,»text»:»Какое из утверждений ошибочное:»,»answer_type»:»Int»,»answer»:»1″,»variables»:{«0″:»В Controller отсутствует вывод информации на экран»,»1″:»В View отсутствует PHP код»,»2″:»В Model не желателен вывод информации на экран и он работает по принципу функций»,»3″:»В View допустимо использовать вспомогательные PHP конструкции с целью — вывести информацию на экран»},»group»:»lvl1″,»course»:»2″}}
{«0″:»147″,»1″:»148″,»2″:»149″,»3″:»150″,»4″:»151″,»5″:»152″,»6″:»153″,»7″:»154″,»8″:»155″,»9″:»156»}
Файлы темы WordPress (иерархия файлов шаблона)
В этом посте речь пойдет о том, какие бывают названия у файлов темы WordPress и за показ какой страницы на сайте отвечает каждый из них. Это очень важные, нужные, и в тоже время очень простые, для понимания, знания. Ими должен обладать каждый, кто работает с WordPress. Ниже полностью расписана структура файлов темы WordPress и порядок их подключения (иерархия).
Об иерархии файлов темы я упоминал в статье «Условные теги в WordPress». А ниже тоже самое, только подробнее и понятнее.
Подключения файлов темы (теория)
Иерархия, в данном случае последовательная проверка, говорит о том, что для вывода одной страницы на сайте, подходят несколько названий файлов. Проверка какой файл будет использован идет поочередно. Т.е. есть список файлов, каждый из них по очереди проверяется на физическое существование, как только найден существующий файл проверка прекращается и найденный файл используется в качестве шаблона.
Например, мы заходим на страницу рубрики «Плагины» http://example.com/category/plugins с ярлыком plugins и id 25. Тогда для генерации кода этой страницы WordPress будет по очереди проверять наличие следующих файлов (проверка прервется на первом существующем файле — именно он будет использован для вывода контента):
- category-plugins. php
- category-25.php
- category.php
- archive.php
- index.php
Полная схема для всех видов страниц и их файлов выглядит так:
Еще одна схема, возможно она понятнее (старая):
менюТипы страниц и названия файлов
Ниже список страниц сайта и отвечающие за них php файлы темы. В этом разделе расписана картинка иерархии файлов темы, которая немного выше.
Ниже указана страница сайта и соответствующий ей список PHP файлов. Такие файлы должны находится в корневой папке темы.
Записи
Страница (запись page)
Запись (запись post)
- single-post-{ярлык_записи}.php
- single-post.php
- single.php
- singular.php
- index.php
Произвольный тип записи
- {любое_название}.php (для древовидного типа с поддержкой шаблонов. С WP 4.7)
- single-{post_type}-{urldecode_post_name}.php
- single-{post_type}-{post_name}.php
- single-{post_type}.php
- single.php
- singular.php
- index.php
Вложение
- {начало_MIME_типа}.php
- {конец_MIME_типа}.php
- {начало_MIME_типа}-{конец_MIME_типа}.php
- attachment.php
- single-attachment-{ярлык_вложения}.php (позволяет указать шаблон для отдельной картинки)
- single-attachment.php (тоже что и attachment.php)
- single.php
- singular.php
- index.php
Под началом и концом MIME типа, имеется виду первая и последняя часть MIME типа, разделенная /. Например, MIME-тип текстового файла: ‘text/plain’ и значит будет проверяться наличие файл text.php
, затем plain. php
, затем text-plain.php
.
Полный список MIME типов смотрите в описании get_allowed_mime_types().
менюАрхивы
Рубрика
- category-{ярлык}.php
- category-{id}.php
- category.php
- archive.php
- paged.php (если страница пагинации)
- index.php
Метка
- tag-{ярлык}.php
- tag-{id}.php
- tag.php
- archive.php
- paged.php (если страница пагинации)
- index.php
Таксономия
- taxonomy-{ярлык_таксономии}-{ярлык_элемента}.php
- taxonomy-{ярлык_таксономии}.php
- taxonomy.php
- archive.php
- paged.php (если страница пагинации)
- index.php
Страница архива типа записи
- archive-{ярлык_типа_записи}. php
- archive.php
- paged.php (если страница пагинации)
- index.php
Страница автора
- author-{nickname}.php
- author-{id}.php
- author.php
- archive.php
- paged.php (если страница пагинации)
- index.php
Страница архива по дате (день, месяц, год)
- date.php
- archive.php
- paged.php (если страница пагинации)
- index.php
404 страница
Страница поиска
Главная страница
- front-page.php
- (логика постоянных страниц, если для главной выбрана страница)
- home.php
- index.php
Страница блога
Страница блога появляется, когда для главной выбрана постоянная страница
Встраивания (embeds)
Шаблоны встраивания используются когда запрашивается запись через REST API. Встраивания появились в версии 4.5 и позволяют встраивать ваши записи в чужие сайты. См. get_post_embed_url()
- embed-{post-type}-{post_format}.php
- embed-{post-type}.php
- embed.php
Чтобы изменить только контент встраивания, можно в теме создать файл embed-content.php и описать там HTML. Оригинальный HTML находится в файле движка /wp-includes/theme-compat/embed-content.php
менюКак это работает
За всю логику: какой файл подключать, отвечает файл ядра wp-includes/template-loader.php. Если разобраться, в нем все описано. Но, это занятие не особо интересное, поэтому я его распишу.
Прежде всего. template-loader.php подключается после того как загрузится вся среда WordPress. После того, как отработает файл wp-load.php и обработается основной запрос — функция wp(). Т.е. template-loader.php подключается в самом-самом конце PHP скрипта…
Сначала срабатывает хук template_redirect. В этом хуке можно произвести какие-то проверки и если надо перенаправить на другой URL. В нем нужно обрывать работу скрипта через die(). Т.е. если этот хук что-то меняет, то на этом работа файла template-loader.php должна закончиться и мы «улетаем» на какую-то другую страницу.
Дальше срабатывает никому не интересный хук exit_on_http_head. Он позволяет сделать так, чтобы при HTTP HEAD запросе что-либо выводилось на экран…
Дальше идут проверки по всем условным тегам где выясняется какой файл шаблона подходит под текущий запрос. Проверяется условный тег, затем еще один и еще… Как только один из условных тегов сработал, вызывается соответствующая функция, которая находит подходящий файл шаблона и возвращает путь до него. Все такие функции описаны в get_query_template().
Дальше — путь до файла темы определен! Теперь он прогоняется через фильтр template_include. Который позволяет нам изменить файл шаблона для текущего запроса.
Дальше, файл подключается в PHP и запускается визуальная часть генерации страницы.
менюФильтры
Иерархию файлов можно изменить через динамические фильтры:
(type)_template_hierarchy — фильтрует массив названий файлов иерархии, по которому будет идти поиск нужного файла. С WP 4.7.
- (type)_template — фильтрует путь до уже определившегося файла шаблона.
Все варианты параметра type смотрите в одноименном параметр $type функции get_query_template(). Вот они:
index
404
archive
post_type_archive
author
category
tag
taxonomy
date
home
frontpage
page
paged
search
single
singular
attachment
comments_popup
Пример использования такого фильтра смотрите в ответе на этот вопрос.
менюДругие файлы темы
Файлы ниже также используются в теме, но они просто подключаемые и не участвуют в иерархии. Например файл sidebar.php подключается в любом файле темы с помощью функции get_sidebar().
Список таких «подключаемых» файлов.
—
Источник
Республиканские органы исполнительной власти — Правительство Республики Башкортостан
Зав. протокольно-организационного отдела
— —
Зав. отделом сопровождения административной реформы
Булатов Артур Нурович
Зав. отделом координации контрольно-надзорной деятельности
Ялалетдинов Радик Фанилевич
+7 347 280-82-79
Зав. отделом развития государственных услуг
Байтуллин Валерий Борисович
+7 (347) 280-84-99
Зав. отделом по делам несовершеннолетних и защите их прав
Ганиев Ильмир Фаизович
+7 347 280-84-93
Зав. отделом взаимодействия с административными органами
Бобрик Олег Павлович
+7 (347) 280-84-34
Факс:
+7 (347) 250-55-79
Зав. отделом мобилизационной подготовки
Галеев Валерий Исламгалеевич+7 (347) 280-85-32
Зав. отделом по обеспечению законодательной деятельности
Давлетова Гульшат Марсовна
+7 (347) 280-83-64
Зав.отделом правовой и антикоррупционной экспертизы
Зиннатуллина Римма Талгатовна
+7 (347) 280-83-59
Факс:
+7 (347) 250-49-39
Зав. отделом судебного представительства
Тактаев Ильнур Ямилевич
+7 (347) 280-83-61
Зав. отделом правового сопровождения инвестиционной деятельности
Сафин Виль Науфилевич
Зав. режимно-секретным отделом
Мугаллимов Игорь Альбертович
+7 (347) 280-84-43
Зав. отделом финансового обеспечения – главный бухгалтер
Минченкова Тамара Ивановна +7 (347) 280-84-45
Факс:
+7 (347) 250-24-79
Зав. отделом кадровой работы
Малейкина Галина Александровна
Структура кода PHP — Vegibit
PHP — интересный язык для работы как для новичков, так и для профессионалов. В этой серии руководств по PHP мы начинаем с первого этажа работы с PHP. Действительно здорово начинать с самого начала даже для более опытных разработчиков, которым нужно освежиться. Часто вы обнаружите, что сложные проблемы часто превращаются в очень простые ошибки. Именно поэтому основы так важны. Они являются фундаментом, на котором вы построите всю свою базу знаний в области программирования.Так что теперь мы рассмотрели, что РНР и историю этого иногда противоречивого языка, давайте начнем получать наши грязные руки с PHP. В этом выпуске мы рассмотрим некоторые из самых основ языка, а также жизненный цикл запроса и то, как PHP подходит для этого. Большая часть этих фрагментов информации — это просто основы хлеба с маслом, которые нам нужно знать, прежде чем мы станем ниндзя на себя. Давайте начнем!
Размещение PHP на вашей веб-странице
Основным способом использования PHP является встраивание его в HTML-страницу.Есть две вещи, которые нужно знать о размещении PHP внутри ваших файлов HTML. Мы знаем, что когда пользователь делает запрос к веб-сайту, он использует HTTP для получения HTML-файла. Веб-сервер, в свою очередь, отправляет файл конечному пользователю, а его веб-браузер интерпретирует этот HTML-код и отображает веб-страницу для просмотра. Это совершенно статично. Чтобы сделать вещи динамичными, давайте добавим немного PHP.
index.php
Php echo ‘Этот текст взят из PHP!’; ?>
|
Php
и ?>
- это открывающие и закрывающие теги PHP. Это то, что сообщает веб-серверу, чтобы он прекратил читать содержимое файла как статический HTML и начал читать содержимое как PHP. Напомним, что это происходит в порядке сверху вниз, и когда больше нет PHP для интерпретации веб-сервером, мы добавляем закрывающий тег, чтобы указать, что мы вернулись к HTML.
Файлы должны иметь расширение .PHP
Любые файлы, которые находятся на вашем веб-сервере, должны иметь расширение .php
для использования PHP на странице. Файлы этого типа могут иметь собственный код HTML и PHP, смешанный вместе, если вы используете открывающие и закрывающие теги PHP.
Альтернативные стили тегов
Существуют альтернативные стили тегов, доступные вам для обозначения мест открытия и закрытия PHP в ваших файлах. Однако имейте в виду, что если вы их используете, вы можете стать целью полиции PHP, поскольку большинство из них - дурной тон. Вот еще два стиля, которые вы можете использовать.
Короткие открытые теги -
и ?>
, а также =
и ?>
- это плохая идея.
Теги стиля ASP - <%
и %>
, а также <% =
и %>
- Это очень плохая идея.
Так почему это плохая идея? Что ж, помните, что одна из целей написания программного обеспечения состоит в том, чтобы ваш код мог работать в как можно большем количестве сред с минимальным количеством требуемых дополнительных настроек. Теперь я знаю, что , вы ленивы , вы хотите ускорить рабочий процесс и сэкономить несколько нажатий клавиш, но дело в том, что вам следует использовать Php
и ?>
в качестве начальных и конечных тегов для PHP, потому что это дает вам максимальную мобильность.Следующие два подойдут, но для этого вам может потребоваться отредактировать файл php.ini. Что делать, если вы пишете плагин для WordPress, и кто-то из дикой природы не может запустить его, потому что вы решили использовать только теги стиля ASP, а их хостинговая компания не разрешает использование тегов стиля ASP? Это не та ситуация, которую вы хотели бы иметь.
PHP для динамических сайтов
Используя PHP, мы можем начать делать наши веб-сайты динамическими. Фактически, вы просматриваете динамический веб-сайт именно на этой странице.Это связано с тем, что большая часть контента, который вы сейчас потребляете, хранится в базе данных, а не в статическом HTML-файле. Используя PHP, мы можем взаимодействовать с базой данных и получать динамически генерируемый контент для обслуживания на основе многих критериев. Но давайте пройдемся перед бегом и начнем с нескольких простых команд.
эхо
Чуть выше мы уже использовали команду echo
в PHP. Используя эту команду, мы можем делать именно то, что она говорит, выводить что-то на экран. Есть и другой способ сделать это.Фактически, почти все, что вы можете сделать в программировании, вы обнаружите, что есть много способов сделать то же самое. Например, мы могли бы переписать наш предыдущий пример, используя команду печати вот так.
index. php
Php print 'Этот текст взят из PHP!'; ?> |
Используем ли мы первый пример echo или второй пример print, они оба будут производить в браузере одно и то же.Фактически, в обоих сценариях, если вы выбираете «Просмотр исходного кода» в своем веб-браузере, вы можете взглянуть на динамически сгенерированный HTML-код, и в обоих случаях он выглядит именно так.
Этот текст взят из PHP! |
Так что это здорово, и вы можете спросить: «Что ж, мне использовать эхо или печать?» В чем разница между echo и print в PHP? Следует помнить о нескольких отличиях.
- echo быстрее При выполнении PHP команда echo будет выполняться быстрее, чем оператор печати. Честно говоря, через миллион лет вы не сможете различить разницу, потому что она такая малая, но факт, что эхо быстрее.
- print - истинная функция В PHP оператор echo не является конструкцией языка, а функция print -. Это делает возможным присвоение возвращаемого значения с помощью оператора печати. Однако это руководство для начинающих, поэтому мы просто будем использовать эхо, если не столкнемся с необходимостью печати.
Изучение цикла ответа на запрос
Ключевым ингредиентом для понимания того, как работают динамические веб-страницы, является изучение цикла ответа на запрос. Это охватывает весь жизненный цикл запроса веб-страницы в вашем браузере с удаленного сервера до ее отображения на экране. Как происходит этот процесс? Представим, что мы используем веб-браузер Google Chrome и запрашиваем просмотр файла index. php
на удаленном сервере Linux, который использует программное обеспечение веб-сервера apache, PHP и базу данных MySQL.Процесс выглядит так.
Chrome отправляет HTTP-запрос. На первом этапе веб-браузер отправляет HTTP-запрос на соответствующий веб-сервер. Это просто вопрос загрузки в ваш браузер чего-то вроде http://example.com/index.php
.
- Apache находит файл Этот запрос интерпретируется Apache, и он ищет в файловой системе файл index.php.
- Файл интерпретируется механизмом PHP. Веб-сервер знает, что этот файл должен запускаться через механизм PHP, поскольку он имеет расширение.php расширение.
- База данных MySQL запрошена Если файл содержит какую-либо логику для выполнения взаимодействия с базой данных, это происходит на этом этапе.
- Вывод отправляется в браузер. Данные возвращаются из базы данных, весь PHP анализируется, а затем все данные упаковываются в окончательный вывод HTML, который отправляется обратно клиенту. Chrome отображает этот HTML-код в браузере и отображает веб-страницу для пользователя.
Интерпретатор PHP не заботится о пробелах
Как и JavaScript, PHP Engine не заботится о пробелах.С помощью JavaScript мы всегда видим, как разработчики минимизируют свой код перед производством. Это удаляет все пробелы и несущественные символы для создания одной массивной строки в значительной степени нечитаемого JavaScript. Однако веб-браузеру все равно, он все равно может запускать JavaScript. То же самое и с PHP. Однако на стороне сервера нет необходимости в минификации, поскольку размер файла не важен. Сам код PHP будет жить на сервере и оставаться на сервере во время выполнения, в отличие от JavaScript, который должен быть отправлен по сети, прежде чем веб-браузер сможет это сделать.
В этом примере функция php будет нормально работать при вызове.
function ssba_shorten ($ urlLong) {$ hmtlBitly = file_get_contents ('http://api. bit.ly/v3/shorten?login=ninja&apiKey=R_supersecretkey&longUrl='.$urlLong); $ arrBitly = json_decode ($ hmtlBitly, true); $ urlShort = $ arrBitly ['данные']; $ urlShort = $ urlShort ['url']; $ hmtlBitly = str_replace ('[]', '', $ hmtlBitly); if ($ urlShort! = '') {Return $ urlShort; } else {return $ urlLong;};} |
Однако вы значительно упростите себе жизнь, если будете использовать стандартное форматирование, чтобы код был удобочитаемым.
1 2 3 4 5 6 7 8 9 10 11 12 13 140002 | function ssba_shorten ($ urlLong) { // получить результаты от bitly и вернуть короткий URL-адрес $ hmtlBitly = file_get_contents ('http: // api.bit.ly/v3/shorten?login=ninja&apiKey=R_supersecretkey&longUrl= '. $ urlLong); $ arrBitly = json_decode ($ hmtlBitly, true); $ urlShort = $ arrBitly ['данные']; $ urlShort = $ urlShort ['url']; $ hmtlBitly = str_replace ('[]', '', $ hmtlBitly); if ($ urlShort! = '') { return $ urlShort; } else { return $ urlLong; }; } |
Если приведенный выше фрагмент не имеет для вас особого смысла, не о чем беспокоиться. Мы используем это только для отображения значения пробелов для кодировщика-человека, которым будете вы, и того факта, что машине все равно, как отформатирован код - она просто читает исходный код, следуя разделителям и управляющим структурам язык как средство его обработки.
Синтаксис комментариев PHP
Теперь мы немного поговорим о комментариях в PHP и синтаксисе их использования. Комментарии настолько важны, что некоторые могут сказать даже более важными, чем сам код. Независимо от того, на каком языке вы программируете, правильные комментарии сэкономят вам и другим программистам, которые работают над проектом, несказанные часы разочарования во время отладки.Забавно то, что когда вы изначально пишете код и приходит время включить некоторые комментарии, так легко думать: «Это настолько очевидно, что здесь делается, зачем мне вообще добавлять какие-либо комментарии? ? » Если вы когда-нибудь задумывались об этом, а затем через полгода или год вернулись к тому же самому коду, чтобы взломать модификацию, вы будете знать, как больно смотреть на этот код и удивляться, что в этом хорошем зеленом название земли, вы думали ?! Теперь примите во внимание тот факт, что вам самому трудно понять, что вы делали в этой более ранней версии кода. А теперь подумайте о каком-нибудь другом незадачливом разработчике, которому пришлось взять на себя ваши обязанности и кодовую базу. Если вам сложно во всем разобраться, подумайте, что должен чувствовать этот другой разработчик! Эти примеры, которые мы здесь покажем, действительно не нуждаются в комментариях, но мы воспользуемся этими простыми примерами, чтобы просто показать, как использовать синтаксис комментариев в ваших собственных файлах php.
1 2 3 4 5 6 7 8 9 10 11 12 13 140002 14 18 19 20 21 22 23 24 25 26 |
Php echo 'Привет, Джимми Боб. '; // Сначала мы говорим привет Джимми Бобу, используя однострочный комментарий в стиле C ++ / * Мы можем так же легко отметить , что мы передаем привет Джимми Бобу, используя многострочный комментарий в стиле , подобный этому * / echo «Джимми Крэк Корн, и мне все равно»; echo «Привет, Джимми, что происходит?»; # Мы можем отметить, что мы спрашиваем Джимми, что происходит, используя комментарий в стиле оболочки ?> |
В приведенном выше фрагменте мы используем все три стиля комментариев, которые вы можете использовать.Вы можете попробовать все из них и выбрать наиболее естественный. Вы можете проявить творческий подход к ним и наметить очень конкретные комментарии в начале различных функций, классов, методов и так далее. Вы обнаружите, что у популярных PHP Framework есть фантастические комментарии.
- Комментарии к стилю C ++ Это комментарии в стиле одной строки с использованием двойной косой черты
//
- Многострочные комментарии Используя открывающий
/ *
и закрывающий* /
, вы можете распределить комментарий по нескольким строкам. - Комментарии стиля оболочки Наконец, у вас есть возможность использовать комментарии стиля оболочки с символом хэштега
#
.
Сводная информация о структуре кода PHP
В этой серии учебных пособий по PHP мы рассмотрели некоторые ключевые составляющие, позволяющие быстрее освоить общую структуру языка PHP. Можете ли вы сделать что-нибудь крутое в PHP? Ну, наверное, не только с информацией из этой статьи. Ключ, однако, в том, что, хотя вы можете захотеть перейти на самые продвинутые PHP-фреймворки и делать потрясающие вещи - если вы не знаете эту базовую структуру кода, который он использует, вы не будете иметь представления о том, что делать, когда что-то не идите направо.Будут времена, когда что-то пойдет не так! Имея это в виду, мы рассмотрели некоторые реальные базовые вещи здесь, такие как встраивание php на веб-страницу, использование правильных начальных и конечных тегов для вашего кода php, использование правильного расширения в файлах php, использование php для динамических веб-сайтов, обучение о жизненном цикле ответа на запрос, соображениях относительно пробелов, комментариях к PHP-коду и многом другом. Теперь мы готовы заняться и начать узнавать о том, как делать крутые вещи на php, в следующих статьях.
Как выбрать структуру каталогов проекта PHP?
Это руководство покажет вам несколько дополнительных и умных способов структурирования файлов и каталоги в вашем проекте PHP.
PHP очень либерален и настраивается, когда дело доходит до структурирования проекта. каталоги. Если вы планируете создать собственное обычное приложение PHP, вы нужно будет изобрести структуру для вашего проекта. Вам понадобится логичный и понятная структура каталогов.
PHP-приложения и фреймворки с открытым исходным кодом имеют свои собственные способы структурирования. каталоги и файлы. Если вы используете фреймворк или CMS, у вас уже есть определена структура каталогов. См. Ссылки внизу для некоторых распространенных программ с открытым исходным кодом Примеры.
Сложность и характер проекта влияют на требуемые каталоги. Например, веб-приложение будет иметь дополнительный общедоступный каталог по сравнению с приложение командной строки.
Структурируйте свой проект так, как вы считаете его наиболее логичным и полезным.
Пример структуры каталогов
Давайте посмотрим на следующий пример.
проект-корень /
.git / # Конфигурация Git и исходный каталог
assets / # Не скомпилированный / необработанный CSS, LESS, Sass, JavaScript, изображения
bin / # Скрипты командной строки
config / # Конфигурация приложения
node_modules / # Node.js-модули для управления интерфейсом
public / # Общедоступные файлы на http://example.com/
index.php # Основная точка входа - фронт-контроллер
...
src / # файлы исходного кода PHP
Контроллер / # Контроллеры
...
templates / # Файлы шаблонов
tests / # Модульные и функциональные тесты
translations / # файлов переводов
en_US.yaml
var / # Временные файлы приложения
cache / # Файлы кеша
log / # Файлы журнала для конкретного приложения
vendor / # сторонние пакеты и компоненты с Composer
.gitignore # Игнорируемые файлы и каталоги в Git (node_modules, var, vendor . ..)
composer.json # Файл зависимостей композитора
phpunit.xml.dist # файл конфигурации PHPUnit
В приведенном выше примере список каталогов в корневом каталоге длиннее и меньше. глубина, чтобы найти конкретный файл и быстрее найти его. Вы можете объединить определенные типы файлов вместе или рефакторинг, которые по-разному подходят для вашего проекта потребности. Найдите баланс для вашего варианта использования между слишком длинным списком элементов и слишком много вложенных папок для просмотра.По возможности применяйте разделение проблем.
Общий справочник
Веб-приложениям требуется общедоступный каталог. В приведенном выше примере используется имя общественный
. Вы можете легко использовать pub
, web
, public_html
или любое другое имя.
Этот каталог будет доступен для внешнего мира при использовании веб-сервера.
По соображениям безопасности вы должны поместить только минимальный набор файлов, необходимых для
ваше приложение для работы. Сюда входит один передний контроллер, например,
Индекс .php
и статические файлы внешнего интерфейса (CSS, JavaScript, изображения…).
Конфигурация
Если у вас несколько файлов конфигурации, рекомендуется использовать
файлы конфигурации в отдельном каталоге. Несколько примеров: config
или и т. Д.
или app / config
… Избегайте размещения файлов конфигурации в
общедоступный каталог.
Композитор
Composer помогает вам упростить и улучшить многие аспекты вашего PHP-приложения.Например, автозагрузка классов PHP, запуск скриптов, автоматизация установка, управление сторонними зависимостями и многое другое.
Специальный файл по умолчанию composer.json
расположен в верхнем корневом каталоге
проэкт. В этом файле вся конфигурация и зависимости Composer указаны
определенный.
Composer создает каталог vendor
в корневом каталоге проекта, который
содержит сторонние зависимости (библиотеки, компоненты, плагины…).
Файлы исходного кода PHP
Когда речь идет о PHP-классах многих проектов, добавьте их в каталог с именем src
.
или приложение
.
Приведенный выше пример включает все файлы PHP в каталоге src
. К ним в основном относятся
классы. Композитор также включает в себя очень интересную функцию - автозагрузку PSR-4.
Добавление частей autoload
и autoload-dev
в файл composer.json
приведет к
автозагрузить для вас все классы:
{
"автозагрузка": {
"пср-4": {
"Приложение \\": "src /"
}
},
"autoload-dev": {
"пср-4": {
"Приложение \\ Тесты \\": "тесты /"
}
}
}
В современных приложениях PHP структурирование файлов PHP в каталоге src
является частью
объектно-ориентированного программирования и шаблонов проектирования.Представлено каждое пространство имен
с подкаталогом в каталоге src
.
Например:
проект-корень /
...
src /
Контроллер / # Классы для управления запросами и ответами путем отображения
# шаблоны с логикой из сервисов и / или данными из БД
Model / # Классы для хранения значений из базы данных
Utils / # Application Services - бизнес-логика
...
...
Следуйте принципам шаблонов проектирования ООП при добавлении классов в пространства имен.
Тесты
В идеале ваше приложение должно также включать тесты. В приведенном выше примере используется тесты
каталог.
Передняя часть
В зависимости от сложности проекта хорошей практикой является разделение клиентской части файлы (CSS, Sass, LESS, JavaScript, изображения…) и внутренние файлы PHP (исходный код PHP код, шаблоны, конфигурация приложения, модульные тесты…) на два отдельных репозитории.
В приведенном выше примере каталог node_modules
является стандартным каталогом (аналогично
to Composer , поставщик
), управляемый Node. js tooling system - npm или yarn.
Вместо разделения проекта на два репозитория используется каталог assets
.
используется для хранения одного или нескольких некомпилированных необработанных изображений из JavaScript, CSS, SaSS, LESS, изображений
и аналогичные файлы ресурсов, которые компилируются и обрабатываются в общедоступном каталоге
.
В случае, если вам не понадобится более сложная и сложная внешняя обработка, вы можете
поместите эти веб-ресурсы непосредственно в общедоступный каталог
.
Как изменить каталог поставщика Composer по умолчанию?
По умолчанию Composer создает каталог vendor
.Смена названия не
распространенный подход, потому что это стандартное имя, используемое в экосистеме PHP.
Однако переименование может быть выполнено путем установки специальной переменной окружения. COMPOSER_VENDOR_DIR
:
COMPOSER_VENDOR_DIR = lib composer требует phpunit / phpunit
или вручную добавив конфигурацию vendor-dir
в composer. json
:
{
...
"config": {
"vendor-dir": "lib"
}
...
}
Как настроить структуру каталогов при использовании виртуального хостинга?
В случае, если вы будете развертывать свое PHP-приложение на общих хостингах с существующие и предварительно определенные местоположения каталогов, в которые вы можете загружать частные и общедоступные файлы, вам нужно будет настроить структуру каталогов проекта соответственно.
Всегда избегайте размещения чего-либо, кроме общедоступных файлов приложения, в
корневой каталог документов, например public_html
, htdocs
или аналогичный.
Некоторые панели управления могут позволить вам определить корень документа, отличный от по умолчанию:
public_html / # Корневой каталог документов панели управления по умолчанию
your-project / # Ваш проект с желаемой структурой каталогов
...
config /
...
public / # Установить этот каталог как новый корень документа
src /
. ..
См. Также
Пример базового шаблона PHP для файловой структуры с примером кода | автор: Steve Sohcot
Шаблон кода для каждой страницы будет выглядеть так:Вы увидите , очень (опять же, на на каждой странице), это то, что я включаю файл конфигурации. Я поставил перед именем файла префикс «a_», чтобы оно отображалось первым в алфавитном порядке при сортировке по имени файла.
Файл конфигурации:
В этом примере файл конфигурации определяет, на какой странице вы находитесь, и устанавливает некоторые переменные, которые позже будут отображать это содержимое.Если вы используете базу данных, строка подключения также будет находиться здесь.
Возвращаясь к шаблону, вы заметите, что я поместил все в теге HEAD в отдельный файл.
Содержимое, импортированное в тег HEAD:
Это позволяет каждой странице иметь свой собственный уникальный заголовок (как определено в файле конфигурации).
На странице «index» (также определяемой одной из переменных в файле конфигурации) я показываю теги META. На не домашних страницах я этого не показываю.
CSS (и JavaScript) обычно хранятся во внешних файлах.Список файлов, которые вы хотите включить, может со временем меняться. Например, вы хотите добавить новую библиотеку JavaScript. Теперь вы можете легко импортировать этот код в всех своих страниц!
Остальные включаемые файлы предназначены для оформления и содержания. В этом примере я разбил его на три части:
1) Верхняя часть дизайна:
Здесь у меня просто общий заголовок. Часто навигация включается в этот файл, однако в демонстрационных целях я разделил его на два файла.
2) Навигация:
Код PHP динамически включает дополнительный класс для каждой ссылки, так что в зависимости от того, на какой странице вы находитесь, эта ссылка будет выделена (указывая, что она «активна»).
Обновление: было несколько комментариев о том, что эта часть не работает. Попробуйте напечатать $ _SERVER [«SCRIPT_NAME»] , чтобы увидеть каталог, в котором вы находитесь. В моем примере я создал каталог под названием «php-template» (и вы, вероятно, не используете тот же самый!).
3) Нижний колонтитул:
Там есть код для динамического отображения текущего года (так что вам не придется вручную менять его каждый год!).
Я предпочитаю иметь свои включаемые файлы с расширением .php . Я знаю, что некоторые люди предпочитают использовать такие расширения, как .html или .inc (чтобы обозначить его как «включенный» файл), но так:
- Исходный код не отображается, если кто-то перешел к этому файлу. прямо на сервере. Это более важно для строк подключения к базе данных.
- В нем могут быть другие функции PHP (например, включить другой файл).
Надеюсь, с этого вы начнете.Скорее всего, у вас будут варианты кода из моего примера.
Одним из изменений может быть DIV с идентификатором «main-content». Вы можете потенциально:
- Поместите открывающий тег DIV в design-top.php
- Создайте дополнительный файл с именем design-bottom.php , который имеет закрывающий тег DIV (который был открыт в другом файле).
Вы также можете поместить открывающие теги HTML и BODY в включаемый файл, а закрывающие эти теги - в отдельный файл.Включив эти дополнительные файлы (или просто переместив эти теги в файлы, которые вы уже включили), код для каждого файла действительно будет иметь только содержимого, предназначенного для этой страницы.
Структура каталогов - Laravel - PHP Framework для веб-мастеров
Введение
Стандартная структура приложения Laravel предназначена для обеспечения отличной отправной точки как для больших, так и для малых приложений. Но вы можете организовать свое приложение так, как вам нравится.Laravel практически не накладывает ограничений на расположение любого данного класса - до тех пор, пока Composer может автоматически загружать класс.
Корневой каталог
Каталог приложений
Каталог app
содержит основной код вашего приложения. Вскоре мы рассмотрим этот каталог более подробно; однако почти все классы в вашем приложении будут в этом каталоге.
Каталог начальной загрузки
Каталог начальной загрузки
содержит приложение .php
, который загружает фреймворк. В этом каталоге также находится каталог cache
, который содержит файлы, сгенерированные фреймворком для оптимизации производительности, такие как файлы кэша маршрутов и служб. Обычно вам не нужно изменять какие-либо файлы в этом каталоге.
Каталог конфигурации
Каталог config
, как следует из названия, содержит все файлы конфигурации вашего приложения. Это отличная идея - прочитать все эти файлы и ознакомиться со всеми доступными вам вариантами.
Каталог базы данных
Каталог базы данных
содержит миграции ваших баз данных, фабрики моделей и начальные числа. При желании вы также можете использовать этот каталог для хранения базы данных SQLite.
Общедоступный каталог
Общедоступный каталог
содержит файл index.php
, который является точкой входа для всех запросов, поступающих в ваше приложение, и настраивает автозагрузку. В этом каталоге также находятся ваши активы, такие как изображения, JavaScript и CSS.
Справочник ресурсов
Каталог ресурсов
содержит ваши представления, а также необработанные, нескомпилированные ресурсы, такие как CSS или JavaScript. В этом каталоге также находятся все ваши языковые файлы.
Каталог маршрутов
Каталог routes
содержит все определения маршрутов для вашего приложения. По умолчанию в Laravel включены несколько файлов маршрутов: web.php
, api.php
, console.php
и каналов.php
.
Файл web.php
содержит маршруты, которые RouteServiceProvider
помещает в группу промежуточного программного обеспечения web
, которая обеспечивает состояние сеанса, защиту CSRF и шифрование файлов cookie. Если ваше приложение не предлагает RESTful API без сохранения состояния, то вполне вероятно, что все ваши маршруты, скорее всего, будут определены в файле web.php
.
Файл api.php
содержит маршруты, которые RouteServiceProvider
помещает в группу промежуточного программного обеспечения api
.Эти маршруты предназначены для того, чтобы не иметь состояния, поэтому запросы, поступающие в приложение по этим маршрутам, предназначены для аутентификации с помощью токенов и не будут иметь доступа к состоянию сеанса.
В файле console.php
вы можете определить все консольные команды на основе закрытия. Каждое замыкание привязано к экземпляру команды, что обеспечивает простой подход к взаимодействию с методами ввода-вывода каждой команды. Несмотря на то, что этот файл не определяет маршруты HTTP, он определяет точки входа (маршруты) в ваше приложение на основе консоли.
В файле channels.php
вы можете зарегистрировать все каналы вещания событий, которые поддерживает ваше приложение.
Каталог хранилища
Каталог storage
содержит ваши журналы, скомпилированные шаблоны Blade, сеансы на основе файлов, кеши файлов и другие файлы, созданные фреймворком. Этот каталог разделен на каталоги app
, framework
и logs
. Каталог app
может использоваться для хранения любых файлов, созданных вашим приложением.Каталог framework
используется для хранения файлов и кэшей, сгенерированных платформой. Наконец, каталог logs
содержит файлы журналов вашего приложения.
Каталог storage / app / public
может использоваться для хранения файлов, созданных пользователями, таких как аватары профиля, которые должны быть общедоступными. Вы должны создать символическую ссылку в public / storage
, которая указывает на этот каталог. Вы можете создать ссылку, используя Artisan-команду php artisan storage: link
.
Справочник тестов
Каталог tests
содержит ваши автоматизированные тесты. Примеры модульных тестов и функциональных тестов PHPUnit предоставляются по умолчанию. Каждый тестовый класс должен иметь суффикс Test
. Вы можете запускать свои тесты с помощью команд phpunit
или php vendor / bin / phpunit
. Или, если вы хотите более подробное и красивое представление результатов ваших тестов, вы можете запустить их, используя команду Artisan php artisan test
.
Справочник поставщиков
Каталог vendor
содержит ваши зависимости Composer.
Каталог приложений
Большая часть вашего приложения находится в каталоге app
. По умолчанию этот каталог находится в пространстве имен под App
и автоматически загружается Composer с использованием стандарта автозагрузки PSR-4.
Каталог app
содержит множество дополнительных каталогов, таких как Console
, Http
и Providers
.Думайте о каталогах Console
и Http
как о предоставлении API для ядра вашего приложения. Протокол HTTP и интерфейс командной строки являются механизмами взаимодействия с вашим приложением, но на самом деле не содержат логики приложения. Другими словами, это два способа подачи команд вашему приложению. Каталог Console
содержит все ваши Artisan-команды, а каталог Http
содержит ваши контроллеры, промежуточное ПО и запросы.
Множество других каталогов будет создано внутри каталога app
, поскольку вы используете Artisan-команды make
для создания классов.Так, например, каталог app / Jobs
не будет существовать, пока вы не выполните Artisan-команду make: job
для создания класса задания.
{подсказка} Многие классы в каталоге
app
могут быть сгенерированы Artisan с помощью команд. Чтобы просмотреть доступные команды, запустите командуphp artisan list make
в своем терминале.
Справочник вещания
Каталог Broadcasting
содержит все классы широковещательных каналов для вашего приложения. Эти классы создаются с помощью команды make: channel
. Этот каталог не существует по умолчанию, но будет создан для вас, когда вы создадите свой первый канал. Чтобы узнать больше о каналах, ознакомьтесь с документацией по трансляции событий.
Каталог консоли
Каталог Console
содержит все пользовательские команды Artisan для вашего приложения. Эти команды могут быть сгенерированы с помощью команды make: command
. В этом каталоге также находится ядро вашей консоли, в котором регистрируются ваши пользовательские команды Artisan и определяются ваши запланированные задачи.
Справочник событий
Этот каталог не существует по умолчанию, но будет создан для вас с помощью Artisan-команд event: generate
и make: event
. В каталоге Events
находятся классы событий. События могут использоваться для предупреждения других частей вашего приложения о том, что произошло определенное действие, обеспечивая большую гибкость и развязку.
Справочник исключений
Каталог Exceptions
содержит обработчик исключений вашего приложения, а также является хорошим местом для размещения любых исключений, создаваемых вашим приложением.Если вы хотите настроить, как ваши исключения регистрируются или обрабатываются, вам следует изменить класс Handler
в этом каталоге.
Каталог Http
Каталог Http
содержит ваши контроллеры, промежуточное ПО и запросы форм. Практически вся логика обработки запросов, поступающих в ваше приложение, будет размещена в этом каталоге.
Справочник вакансий
Этот каталог не существует по умолчанию, но будет создан для вас, если вы выполните команду Artisan make: job
.В каталоге Jobs
хранятся задания в очереди для вашего приложения. Задания могут ставиться в очередь вашим приложением или выполняться синхронно в течение текущего жизненного цикла запроса. Задания, которые выполняются синхронно во время текущего запроса, иногда называют «командами», поскольку они являются реализацией шаблона команд.
Справочник слушателей
Этот каталог не существует по умолчанию, но будет создан для вас, если вы выполните команду Artisan event: generate
или make: listener
.Каталог Listeners
содержит классы, которые обрабатывают ваши события. Слушатели событий получают экземпляр события и выполняют логику в ответ на запускаемое событие. Например, событие UserRegistered
может обрабатываться прослушивателем SendWelcomeEmail
.
Почтовый каталог
Этот каталог не существует по умолчанию, но будет создан для вас, если вы выполните команду Artisan make: mail
. Каталог Mail
содержит все ваши классы, которые представляют электронные письма, отправленные вашим приложением.Почтовые объекты позволяют инкапсулировать всю логику создания электронной почты в одном простом классе, который может быть отправлен с помощью метода Mail :: send
.
Каталог моделей
Каталог Models
содержит все классы вашей модели Eloquent. Eloquent ORM, включенный в Laravel, предоставляет красивую и простую реализацию ActiveRecord для работы с вашей базой данных. Каждая таблица базы данных имеет соответствующую «Модель», которая используется для взаимодействия с этой таблицей.Модели позволяют запрашивать данные в таблицах, а также вставлять новые записи в таблицу.
Каталог уведомлений
Этот каталог не существует по умолчанию, но будет создан для вас, если вы выполните команду Artisan make: notification
. В каталоге Notifications
содержатся все «транзакционные» уведомления, которые отправляет ваше приложение, например простые уведомления о событиях, которые происходят в вашем приложении. Уведомления Laravel позволяют абстрагироваться от отправки уведомлений по различным драйверам, таким как электронная почта, Slack, SMS, или хранятся в базе данных.
Каталог политик
Этот каталог не существует по умолчанию, но будет создан для вас, если вы выполните команду Artisan make: policy
. Каталог Policies
содержит классы политик авторизации для вашего приложения. Политики используются, чтобы определить, может ли пользователь выполнить определенное действие с ресурсом.
Справочник поставщиков
Каталог Providers
содержит всех поставщиков услуг для вашего приложения.Поставщики услуг загружают ваше приложение, привязывая службы к контейнеру служб, регистрируя события или выполняя любые другие задачи для подготовки вашего приложения к входящим запросам.
В новом приложении Laravel этот каталог уже будет содержать несколько провайдеров. При необходимости вы можете добавлять своих собственных провайдеров в этот каталог.
Справочник правил
Этот каталог не существует по умолчанию, но будет создан для вас, если вы выполните команду Artisan make: rule
.Каталог Rules
содержит настраиваемые объекты правил проверки для вашего приложения. Правила используются для инкапсуляции сложной логики проверки в простой объект. Для получения дополнительной информации ознакомьтесь с документацией по валидации.
php-pds / skeleton: скелет стандартного пакета PHP.
Эта публикация описывает стандартный каркас файловой системы, подходящий для всех PHP. пакеты.
Пожалуйста, посетите https://github.com/php-pds/skeleton_research для справки. Информация.
Инструменты командной строки для проверки
или создания пакетов, соответствующих стандарту PDS
, которые включены в этот стандарт, описаны здесь.
Ключевые слова «ДОЛЖЕН», «НЕ ДОЛЖЕН», «ОБЯЗАТЕЛЬНО», «ДОЛЖЕН», «НЕ ДОЛЖЕН», «ДОЛЖЕН», «НЕ ДОЛЖЕН», «РЕКОМЕНДУЕТСЯ», «МОЖЕТ» и «ДОПОЛНИТЕЛЬНО» в этой публикации должны быть интерпретируется, как описано в RFC 2119.
Сводка
Пакет ДОЛЖЕН использовать эти имена для этих корневых каталогов:
Если в пакете есть каталог корневого уровня для... | ... тогда он ДОЛЖЕН называться: |
---|---|
Исполняемые файлы командной строки | бункер / |
файлы конфигурации | конфигурация / |
файлы документации | документы / |
файлы веб-сервера | общественный / |
файлы других ресурсов | ресурсов / |
Исходный код PHP | SRC / |
код теста | тестов / |
Пакет ДОЛЖЕН использовать эти имена для файлов корневого уровня:
Если в пакете есть файл корневого уровня для. .. | ... тогда он ДОЛЖЕН называться: |
---|---|
журнал изменений между выпусками | ИЗМЕНЕНИЕ (. *) |
Рекомендации для участников | ДОПОЛНИТЕЛЬНАЯ (. *) |
информация о лицензировании | ЛИЦЕНЗИЯ (. *) |
информация о самой упаковке | README (. *) |
Пакет ДОЛЖЕН включать файл корневого уровня с указанием лицензирования и авторские права на содержимое пакета.
Каталоги корневого уровня
бин /
Если пакет предоставляет каталог корневого уровня для исполняемого файла командной строки
файлов, он ДОЛЖЕН называться bin /
.
Настоящая публикация не определяет структуру и содержание каталог.
конфиг /
Если пакет предоставляет каталог корневого уровня для файлов конфигурации, он ДОЛЖЕН
называться config /
.
Настоящая публикация не определяет структуру и содержание каталог.
документов /
Если пакет предоставляет каталог корневого уровня для файлов документации, он ДОЛЖЕН
называться docs /
.
Настоящая публикация не определяет структуру и содержание каталог.
общедоступные /
Если пакет предоставляет каталог корневого уровня для файлов веб-сервера, он ДОЛЖЕН быть
под названием public /
.
Настоящая публикация не определяет структуру и содержание каталог.
Н.б .: Этот каталог МОЖЕТ быть задуман как корень документов веб-сервера. В качестве альтернативы МОЖЕТ быть так, что файлы будут обслуживаться динамически через другие код, скопированный или связанный с "реальным" корнем документа, или управляемый другим способом чтобы они стали общедоступными в сети.
ресурсов /
Если пакет предоставляет каталог корневого уровня для других файлов ресурсов, он ДОЛЖЕН
называться ресурсов /
.
Настоящая публикация не определяет структуру и содержание каталог.
src /
Если пакет предоставляет каталог корневого уровня для файлов исходного кода PHP, он
ДОЛЖЕН называться src /
.
Настоящая публикация не определяет структуру и содержание каталог.
тестов /
Если пакет предоставляет каталог корневого уровня для тестовых файлов, он ДОЛЖЕН быть назван тестов /
.
Настоящая публикация не определяет структуру и содержание каталог.
Другие каталоги
Пакет МОЖЕТ содержать другие каталоги корневого уровня для целей, не описанных этой публикацией.
Эта публикация не определяет структуру и содержание других каталоги корневого уровня.
Файлы корневого уровня
ИЗМЕНЕНИЕ
Если пакет предоставляет файл корневого уровня со списком изменений с момента последнего
выпуск или версия, он ДОЛЖЕН называться CHANGELOG
.
МОЖЕТ иметь расширение имени файла в нижнем регистре, указывающее на формат файла.
Настоящая публикация не определяет структуру и содержание файл.
ДОПОЛНИТЕЛЬНО
Если пакет предоставляет файл корневого уровня, описывающий, как внести свой вклад в
пакет ДОЛЖЕН быть назван СОДЕЙСТВУЮЩИМ
.
МОЖЕТ иметь расширение имени файла в нижнем регистре, указывающее на формат файла.
Настоящая публикация не определяет структуру и содержание файл.
ЛИЦЕНЗИЯ
Принимая во внимание, что потребители упаковки могут нарушать закон об авторском праве при копировании нелицензионная интеллектуальная собственность, пакет ДОЛЖЕН включать файл корневого уровня с указанием условий лицензирования и авторских прав на содержимое пакета.
Если пакет предоставляет файл корневого уровня с указанием лицензии и авторских прав
В соответствии с условиями пакета он ДОЛЖЕН называться ЛИЦЕНЗИЯ
.
МОЖЕТ иметь расширение имени файла в нижнем регистре, указывающее на формат файла.
Настоящая публикация не определяет структуру и содержание файл.
README
Если пакет предоставляет файл корневого уровня с информацией о пакете
сам он ДОЛЖЕН называться README
.
МОЖЕТ иметь расширение имени файла в нижнем регистре, указывающее на формат файла.
Настоящая публикация не определяет структуру и содержание файл.
Другие файлы
Пакет МОЖЕТ содержать другие файлы корневого уровня для целей, не описанных в это издание.
Эта публикация не определяет структуру и содержание других файлы корневого уровня.
О структурировании PHP-проектов - Никола Поша
Неотъемлемой частью каждого программного проекта является то, как вы его структурируете, что включает в себя организацию файлов и источников в каталоги, соглашения об именах и т. Д.По мере роста вашего приложения возрастает и необходимость его структурирования, чтобы им было легко управлять и поддерживать.
В большинстве случаев структура среднестатистического PHP-приложения диктуется или зависит от используемой структуры, а я против этого.
Без намерения быть навязчивым и без какого-либо предубеждения в отношении конкретной структуры, я поделюсь с вами, как я думаю об организации моих проектов PHP.
Структура каталогов
Первое впечатление - самое важное, что они говорят, и когда дело доходит до проектов, вы получаете его через структуру каталогов.Мне больше всего подходит этот:
bin / # исполняемые файлы командной строки
config / # файлы конфигурации
общедоступные / # файлы веб-сервера, ресурсы
ресурсы / # другие файлы ресурсов
src / # Исходный код PHP
шаблоны / # файлы просмотра и макета
тесты / # тестовый код
Это в значительной степени стандартно для приложений, но также и для библиотек, тогда как в их случае вряд ли можно найти каталоги public /
или templates /
.Кроме того, библиотеки обычно имеют следующие типы файлов: docs /
, CHANGELOG
, LICENSE
, README
. Конечно, они могут быть и в приложениях.
Я считаю эту структуру каталогов независимым от фреймворка , и на его основе мне удалось успешно построить различные проекты, в которых использовались разные фреймворки, такие как Zend Expressive, Slim и Laravel.
Недавно я узнал, что существует инициатива PHP-PDS, которая предлагает стандарт для структуры каталогов пакетов PHP.Я решительно поддерживаю такие попытки по тем же причинам, по которым я восхищаюсь работой и усилиями PHP-FIG. Я был рад видеть, что используемые мной соглашения об именах полностью соответствуют предложенному стандарту.
Исходный код PHP
Что касается представленной структуры каталогов, у вас может возникнуть вопрос: «А как насчет каталога app /?», И мой ответ на это: нет каталога app /
, и не должно быть . Все, кроме src /
, вносит ненужный уровень сложности.
Теперь, когда у нас есть автозагрузчик PSR-4 и Composer, все, что вам нужно сделать, это использовать пространства имен . Так, например, вместо app / controllers /
у вас будет src / Controller /
. Благодаря этому структура каталогов становится простой и однозначной. То же самое и с автозагрузкой, поскольку нет необходимости в каком-либо настраиваемом механизме автозагрузки или фреймворке. Единственная директива для composer.json
выполняет всю работу:
{
"автозагрузка": {
"пср-4": {
"MyApp \\": "src /",
}
}
}
Теперь, когда мы развенчали все мифы о том, где должны располагаться исходные коды PHP, давайте рассмотрим варианты их организации в каталоге src /
, потому что именно там и находится сок.
Группировка по архетипу
Распространенная тенденция - организовывать вещи по их архетипам, например:
src /
Контроллер /
Юридическое лицо/
Репозиторий /
Служба/
Это допустимо для небольших приложений, но все же заставляет разработчика часто переключать несколько каталогов при работе над определенной функцией. Кроме того, этот подход плохо масштабируется, поэтому в случае более 20 контроллеров, сущностей или чего-то еще, структура каталогов становится громоздкой и неэффективной, и разработчикам становится все труднее находить нужные материалы.
Группировка по признаку
Идея здесь в том, что когда вы ищете код , который создает функцию , он находится в одном месте. Такой подход приводит к интуитивно понятной структуре каталогов, которая говорит сама за себя, тогда как код организован на основе функциональных областей . Только заглянув в каталог src /
, разработчик может сразу понять, что делает приложение .
Если мы возьмем простой веб-сайт электронной коммерции в качестве примера, вот как все должно быть организовано в соответствии с этим подходом:
src /
Корзина /
Корзина.php
CartRepository.php
CartRepositoryFactory.php
CartService.php
CartServiceFactory. php
Товар/
Product.php
ProductCategory.php
ProductRepository.php
ProductRepositoryFactory.php
ProductService.php
ProductServiceFactory.php
Пользователь/
User.php
UserRepository.php
UserRepositoryFactory.php
UserService.php
UserServiceFactory.php
Я не особо вдавался в подробности реальных классов, интерфейсов и т. Д., потому что я хотел сосредоточиться на группировке вещей.
Вы можете возразить, что, например, если для функции существует несколько сервисов, было бы разумно выполнить некоторую группировку архетипов. Вы, , можете ввести дополнительную группировку по типу внутри функции, но я предпочитаю более плоскую структуру, пока не пойму конкретную ценность при создании нового каталога. Например, я вижу ценность в хранении контроллеров и команд CLI (мне нравится консоль Symfony) в специальных пространствах имен:
src /
Пользователь/
HTTP /
UserController. php
CLI /
CreateUserCommand.php
User.php
UserRepository.php
UserRepositoryFactory.php
UserService.php
UserServiceFactory.php
Отдельный домен и код общего назначения
Существует большая вероятность, что помимо кода, специфичного для домена, потребуется создать некоторый общий, многоразовый, подобный фреймворку код внутри каталога src /
, например, пользовательский обработчик журнала (хотя, скорее всего, он уже есть в Monolog) , облегчение кеширования, фильтры и т. д.Этот материал не является логикой вашей предметной области, он не специфичен для вашего приложения и, вероятно, может повторно использоваться между проектами. Более того, он должен быть не частью вашего приложения, а скорее в отдельной библиотеке и в отдельном репозитории.
Я видел решение, в котором весь универсальный код помещен в отдельное пространство имен, например MyApp \ Framework
или MyApp \ Common
:
src /
Корзина /
Рамки/
Регистратор /
Кэш /
Товар/
Пользователь/
Это совершенно нормально, но я вижу в этом подходе недостаток, который связан не с тем, как он влияет на приложение, содержащее этот универсальный код, а с самим кодом. Помните, что в идеале этот код должен находиться в отдельном репозитории, и усилия по его перемещению также потребуют избавления от этой дополнительной «Framework» или «Common» части пространства имен, что, в свою очередь, требует не только изменения всех определений классов. , но и обычаи.
По этой причине я выбираю совершенно другой подход, в то время как сам код домена изолирован в отдельном пространстве имен. Что важно в этом подходе, так это то, что вы разумно выбираете имя для пространства имен верхнего уровня. MyApp
, наверное, не лучший выбор с точки зрения извлечения универсального кода в отдельный репозиторий.При разработке пространства имен верхнего уровня не выходите за рамки проекта, над которым вы работаете. Как правило, это должно быть название вашей компании, бренда или, в конечном счете, ваше собственное имя. Что касается части пространства имен кода домена, она обычно должна описывать то, что делает приложение, например, Eshop
, но я предпочитаю использовать для этих целей общее слово - Domain
:
src /
Кэш /
Домен/
Корзина /
Товар/
Пользователь/
Регистратор /
В результате вы получите такие пространства имен, как Company \ Cache
и Company \ Domain \ User
. Теперь, когда вы решите извлечь это облегчение кэша в отдельную многократно используемую библиотеку, никаких изменений в отношении его пространства имен не требуется.
Заключительные мысли
Код местоположения должен быть интуитивно понятным и быстрым. Соответствующее структурирование приложения экономит массу времени и усилий разработчиков.
Суммируем:
- Не позволяйте фреймворку диктовать вашу структуру каталогов
- Хранить все источники PHP в каталоге
src /
- Группировка по признаку, а не по архетипу
- Не смешивайте домен и универсальный код
Управляющие структуры PHP: If else, Switch Case
- Подробности
Что такое структура управления?
Выполнение кода можно сгруппировать по категориям, как показано ниже.- Последовательный - это включает выполнение всех кодов в том порядке, в котором они были записаны.
- Решение - это решение включает выбор из нескольких вариантов. Выполняемый код зависит от значения условия.
Управляющая структура - это блок кода, который определяет путь выполнения программы в зависимости от значения установленного условия.
Давайте теперь посмотрим на некоторые управляющие структуры, которые поддерживает PHP.
PHP IF Else
If… then ... else - это простейший элемент управления структура .Он оценивает условия с помощью логической логикиКогда использовать if… then… else
- У вас есть блок кода, который должен выполняться, только если выполняется определенное условие
- У вас есть два варианта, и вы должны выбрать один.
- If… then… else if… используется, когда вам нужно выбрать более двух опций и вы должны выбрать один или несколько
Синтаксис Синтаксис if… then… else;
Php if (условие верно) { блок один еще блок два } ?>
ЗДЕСЬ,
- « if (condition is true)» - это управляющая структура
- « block one » - это код, который будет выполняться, если условие истинно
- {… else …} - это откат, если условие ложно
- « блок два » - это блок кода, выполняемый, если условие ложно
Как это работает Блок-схема, показанная ниже, показывает, как если, то… иначе структура управления работает
Давайте посмотрим на это в действии В приведенном ниже коде используется «if… then… else» для определения большего значения между двумя числами.
Php $ first_number = 7; $ second_number = 21; if ($ first_number> $ second_number) { echo "$ first_number больше, чем $ second_number"; }еще{ echo "$ second_number больше, чем $ first_number"; } ?>
Вывод:
21 больше 7
PHP Switch Case
Switch… case аналогичен if then… else control structure.Только выполняет отдельный блок кода в зависимости от значения условия.
Если ни одно условие не было выполнено, выполняется блок кода по умолчанию.
Он имеет следующий базовый синтаксис.
Php switch (condition) { значение case: // блок кода для выполнения перемена; case value2: // блок кода для выполнения перемена; дефолт: // код блока по умолчанию перемена; } ?>
ЗДЕСЬ,
- «переключатель (…) {…}» - это код блока структуры управления.
- «значение случая: случай…» - это блоки кода, которые должны выполняться в зависимости от значение условия
- «по умолчанию:» - это блок кода, который должен выполняться, когда никакое значение не соответствует условию
Как это работает
Блок-схема, показанная ниже, показывает, как работает структура управления переключателем
Практический пример
В приведенном ниже коде используется структура управления переключателем для отображения сообщения в зависимости от дня недели.