Путь программирования на PHP

база данных PHP модульный тест Composer

предисловие

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

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

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

назад навигация

Руководство по началу работы

Используйте текущую стабильную версию PHP (7.1)

Если вы впервые начинаете изучать PHP, используйте последние стабильные версии.PHP 7.1. По сравнению со старым 5.x, PHP 7.1 очень новый и добавляет много сюрпризов.новые особенности. Поскольку базовый движок был в значительной степени переписан, новые версии PHP теперь работают быстрее, чем старые версии.

Часто в своей будущей работе вы будете сталкиваться с ситуациями, когда вы все еще используете PHP 5.x, последней версией серии 5.x является 5.6. Хотя эта версия неплохая, вам стоит попробовать обновиться до последней стабильной версии из этой серии — PHP 5.6.Обновления безопасности больше не будут получать после 2018 года.. из-зане обратно совместимыйСлучаев не так много, поэтому апгрейд на самом деле очень прост. Если вы не уверены, какая функция была представлена ​​в какой версии, перейдите кphp.netПроверьте веб-сайт.

Встроенный веб-сервер

После PHP 5.4 вы можете начать изучение PHP без установки и настройки полнофункционального веб-сервера. Чтобы запустить встроенный веб-сервер, перейдите в корневой веб-каталог вашего проекта из терминала командной строки и выполните следующую команду:

> php -S localhost:8000

Mac System Установлена ​​PHP

ОС X будет предварительно установлена ​​PHP, только некоторые общие выпуску будут ниже, чем последняя стабильная версия. Mavericks в настоящее время предустановлен 5.4.17, Йосемит - 5.5.9, Эль-Капитан - 5.5.29, Sierra 5.6.24, но после выросла PHP 7.1, эта предварительная установленная версия устарела.

Есть много способов установить PHP на OS X.

Установить PHP через Homebrew

HomebrewЭто мощный менеджер пакетов для OS X, который может помочь вам легко установить PHP и различные расширения.Homebrew PHPэто репозиторий, содержащий формулы, связанные с PHP, которые позволяют вам установить PHP через доморощенный.

В настоящее время вы можете пройтиbrew installкоманда для установкиphp53,php54,php55,php56,php70илиphp71, и путем измененияPATHпеременная для переключения между версиями. или вы также можете использоватьbrew-php-switcherпомочь вам переключаться автоматически.

Установите PHP через Macports

MacPortsэто проект с открытым исходным кодом, инициированный сообществом, целью которого является разработка простой в использовании системы для компиляции, установки и обновления программного обеспечения с открытым исходным кодом для командной строки, X11 или Aqua в системах OS X.

MacPorts поддерживает предварительно скомпилированные двоичные файлы, поэтому вам не нужно перекомпилировать все зависимости из исходных tar-архивов, а если в вашей системе не установлен PHP, MacPorts может сэкономить вам много времени.

В настоящее время вы можете использоватьport installкоманда для установкиphp54,php55,php56,php70илиphp71,Например:

sudo port install php56
sudo port install php71

и ты можешь сделатьselectКоманда для переключения текущей версии PHP:

sudo port select --set php php71

Установить PHP через phpbrew

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

Установите PHP через бинарный установщик Liip

Еще один популярный вариантphp-osx.liip.ch, вы можете установить любую версию PHP от 5.3 до 7.1 с помощью одной строки инструкций по установке. Он устанавливает все файлы в отдельное место (/usr/local/php5) и не перезаписывает двоичный файл php, который поставляется с системой.

компиляция исходного кода

Другой вариант, который дает вам контроль над версией PHP, которую вы устанавливаете, этоСоставьте его сам. Если вы используете этот метод, вы должны сначала подтвердить, был ли он загружен и установлен через «Apple's Mac Developer Center».Xcodeили«Инструменты командной строки для XCode».

Пакеты интеграции (универсальные установщики)

Перечисленные выше решения в основном предназначены для самого PHP и не включают: например, Apache, Nginx или SQL-сервер. Пакеты интеграции, такие какMAMPа такжеXAMPPПрограммное обеспечение установлено и связано вместе, но простота установки достигается за счет гибкости.

Установить PHP в Windows

ты можешь начатьwindows.php.net/downloadЗагрузите бинарный установочный пакет. После распаковки лучше добавить корневой каталог, в котором находится ваш PHP (папка, в которой находится php.exe), вPATHпеременные окружения, чтобы PHP можно было запускать прямо из командной строки.

Если вы только учитесь или разрабатываете локально, вы можете напрямую использовать встроенный веб-сервер PHP 5.4+ и избавить себя от необходимости настраивать сервер. Если вам нужен пакет интеграции, включающий веб-сервер и MySql, то что-то вродеWeb Platform Installer,XAMPP,EasyPHP,OpenServerа такжеWAMPТакие инструменты помогут вам быстро настроить среду разработки Windows. Однако эти инструменты будут немного отличаться от онлайн-среды, если вы разрабатываете под Windows, а производственная среда развернута в Linux, будьте осторожны.

Если вам нужно развернуть производственную среду в Windows, IIS7 обеспечит наиболее стабильную и лучшую производительность. вы можете использоватьphpmanager(Графический плагин для IIS7) позволяет легко настраивать PHP и управлять им. IIS7 также имеет встроенный FastCGI, вам просто нужно настроить PHP в качестве его процессора. Подробнее см.dedicated area on iis.net.

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

Крис Танкерсли немного рассказал оPHP-разработка под WindowsРекомендуется ознакомиться с соответствующими сообщениями в блогах некоторых используемых инструментов.

назад навигация

руководство по стилю кода

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

Группа стандартов взаимодействия фреймворковБыл сделан и принят ряд рекомендаций по стилю кодирования. Частично это касается стиля кода, а именноPSR-0,PSR-1,PSR-2а такжеPSR-4. Эти рекомендации — лишь некоторые из правил, которым следуют проекты с открытым исходным кодом, такие как Drupal, Zend, Symfony, Laravel, CakePHP, phpBB, AWS SDK, FuelPHP, Lithium и т. д. Вы можете использовать эти правила в своих проектах или продолжать использовать свой собственный стиль.

В идеале вы должны следовать известному стандарту написания PHP-кода. Может быть одним из руководств по кодированию PSR, PEAR или Zend. Преимущество этого заключается в том, что другие разработчики могут легко читать и использовать ваш код, а приложения, использующие эти компоненты, могут быть согласованы с другими сторонними компонентами.

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

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

  • одинPHP Coding Standards Fixer, у него хорошее тестирование кода.
  • Другой инструментPHP Code Beautifier and FixerОн включен в PHP_CodeSniffer, вы также можете настроить свой формат кода.

Вы можете запустить phpcs вручную из командной строки:

phpcs -sw --standard=PSR2 file.php

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

If you have PHP_CodeSniffer, then you can fix the code layout problems reported by it, automatically, with the PHP Code Beautifier and Fixer.

phpcbf -w --standard=PSR2 file.php

Другой вариант — использоватьPHP Coding Standards Fixer. Он может перечислить ошибки и типы ошибок в структуре кода перед их исправлением.

php-cs-fixer fix -v --level=psr2 file.php

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

назад навигация

Выделяет язык

Парадигма программирования

PHP — это гибкий и динамичный язык, который поддерживает множество методов программирования. Разработка продолжалась на протяжении многих лет, с основными вехами, включая PHP 5.0 (2004 г.) с добавлением полной объектно-ориентированной модели, PHP 5.3 (2009 г.) с добавлением анонимных функций и пространств имен и PHP 5.4 (2012 г.) с добавлением признаков.

Объектно-ориентированное программирование

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

Функциональное программирование Функциональное программирование

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

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

Поддержка замыканий и анонимных функций появилась начиная с PHP 5.3 (2009).

В PHP 5.4 добавлена ​​возможность связывать замыкания с областью видимости объекта и улучшена возможность их вызова, так что в большинстве случаев вместо обычных функций можно использовать анонимные функции.

метапрограммирование

PHP может реализовывать метапрограммирование многими способами с помощью API отражения и магических методов. Разработчики передают магические методы, такие как__get(), __set(), __clone(), __toString(), __invoke()и т. д., могут изменить поведение класса. Разработчики Ruby часто говорят, что PHP неmethod_missingметод, по сути__call()а также__callStatic()может выполнять ту же функцию.

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

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

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

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

PSR-4Предоставляет рекомендуемый способ использования пространств имен, который обеспечивает стандартное соглашение об использовании файлов, классов и пространств имен, так что код может работать по принципу plug-and-play.

В октябре 2014 года PHP-FIG объявил устаревшим последний стандарт автозагрузки:PSR-0. В настоящее время полностью доступны стандарты PSR-0 и PSR-4. Поскольку для PSR-4 требуется PHP 5.3 и выше, многие проекты, специально ориентированные на PHP 5.2, реализуют стандарт PSR-0.

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

Стандартная библиотека PHP

Стандартная библиотека PHP (SPL) поставляется с PHP и обеспечивает набор классов и интерфейсов. Содержит обычно используемые классы структуры данных (стек, очередь, куча и т. Д.) И итераторы для прохождения этих структур данных, или вы можете реализовать интерфейс SPL.

Интерфейс командной строки

PHP был создан для разработки веб-приложений, но его интерфейс сценариев командной строки (CLI) также очень полезен. Программирование командной строки PHP может помочь вам автоматизировать такие задачи, как тестирование, развертывание и управление приложениями.

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

Запустите PHP из командной строки:

> php -i

Опции-iнапечатает конфигурацию PHP, что-то вродеphpinfo()функция.

Опции-aПредоставляет интерактивную оболочку, похожую на интерактивную оболочку Ruby IRB или интерактивную оболочку Python, а также множество других полезных функций.параметры командной строки.

Затем напишите простую CLI-программу «Hello, $name», сначала создайте программу с именем «Hello, $name».hello.phpсценарий:

<?php
if($argc != 2) {
    echo "Usage: php hello.php [name].\n";
    exit(1);
}
$name = $argv[1];
echo "Hello, $name\n";

PHP установит две специальные переменные в соответствии с параметрами при запуске скрипта,$argcцелое число, представляющее параметрколичество,$argvпредставляет собой переменную массива, содержащуюстоимость, первым элементом которого всегда является имя PHP-скрипта, в данном случаеhello.php.

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

Чтобы запустить вышеуказанный скрипт, введите в командную строку:

> php hello.php
Usage: php hello.php [name]
> php hello.php world
Hello, world

Xdebug

Правильный отладчик — один из самых полезных инструментов в разработке программного обеспечения, позволяющий отслеживать результаты выполнения программы и отслеживать информацию в стеке программы. Xdebug — это отладчик php, который можно использовать для отладки точек останова и проверки стека во многих IDE (интегрированных средах разработки). Он также может выполнять проверку покрытия кода или отслеживать производительность программы, как PHPUnit и KCacheGrind.

если вы все еще используетеvar_dump()/print_r()Совершите ошибку, и часто оказываетесь перед дилеммой и до сих пор не можете найти решение. На этом этапе пришло время использовать отладчик.

Установите XdebugЭто может быть утомительно, но одна из самых важных функций «удаленной отладки» - если вы разрабатываете локально, и тестируете на виртуальную машину или другой сервер, удаленная отладка, вероятно, то, как вы этого хотите.

Обычно вам нужно изменить эти значения Apache Vhost или ваш файл .htaccess:

php_value xdebug.remote_host 192.168.?.?
php_value xdebug.remote_port 9000

«удаленный хост» и «удаленный порт» соответствуют адресу и порту, которые прослушивает ваша локальная машина разработки. Затем установите IDE в режим «прослушивания подключений» и перейдите по URL-адресу:

http://your-website.example.com/index.php?XDEBUG_SESSION_START=1

Ваша IDE перехватит текущее состояние исполняемого скрипта, запустит установленные вами точки останова и просмотрит значения в памяти.

Графический отладчик позволяет легко выполнять код, переменные и код evel во время выполнения. Многие IDE уже имеют встроенную или подключаемую поддержку графического отладчика XDebug. Например, MacGDBp — это бесплатный автономный отладчик с открытым исходным кодом для Mac.

назад навигация

управление зависимостями

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

В настоящее время PHP имеет две широко используемые системы управления пакетами:Composerа такжеPEAR. Composer — самый популярный менеджер пакетов, используемый PHP, однако PEAR уже давно играет эту роль. Вы должны знать, что такое PEAR, потому что, даже если вы никогда не использовали его, вы все равно можете встретить упоминания о нем.

Композитор и упаковщик

Композитор - этовыдающийсяМенеджер зависимостей. существуетcomposer.jsonВ файле перечислены зависимости, необходимые для вашего проекта, и с помощью нескольких простых команд Composer автоматически загрузит для вас зависимости и настроит автоматическую загрузку. Composer можно сравнить с NPM в мире node.js или Bundler в мире Ruby.

Уже существует множество сторонних пакетов PHP, совместимых с Composer, готовых к использованию в ваших проектах. Эти «пакеты» перечислены вPackagistЭто официальный репозиторий пакетов совместимости с Composer.

Как установить Композитор

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

Мы рекомендуем установить Composer наГлобальныйсреде (например, скопируйте в каталог /usr/local/bin) следующим образом:

mv composer.phar /usr/local/bin/composer

Уведомление:Если вышеуказанный процесс завершается сбоем из-за разрешений, повторите выполнение.mvИ добавить перед этой командойsudo.

Чтобы запустить локально установленный Composer, используйтеphp composer.pharкоманда; запустить глобально установленный Composer напрямую, используяcomposerЗаказ.

Установка в среде Windows

Для пользователей Windows самый простой способ получить и выполнить — использоватьComposerSetupустановщик, который выполняет глобальную установку и настраивает$PATH, поэтому вы используете его в командной строке в любом каталогеcomposer.

Как вручную установить Composer

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

  • Используется допустимая версия PHP
  • .pharфайл может быть выполнен правильно
  • Соответствующий каталог имеет достаточные разрешения
  • Соответствующее проблемное расширение не было загружено
  • Связанныйphp.iniНастройка завершена

Поскольку ручная установка не выполняет эти проверки, вам придется решить для себя, стоит ли это делать, вот как установить Composer вручную:

curl -s https://getcomposer.org/composer.phar -o $HOME/local/bin/composer
chmod +x $HOME/local/bin/composer

дорожка$HOME/local/bin(или путь, который вы выбираете) должен быть в вашем$PATHв переменных окружения. это повлияетcomposerДоступна ли эта команда.

Когда вы сталкиваетесь с документацией, говорится, что команда для выполнения Composerphp composer.phar install, вместо этого вы можете использовать следующую команду:

composer install

В этом разделе предполагается, что вы уже установили Composer глобально.

Как установить и установить зависимости

Композитор пройдетcomposer.jsonФайл отслеживает зависимости вашего проекта. Если хотите, вы можете управлять этим файлом вручную или использовать Composer, чтобы управлять им самостоятельно.composer requireЭта директива добавит зависимость проекта, если вы еще этого не сделали.composer.jsonфайл, он будет создан. Вот пример для добавления в ваш проектTwigполагаться.

composer require twig/twig:~1.8

Кроме того,composer initкоманда поможет вам создать полныйcomposer.jsonфайл в свой проект. Какой бы способ вы ни использовали, как только вы создадитеcomposer.jsonфайл, вы можете указать Composer загрузить и установить ваши зависимости вvendor/в каталоге. Эта команда также работает для загруженных вами файлов, которые ужеcomposer.jsonЭлементы файла:

composer install

Затем добавьте эту строку в основной файл PHP вашего приложения, которая укажет PHP использовать автозагрузчик Composer для зависимостей вашего проекта.

<?php
require 'vendor/autoload.php';

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

обновите свои зависимости

Композитор создастcomposer.lockфайл, при первом выполненииcomposer install, сохраните точный номер версии каждого загруженного пакета зависимостей. Если вы хотите поделиться своим проектом с другими разработчиками иcomposer.lockЕсли файл также находится среди файлов, которыми вы делитесь. когда они выполняютсяcomposer installЭта команда, они получат ту же версию зависимостей, что и вы. Если вы хотите обновить свои зависимости, выполнитеcomposer update. При развертывании проекта используйте толькоcomposer installВместо того, чтобы использоватьcomposer updateкоманду, иначе зависимости, установленные в производственной среде, не соответствуют вашим ожиданиям.

Это наиболее полезно, когда вам нужна гибкость для определения нужной вам версии зависимостей. Например,~1.8означает «все, что больше, чем1.8.0, но меньше2.0.x-devверсия". Вы также можете использовать подстановочные знаки*существует1.8.*среди. Сейчас Composer выполняетcomposer updateобновит все ваши зависимости до последней версии, которую вы ограничиваете.

уведомление об обновлении

Чтобы получать уведомления об обновлениях о новых версиях. вы можете зарегистрироватьсяVersionEye, веб-служба, которая отслеживает ваши учетные записи Github и BitBucket на наличиеcomposer.jsonфайл и отправляет вам электронное письмо, когда появляются новые обновления для пакета.

Проверьте свои зависимости на наличие проблем с безопасностью

Security Advisories Checkerэто веб-служба и инструмент командной строки, оба дважды проверят вашcomposer.lockфайл и сообщите вам все зависимости, которые вам нужно обновить.

Обработка глобальных зависимостей Composer

Composer также может обрабатывать глобальные зависимости и их двоичные файлы. Использование простое, все, что вам нужно сделать, это добавить команду сglobalприставка. Если вы хотите установить PHPUnit и сделать его доступным по всему миру, вы можете запустить следующую команду:

composer global require phpunit/phpunit

Это создаст~/.composerВ каталоге хранятся глобальные зависимости, чтобы бинарные команды установленных зависимостей были доступны везде, нужно добавить~/.composer/vendor/binкаталог на ваш$PATHПеременная.

Введение в грушу

PEAR— еще один широко используемый менеджер пакетов зависимостей, который очень похож на Composer, но имеет некоторые заметные отличия.

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

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

Как установить ГРУШУ

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

Если вы используете Linux, вы можете попробовать найти диспетчер системных приложений, например, в Debian и Ubuntu он есть.php-pearПодходящий установочный пакет.

Как установить пакеты расширений

Если пакет расширения находится вPEAR packages listИз этого списка вы можете установить его с помощью следующей команды:

pear install foo

Если пакет расширения размещен на другом канале, вам необходимо发现 (discover)первый канал, см. документациюиспользовать канал.

Использование Composer для установки расширения PEAR

если вы используетеComposer, и вы хотите использовать код PEAR, вы можете установить расширение PEAR через Composer.

Ниже изpear2.php.netПример установки зависимостей кода:

{
    "repositories": [
        {
            "type": "pear",
            "url": "http://pear2.php.net"
        }
    ],
    "require": {
        "pear-pear2/PEAR2_Text_Markdown": "*",
        "pear-pear2/PEAR2_HTTP_Request": "*"
    }
}

первая часть"repositories"Это нужно, чтобы Composer знал, как «инициализировать» (или «обнаружить» в терминологии PEAR) репозиторий груши. Следующийrequiresection добавит префикс к имени пакета следующим образом:

pear-channel/Package

Префикс «груша» жестко запрограммирован во избежание конфликтов.

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

vendor/pear-pear2.php.net/PEAR2_HTTP_Request/pear2/HTTP/Request.php

В коде вы можете использовать это так:

<?php
$request = new pear2\HTTP\Request();

назад навигация

практика разработки

Базовые знания

PHP - огромный язык, который разработчики всех уровней могут использовать для быстрого и эффективного развития. Однако в процессе изучения языка постепенно мы часто забываем (или игнорировать) основные знания, которые мы узнали в начале из-за ярлыков и / или вредных привычек. Чтобы полностью решить эту проблему, цель этой главы - напомнить разработчикам основных практик программирования в PHP.

Дата и время

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

Перед использованием DateTime передайтеcreateFromFormat()Фабричные методы для преобразования необработанных строк даты и времени в объекты или использованияnew DateTimeчтобы получить текущую дату и время. использоватьformat()DateTime преобразуется обратно в строку для вывода.

<?php
$raw = '22. 11. 1968';
$start = DateTime::createFromFormat('d. m. Y', $raw);

echo 'Start date: ' . $start->format('Y-m-d') . "\n";

Класс DateInterval можно использовать при выполнении вычислений в DateTime. Класс DateTime имеет, например.add()а такжеsub()и т. д. методы, которые принимают DateInterval в качестве параметра. При написании кода будьте осторожны и не думайте, что каждый день состоит из одного и того же количества секунд.Будь то переход на летнее время (DST) или преобразование часового пояса, вы столкнетесь с проблемами с расчетами меток времени, и вам следует выбрать интервал дат. . использоватьdiff()метод для вычисления интервала между датами, он возвращает новый DateInterval, который очень легко отображать.

<?php
// create a copy of $start and add one month and 6 days
$end = clone $start;
$end->add(new DateInterval('P1M6D'));

$diff = $end->diff($start);
echo 'Difference: ' . $diff->format('%m month, %d days (total: %a days)') . "\n";
// Difference: 1 month, 6 days (total: 37 days)

Сравнение можно проводить непосредственно между объектами DateTime:

<?php
if ($start < $end) {
    echo "Start is before the end!\n";
}

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

<?php
// output all thursdays between $start and $end
$periodInterval = DateInterval::createFromDateString('first thursday');
$periodIterator = new DatePeriod($start, $periodInterval, $end, DatePeriod::EXCLUDE_START_DATE);
foreach ($periodIterator as $date) {
    // output each date in the period
    echo $date->format('Y-m-d') . ' ';
}

Carbon— популярное расширение PHP API. Он наследует все функциональные возможности класса DateTime, поэтому с очень небольшой модификацией кода вы можете использовать больше дополнительных функций, таких как поддержка локализации, добавление и вычитание дат, а также форматирование объектов Datetime, а также возможность имитации дат по вашему выбору. и время и протестируйте свой код.

Шаблоны проектирования

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

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

Используйте кодировку UTF-8

Эта глава состоит изAlex CabalПервоначально написано вPHP Best Practices, мы используем его как основу для рекомендаций.

Это не шутка. Пожалуйста, обращайтесь с ним внимательно, бережно и последовательно.

В настоящее время в PHP не реализована внутренняя поддержка Unicode. Хотя существует несколько способов убедиться, что строки UTF-8 обрабатываются правильно, это не тривиально и обычно требует полной проверки веб-приложения, от HTML до SQL и PHP. Мы будем стремиться к краткому и практическому изложению.

UTF-8 в PHP

Самые простые операции со строками, такие как объединение двух строк или присвоение строк переменным, не требуют специальной обработки UTF-8. Однако большинство строковых функций, напримерstrpos()а такжеstrlen(), требует специального лечения. Эти функции обычно имеют префикс, называемыйmb_*Эквивалентные функции, начинающиеся с: например,mb_strpos()а такжеmb_strlen(). Этиmb_*Функции манипулирования строками в начале получены изMultibyte String Extension, который специально разработан для работы со строками Unicode.

При работе со строками Unicode вы должны использоватьmb_*функция. Например, если вы используете строку UTF-8substr(), возвращаемый результат, скорее всего, будет содержать искаженные символы. Правильный способ - использоватьmb_substr().

Самое сложное — не забывать использовать его каждый разmb_*функция. Если вы забудете использовать его хотя бы один раз, ваши строки Unicode рискуют быть искаженными до конца.

Не все строковые функции имеют соответствующийmb_*функция. Если нет соответствующей функции для функции, которую вы хотитеmb_*функции, это может означать только то, что вам не повезло.

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

Кроме того, многие функции, работающие со строками, имеют необязательный параметр, указывающий кодировку строки. Вы всегда должны явно указывать использование UTF-8, когда такие параметры могут быть установлены. Например,htmlentities()Существует опция кодировки символов, вы всегда должны устанавливать ее на UTF-8. Начиная с PHP 5.4.0,htmlentities()а такжеhtmlspecialchars()По умолчанию установлена ​​кодировка UTF-8.

Наконец, если вы пишете распределенное приложение и не уверены,mbstringЕсли расширение должно быть включено, рассмотрите возможность использованияpatchwork/utf8Пакет композитора. это будет вmbstringАвтоматически используется, когда доступно, в противном случае автоматически переключается обратно на функции, отличные от UTF-8.

UTF-8 на уровне базы данных

Если вы используете PHP для работы с MySQL, иногда, даже если вы сделали все вышеперечисленные пункты, ваши строки могут по-прежнему сталкиваться с проблемами при сохранении в базе данных в формате, отличном от UTF-8.

Чтобы убедиться, что ваши строки из PHP в MySQL используют UTF-8, убедитесь, что ваша база данных и таблицы настроены наutf8mb4наборы символов и сопоставление, а также убедитесь, что ваши запросы на соединение с PDO также используютutf8mb4набор символов. См. пример кода ниже, которыйОчень важныйиз.

Обратите внимание, что для полной поддержки UTF-8 вы должны использоватьutf8mb4вместоutf8! Вы узнаете, почему в дальнейшем чтении.

UTF-8 на уровне браузера

использоватьmb_http_output()чтобы убедиться, что PHP выводит строки в формате UTF-8 в браузер.

Затем браузеру необходимо получить ответ HTTP, указывающий, что страница закодирована в UTF-8. Ранее этот шаг выполнялся на странице<head>под этикеткой содержитсянабор символов<meta>ЭтикеткаПонял, это осуществимый путь. Но лучший подход состоит в том, чтобыContent-Typeзаголовки ответов, потому что скорость их выполнения будетБыстрее.

<?php
// Tell PHP that we're using UTF-8 strings until the end of the script
mb_internal_encoding('UTF-8');

// Tell PHP that we'll be outputting UTF-8 to the browser
mb_http_output('UTF-8');

// Our UTF-8 test string
$string = 'Êl síla erin lû e-govaned vîn.';

// Transform the string in some way with a multibyte function
// Note how we cut the string at a non-Ascii character for demonstration purposes
$string = mb_substr($string, 0, 15);

// Connect to a database to store the transformed string
// See the PDO example in this document for more information
// Note the `charset=utf8mb4` in the Data Source Name (DSN)
$link = new PDO(
    'mysql:host=your-hostname;dbname=your-db;charset=utf8mb4',
    'your-username',
    'your-password',
    array(
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_PERSISTENT => false
    )
);

// Store our transformed string as UTF-8 in our database
// Your DB and tables are in the utf8mb4 character set and collation, right?
$handle = $link->prepare('insert into ElvishSentences (Id, Body) values (?, ?)');
$handle->bindValue(1, 1, PDO::PARAM_INT);
$handle->bindValue(2, $string);
$handle->execute();

// Retrieve the string we just stored to prove it was stored correctly
$handle = $link->prepare('select * from ElvishSentences where Id = ?');
$handle->bindValue(1, 1, PDO::PARAM_INT);
$handle->execute();

// Store the result into an object that we'll output later in our HTML
$result = $handle->fetchAll(\PDO::FETCH_OBJ);

header('Content-Type: text/html; charset=UTF-8');
?><!doctype html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>UTF-8 test page</title>
    </head>
    <body>
        <?php
        foreach($result as $row){
            print($row->Body);  // This should correctly output our transformed UTF-8 string to the browser
        }
        ?>
    </body>
</html>

дальнейшее чтение

Интернационализация (i18n) и локализация (l10n)

Disclaimer for newcomers: i18n and l10n are numeronyms, a kind of abbreviation where numbers are used to shorten words - in our case, internationalization becomes i18n and localization, l10n.

Во-первых, нам нужно определить эти два похожих понятия и связанные понятия:

  • Internationalizationэто когда вы организуете свой код так, чтобы его можно было адаптировать к разным языкам или регионам без рефакторинга.Обычно это делается один раз - желательно в начале проекта, иначе вы, вероятно, нужны огромные изменения в исходниках!
  • Localization happens when you adapt the interface (mainly) by translating contents, based on the i18n work done before. It usually is done every time a new language or region needs support and is updated when new interface pieces are added, as they need to be available in all supported languages.
  • Pluralizationопределяет правила, необходимые между разными языками для взаимодействия строк, содержащих числа и счетчики.Например, в английском языке, когда у вас есть только один элемент, он в единственном числе, и все, что отличается от этого называется множественным числом, множественное число в этом языке обозначается добавлением буквы S после некоторых слов, а иногда и изменением его частей. даже найти языки с четырьмя, пятью или шестью формами, такие как словенский, ирландский или арабский.

Общий метод реализации

The easiest way to internationalize PHP software is by using array files and using those strings in templates, such as <h1><?=$TRANS['title_about_page']?></h1>Однако это вряд ли рекомендуется для серьезных проекты, так как это создает некоторые проблемы с обслуживанием по пути - некоторые могут появиться в самом начале, например, множественное число. Поэтому, пожалуйста, не пытайтесь это сделать, если ваш проект будет содержать более пары страниц. Для программного обеспечения PHP первый , самый простой способ добиться интернационализации — использовать метод, соответствующий значению ключа массива, например<h1><?=$TRANS['title_about_page']?></h1>, но в более серьезных проектах это делать не рекомендуется. Поскольку количество проектных кодов будет постепенно увеличиваться, сложность обслуживания будет возрастать, особенно будет затруднена последующая реализация локализации.

The most classic way and often taken as reference for i18n and l10n is a Unix tool called gettext, Он восходит к 1995 году и до сих пор является полной реализацией для перевода программного обеспечения. Его довольно легко запустить, хотя он по-прежнему обладает мощными вспомогательными инструментами. Мы будем говорить здесь о Gettext. Кроме того, чтобы помочь вам не запутаться в командной строке, мы представим отличное приложение с графическим интерфейсом, которое можно используется для простого обновления исходных файлов l10n.

Другие инструменты

There are common libraries used that support Gettext and other implementations of i18n. Some of them may seem easier to install or sport additional features or i18n file formats. In this document, we focus on the tools provided with the PHP core, but here we list others for completion:

  • oscarotero/Gettext: Gettext support with an OO interface; includes improved helper functions, powerful extractors for several file formats (some of them not supported natively by the gettext command), and can also export to other formats besides .mo/.po files. Can be useful if you need to integrate your translation files into other parts of the system, like a JavaScript interface.
  • symfony/translation: поддерживает множество различных форматов, но рекомендует использовать подробные XLIFF. Не включает вспомогательные функции и встроенный экстрактор, но поддерживает заполнители с использованиемstrtr() internally.
  • zend/i18n: supports array and INI files, or Gettext formats. Implements a caching layer to save you from reading the filesystem every time. It also includes view helpers, and locale-aware input filters and validators. However, it has no message extractor.

Other frameworks also include i18n modules, but those are not available outside of their codebases: - Laravel supports basic array files, has no automatic extractor but includes a @lang helper for template files. - Yii supports array, Gettext, and database-based translation, and includes a messages extractor. It is backed by the Intl extension, available since PHP 5.3, and based on the ICU project; this enables Yii to run powerful replacements, like spelling out numbers, formatting dates, times, intervals, currency, and ordinals.

If you decide to go for one of the libraries that provide no extractors, you may want to use the gettext formats, so you can use the original gettext toolchain (including Poedit) as described in the rest of the chapter.

Gettext

Установить

Во-первых, вам может понадобиться пройти через диспетчер пакетов (например,apt-getилиyum) для установки Gettext и связанных библиотек PHP. После установки вphp.iniфайл добавленextension=gettext.so(Линукс/Юникс) илиextension=php_gettext.dll(Windows), чтобы включить Gettext.

мы также должны использоватьPoeditдля создания файлов перевода. Как правило, его можно установить через менеджер пакетов, поставляемый с системой; существуют соответствующие версии для систем Unix, Mac и Windows, или вы можетеСкачать с его официального сайта.

Structure

Types of files

Есть три файла, с которыми вы обычно имеете дело при работе с gettext.Главные из них — это файлы PO (Portable Object) и MO (Machine Object), первый из которых представляет собой список читаемых «переведенных объектов», а второй — соответствующий двоичный файл, который нужно преобразовать. интерпретируется gettext при локализации. Существует также файл POT (шаблон), который просто содержит все существующие ключи из ваших исходных файлов и может использоваться в качестве руководства для создания и обновления всех файлов PO. Эти файлы шаблонов не обязательно: в зависимости от инструмента, который вы используете для выполнения l10n, вы можете прекрасно работать только с файлами PO/MO.У вас всегда будет одна пара файлов PO/MO для каждого языка и региона, но только один POT для каждого домена.

Domains

There are some cases, in big projects, where you might need to separate translations when the same words convey different meaning given a context. In those cases, you split them into different domains, В основном это названные группы Файлы POT/PO/MO, где имя файла является указаннымtranslation domainВ небольших и средних проектах обычно для простоты используется только один домен, его имя произвольное, но мы будем использовать «main» для наших примеров кода.
In Symfony projects, for example, domains are used to separate the translation for validation messages.

Locale code

Локаль — это просто код, который идентифицирует одну версию языка.ISO 639-1 and ISO 3166-1 alpha-2 specs: two lower-case letters for the language, optionally followed by an underline and two upper-case letters identifying the country or regional code. For rare languages, three letters are used.

For some speakers, the country part may seem redundant. In fact, some languages have dialects in different countries, such as Austrian German (de_AT) or Brazilian Portuguese (pt_BR).Вторая часть используется для различения между этими диалектами - когда он отсутствует, он воспринимается как «общая» или «гибридная» версия языка.

Структура каталогов

Чтобы использовать Gettext, нам нужно создать определенную структуру каталогов. Во-первых, вам нужно выбрать любой каталог в исходном репозитории в качестве корневого каталога файла l10n. В этом каталоге создайте отдельный каталог для каждого локализованного языка и, кроме того, создайтеLC_MESSAGESКаталог содержит файлы PO/MO. Например:

<project root>
 ├─ src/
 ├─ templates/
 └─ locales/
    ├─ forum.pot
    ├─ site.pot
    ├─ de/
    │  └─ LC_MESSAGES/
    │     ├─ forum.mo
    │     ├─ forum.po
    │     ├─ site.mo
    │     └─ site.po
    ├─ es_ES/
    │  └─ LC_MESSAGES/
    │     └─ ...
    ├─ fr/
    │  └─ ...
    ├─ pt_BR/
    │  └─ ...
    └─ pt_PT/
       └─ ...

Plural forms

As we said in the introduction, different languages might sport different plural rules. However, gettext saves us from this trouble once again. When creating a new .poфайл, вам нужно объявитьplural rulesДля этого языка и переведенные предметы, которые являются множественными, чувствительными к множеству, имеют различную форму для каждого из этих правил. При вызове GetText в коде вам придется указать номер, связанный с предложением, и он будет работать правильно Форма для использования - даже с использованием строкового замещения, если это необходимо.

Plural rules include the number of plurals available and a boolean test with n that would define in which rule the given number falls (starting the count with 0). For example:

  • Japanese: nplurals=1; plural=0 - only one rule
  • English: nplurals=2; plural=(n != 1); - two rules, first if N is one, second rule otherwise
  • Brazilian Portuguese: nplurals=2; plural=(n > 1); - two rules, second if N is bigger than one, first otherwise

Теперь, когда вы поняли, как работают правила множественного числа, а если нет, посмотрите более подробное объяснениеLingoHub tutorial -, you might want to copy the ones you need from a list instead of writing them by hand.

Когда вы вызываете Gettext для локализации предложений со счетчиками, вы также должны дать ему соответствующий номер. Gettext определит, какое правило должно действовать, и использует правильную локализованную версию. Вам нужно будет включить в в.po file a different sentence for each plural rule defined.

Sample implementation

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

msgid ""
msgstr ""
"Language: pt_BR\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"

msgid "We're now translating some strings"
msgstr "Nós estamos traduzindo algumas strings agora"

msgid "Hello %1$s! Your last visit was on %2$s"
msgstr "Olá %1$s! Sua última visita foi em %2$s"

msgid "Only one unread message"
msgid_plural "%d unread messages"
msgstr[0] "Só uma mensagem não lida"
msgstr[1] "%d mensagens não lidas"

The first section works like a header, having the msgid and msgstr especially empty. It describes the file encoding, plural forms and other things that are less relevant. The second section translates a simple string from English to Brazilian Portuguese, and the third does the same, but leveraging string replacement from sprintf so the translation may contain the user name and visit date.
The last section is a sample of pluralization forms, displaying the singular and plural version as msgid in English and their corresponding translations as msgstr 0 and 1 (following the number given by the plural rule). There, string replacement is used as well so the number can be seen directly in the sentence, by using %d. The plural forms always have two msgid(единственное и множественное число), поэтому рекомендуется не использовать сложное язык как источник перевода.

Discussion on l10n keys

Как вы могли заметить, мы используем в качестве идентификатора источника фактическое предложение на английском языке.msgid is the same used throughout all your .po files, meaning other languages will have the same format and the same msgid fields but translated msgstr lines.

Говоря о ключах перевода, здесь есть две основные «школы»:

  1. msgid as a real sentence.
    The main advantages are:
    • if there are pieces of the software untranslated in any given language, the key displayed will still maintain some meaning. Example: if you happen to translate by heart from English to Spanish but need help to translate to French, you might publish the new page with missing French sentences, and parts of the website would be displayed in English instead;
    • переводчику гораздо легче понять, о чем идет речь, и сделать правильный перевод на основеmsgid;
    • он дает вам "бесплатный" l10n для одного языка - исходного;
    • The only disadvantage: if you need to change the actual text, you would need to replace the same msgid across several language files.
  2. msgid as a unique, structured key.
    It would describe the sentence role in the application in a structured way, including the template or part where the string is located instead of its content.
    • это отличный способ организовать код, отделив текстовое содержимое от логики шаблона.
    • however, that could bring problems to the translator that would miss the context. A source language file would be needed as a basis for other translations. Example: the developer would ideally have an en.po file, that translators would read to understand what to write in fr.po for instance.
    • missing translations would display meaningless keys on screen (top_menu.welcome instead of Hello there, User!на упомянутой непереведенной французской странице) Это хорошо, как бы заставить перевод быть полным перед публикацией - но плохо, поскольку проблемы с переводом будут действительно ужасными в интерфейсе.Однако некоторые библиотеки включают возможность указать данный язык как «откат», имея поведение, аналогичное другому подходу.

The Gettext manualотдает предпочтение первому подходу, так как в целом проще переводчикам и пользователям в случае затруднений, так мы и здесь будем работать.Symfony documentation favors keyword-based translation, to allow for independent changes of all translations without affecting templates as well.

Everyday usage

In a common application, you would use some Gettext functions while writing static text in your pages. Those sentences would then appear in .po files, get translated, compiled into .moфайлы, а затем, используемые Gettext при рендеринге фактического интерфейса. Учитывая это, давайте свяжем то, что мы обсуждали до сих пор, в пошаговом примере:

1. A sample template file, including some different gettext calls

<?php include 'i18n_setup.php' ?>
<div id="header">
    <h1><?=sprintf(gettext('Welcome, %s!'), $name)?></h1>
    <!-- code indented this way only for legibility -->
    <?php if ($unread): ?>
        <h2><?=sprintf(
            ngettext('Only one unread message',
                     '%d unread messages',
                     $unread),
            $unread)?>
        </h2>
    <?php endif ?>
</div>

<h1><?=gettext('Introduction')?></h1>
<p><?=gettext('We\'re now translating some strings')?></p>
  • gettext() simply translates a msgid into its corresponding msgstrдля данного языка.Также есть сокращенная функция_() that works the same way;
  • ngettext() does the same but with plural rules;
  • есть такжеdgettext() and dngettext(), that allows you to override the domain for a single call. More on domain configuration in the next example.

2. A sample setup file (i18n_setup.php as used above), selecting the correct locale and configuring Gettext

<?php
/**
 * Verifies if the given $locale is supported in the project
 * @param string $locale
 * @return bool
 */
function valid($locale) {
   return in_array($locale, ['en_US', 'en', 'pt_BR', 'pt', 'es_ES', 'es']);
}

//setting the source/default locale, for informational purposes
$lang = 'en_US';

if (isset($_GET['lang']) && valid($_GET['lang'])) {
    // the locale can be changed through the query-string
    $lang = $_GET['lang'];    //you should sanitize this!
    setcookie('lang', $lang); //it's stored in a cookie so it can be reused
} elseif (isset($_COOKIE['lang']) && valid($_COOKIE['lang'])) {
    // if the cookie is present instead, let's just keep it
    $lang = $_COOKIE['lang']; //you should sanitize this!
} elseif (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
    // default: look for the languages the browser says the user accepts
    $langs = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
    array_walk($langs, function (&$lang) { $lang = strtr(strtok($lang, ';'), ['-' => '_']); });
    foreach ($langs as $browser_lang) {
        if (valid($browser_lang)) {
            $lang = $browser_lang;
            break;
        }
    }
}

// here we define the global system locale given the found language
putenv("LANG=$lang");

// this might be useful for date functions (LC_TIME) or money formatting (LC_MONETARY), for instance
setlocale(LC_ALL, $lang);

// this will make Gettext look for ../locales/<lang>/LC_MESSAGES/main.mo
bindtextdomain('main', '../locales');

// indicates in what encoding the file should be read
bind_textdomain_codeset('main', 'UTF-8');

// if your application has additional domains, as cited before, you should bind them here as well
bindtextdomain('forum', '../locales');
bind_textdomain_codeset('forum', 'UTF-8');

// here we indicate the default domain the gettext() calls will respond to
textdomain('main');

// this would look for the string in forum.mo instead of main.mo
// echo dgettext('forum', 'Welcome back!');
?>

3. Preparing translation for the first run

Чтобы упростить задачу — и одно из мощных преимуществ Gettext по сравнению с пользовательскими пакетами i18n framework — это его настраиваемый тип файла: «О, чувак, это довольно сложно понять и редактировать вручную, простой массив был бы проще!» Не заблуждайтесь. , приложения, такие какPoedit are here to help - a lot. You can get the program from their website, это бесплатно и доступно для всех платформ. инструмент, к которому можно привыкнуть, и в то же время очень мощный, использующий все мощные функции, доступные Gettext.

При первом запуске вы должны выбрать "Файл > Новый каталог" из меню. Там у вас будет небольшой экран, на котором мы настроим ландшафт, чтобы все остальное работало гладко. Вы сможете найти эти настройки позже через " Каталог > Недвижимость»:

  • Project name and version, Translation Team and email address: useful information that goes in the .po file header;
  • Language: here you should use that format we mentioned before, such as en_US or pt_BR;
  • Charsets: UTF-8, preferably;
  • Source charset: set here the charset used by your PHP files - probably UTF-8 as well, right?
  • формы множественного числа: вот те правила, о которых мы упоминали ранее - там есть ссылка с образцами;
  • Source paths: here you must include all folders from the project where gettext() (and siblings) will happen - this is usually your templates folder(s)
  • Source keywords: this last part is filled by default, but you might need to alter it later - and is one of the powerful points of Gettext. The underlying software knows how the gettext()вызовы выглядят как в нескольких программах языков, но вы также можете создавать свои собственные формы перевода, об этом будет рассказано позже в разделе «Советы».

После настройки этих точек вам будет предложено сохранить файл - используя эту структуру каталогов, который мы также упомянули, и тогда она будет запустить сканирование через исходные файлы, чтобы найти вызовы локализации. Они будут кормить пустым в перевод стол, и вы начнете вводить в локализованные версии этих строк. Сохранить его и.mo file will be (re)compiled into the same folder and ta-dah: your project is internationalized.

4. Translating strings

Как вы, возможно, заметили ранее, есть два основных типа локализованных строк: простые и с формами множественного числа. Первые имеют просто два поля: исходная и локализованная строка. Исходная строка не может быть изменена как Gettext/Poedit. не включайте права на изменение ваших исходных файлов - вы должны изменить сам источник и повторно отсканировать файлы.Совет: вы можете щелкнуть правой кнопкой мыши строку перевода, и он подскажет вам исходные файлы и строки, где используется эта строка.
On the other hand, plural form strings include two boxes to show the two source strings, and tabs so you can configure the different final forms.

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

Наконец, рекомендуется оставить отмеченным «Просмотр > Непереведенные записи», так как это поможет вамa lot to not forget any entry. From that menu, you can also open parts of the UI that allow you to leave contextual information for translators if needed.

Tips & Tricks

Possible caching issues

Если вы используете PHP как модуль на Apache (mod_php), you might face issues with the .moфайл кэшируется, это происходит при первом чтении, а затем, чтобы обновить его, может потребоваться перезапуск сервера. и PHP5 обычно требуется всего пара обновлений страницы для обновления кеша переводов, а в PHP7 это требуется редко.

Additional helper functions

Как предпочитают многие люди, это проще в использовании_() instead of gettext(). Many custom i18n libraries from frameworks use something similar to t()а также сделать переведенный код короче. единственная функция, которая имеет ярлык. Возможно, вы захотите добавить в свой проект некоторые другие, такие как__() or _n() for ngettext(), or maybe a fancy _r() that would join gettext() and sprintf() calls. Other libraries, such as Оскаротеро Gettext also provide helper functions like these.

В таких случаях вам нужно указать утилите Gettext, как извлекать строки из этих новых функций. Не бойтесь, это очень просто. Это просто поле в.poфайл или экран настроек в Poedit. В редакторе эта опция находится внутри «Каталог> Свойства> Исходные ключевые слова». Вам необходимо включить туда спецификации этих новых функций, следуяa specific format:

  • if you create something like t() that simply returns the translation for a string, you can specify it as t. Gettext will know the only function argument is the string to be translated;
  • if the function has more than one argument, you can specify in which one the first string is - and if needed, the plural form as well. For instance, if we call our function like this: __('one user', '%d users', $number), the specification would be __:1,2, meaning the first form is the first argument, and the second form is the second argument. If your number comes as the first argument instead, the spec would be __:2,3, indicating the first form is the second argument, and so on.

After including those new rules in the .po file, a new scan will bring in your new strings just as easy as before.

References

назад навигация

внедрение зависимости

из ВикипедииWikipedia:

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

Это объяснение делает концепцию внедрения зависимостей более сложной, чем она есть на самом деле. Внедрение зависимостей обеспечивает зависимости компонентов посредством внедрения конструкции, вызовов функций или настроек свойств. Это так просто.

основная концепция

Мы можем проиллюстрировать концепцию внедрения зависимостей на простом примере.

Код ниже имеетDatabaseclass, который требует адаптера для взаимодействия с базой данных. Мы создаем экземпляр адаптера в конструкторе, тем самым создавая связь. Это затрудняет тестирование иDatabaseКлассы и адаптеры тесно связаны.

<?php
namespace Database;

class Database
{
    protected $adapter;

    public function __construct()
    {
        $this->adapter = new MySqlAdapter;
    }
}

class MysqlAdapter {}

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

<?php
namespace Database;

class Database
{
    protected $adapter;

    public function __construct(MySqlAdapter $adapter)
    {
        $this->adapter = $adapter;
    }
}

class MysqlAdapter {}

Теперь мы задаем параметр в видеDatabaseКласс передает объекты, от которых он зависит, вместо того, чтобы создавать объекты, от которых он зависит. Мы даже можем создать метод, который принимает объект зависимости в качестве параметра и устанавливает зависимость внутри, или, если$adapterСобственность сама по себеpublic, мы можем назначить его напрямую.

сложный вопрос

Если вы когда-либо читали о внедрении зависимостей, вы, вероятно, видели«Инверсия контроля» (инверсия контроля)илиПринцип инверсии зависимостиЭтот аргумент. Это более сложные проблемы, которые может решить внедрение зависимостей.

Инверсия контроля

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

Некоторые фреймворки PHP уже давно реализовали инверсию управления, но вопрос в том, какие части должны быть инвертированы и в какой степени? Например, среды MVC часто предоставляют суперклассы или классы базовых контроллеров, чтобы другие контроллеры могли наследовать их зависимости. Это пример инверсии управления, но этот подход устраняет зависимость напрямую, а не смягчает ее.

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

Критерий инверсии зависимости

Принцип инверсии зависимостей — это буква «D» в принципе объектно-ориентированного проектирования S.O.L.I.D.«Опирайтесь на абстракцию, а не на конкретику». Проще говоря, зависимости должны быть интерфейсами/контрактами или абстрактными классами, а не конкретными реализациями. Мы можем легко изменить предыдущий пример, чтобы следовать этому правилу.

<?php
namespace Database;

class Database
{
    protected $adapter;

    public function __construct(AdapterInterface $adapter)
    {
        $this->adapter = $adapter;
    }
}

interface AdapterInterface {}

class MysqlAdapter implements AdapterInterface {}

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

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

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

контейнер

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

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

дальнейшее чтение

назад навигация

база данных

Большую часть времени ваши PHP-программы должны использовать базу данных для постоянного хранения данных. На этом этапе у вас есть несколько различных вариантов подключения к базе данных и взаимодействия с ней. существуетДо PHP 5.1.0, мы рекомендуем использовать, например.mysqli,pgsql,mssqlи другие родные драйвера.

Родной драйвер использует толькоОдинХороший подход в случае базы данных, но если, например, вы используете и MySQL, и немного MSSQL, или вам нужно использовать базу данных Oracle, то вы не можете просто использовать один драйвер базы данных. Вам нужно изучить разные API для каждой базы данных - очевидно, ненаучно.

Расширение MySQL

в PHPmysqlРасширение очень старое, и теперь его заменили два преемника:

не только потому, чтоmysqlРазработка расширения давно застопорилась и былаУстарело с PHP 5.5.0, и ужеОфициально удален из PHP 7.0.

чтобы избежатьphp.iniДругой способ — использовать удобный редактор, чтобы найти любой модуль расширения, который вы используете.mysql_*функция в начале. Если вы найдете какие-либо, например.mysql_connect()а такжеmysql_query()функция, это означает, что вы все еще используетеmysqlмодуль.

Даже если вы еще не использовали PHP 7.x, во избежание неожиданного обновления PHP 7.x рекомендуется подготовиться как можно скорее. Лучший вариант — использовать в плане разработки приложенийmysqliилиPDOна замену mysql, чтобы в дальнейшем не возиться.

если вы изmysqlобновитесь доmysqli, остерегайтесь того, что говорят вам эти ленивые учебникиmysql_*замените функцию в начале наmysqli_*Искушение для начала. Эта небольшая хитрость позволяет вам упустить расширенные функции, предоставляемые mysqli, такие как привязка параметров, которые можно найти вPDOТакже доступен в формате .

Расширение PDO

PDO— это библиотека абстракции подключения к базе данных, встроенная в PHP, начиная с версии 5.1.0, которая предоставляет общий интерфейс для взаимодействия с различными базами данных. Например, вы можете использовать тот же простой код для подключения к MySQL или SQLite:

<?php
// PDO + MySQL
$pdo = new PDO('mysql:host=example.com;dbname=database', 'user', 'password');
$statement = $pdo->query("SELECT some_field FROM some_table");
$row = $statement->fetch(PDO::FETCH_ASSOC);
echo htmlentities($row['some_field']);

// PDO + SQLite
$pdo = new PDO('sqlite:/path/db/foo.sqlite');
$statement = $pdo->query("SELECT some_field FROM some_table");
$row = $statement->fetch(PDO::FETCH_ASSOC);
echo htmlentities($row['some_field']);

PDO не транслирует SQL-запросы и не эмулирует несуществующие функции, он просто использует один и тот же API для подключения к разным типам баз данных.

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

Предположим, PHP-скрипт получает числовой идентификатор в качестве параметра запроса. Этот идентификатор следует использовать для извлечения записи пользователя из базы данных. Ниже приведен错误способ сделать:

<?php
$pdo = new PDO('sqlite:/path/db/users.db');
$pdo->query("SELECT name FROM users WHERE id = " . $_GET['id']); // <-- NO!

Это плохой код. Вы вставляете необработанный параметр запроса в запрос SQL. Это позволит хакерам легко использовать [инъекцию SQL] для атаки. Представьте, если бы хакер поместил сконструированныйidпараметры передаются какhttp://domain.com/?id=1%3BDELETE+FROM+usersТакой URL передается. Это сделает$_GET['id']Значение переменной устанавливается равным1;DELETE FROM usersзатем выполняется для удаления всех пользовательских записей! Следовательно, вы должны использовать параметр предела PDO для фильтрации ввода идентификатора.

<?php
$pdo = new PDO('sqlite:/path/db/users.db');
$stmt = $pdo->prepare('SELECT name FROM users WHERE id = :id');
$id = filter_input(INPUT_GET, 'id', FILTER_SANITIZE_NUMBER_INT); // <-- filter your data first (see [Data Filtering](#data_filtering)), especially important for INSERT, UPDATE, etc.
$stmt->bindParam(':id', $id, PDO::PARAM_INT); // <-- Automatically sanitized for SQL by PDO
$stmt->execute();

Это правильный код. Он использует параметр limit в операторе PDO. Это избегает ввода внешнего идентификатора перед отправкой его в базу данных, чтобы предотвратить потенциальные атаки SQL-инъекций.

Для операций записи, таких как INSERT или UPDATE, выполнитеФильтрация данныхОсобенно важно очистить другое содержимое (удалить HTML-теги, Javascript и т. д.). PDO будет выполнять только очистку SQL, он ничего не делает для вашего приложения.

Вы также должны знать, что соединения с базой данных иногда могут исчерпать ресурсы, что может привести к истощению доступных ресурсов, если соединение не закрыто неявным образом. Однако это обычно более распространено в других языках. Используя PDO, вы можете неявно закрыть эти соединения, уничтожив объект, то есть установив значение NULL, гарантируя, что все оставшиеся соединения, ссылающиеся на объект, будут удалены. Если вы не сделаете этого сами, PHP сделает это автоматически в конце вашего скрипта, если только вы не используете постоянные ссылки.

взаимодействие с базой данных

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

<ul>
<?php
foreach ($db->query('SELECT * FROM table') as $row) {
    echo "<li>".$row['field1']." - ".$row['field1']."</li>";
}
?>
</ul>

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

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

Рассмотрим самый простой подход:

<?php
function getAllFoos($db) {
    return $db->query('SELECT * FROM table');
}

foreach (getAllFoos($db) as $row) {
    echo "<li>".$row['field1']." - ".$row['field1']."</li>"; // BAD!!
}

Это хорошее начало. Поместите эти два элемента в два разных файла, и вы получите четкое разделение.

Создайте класс, чтобы поместить вышеперечисленные функции, и вы получите «Модель». Создайте простой.phpфайл для хранения логики презентации, и вы получите «Просмотр». это близкоMVC- большинствоРамкаОбщая объектно-ориентированная архитектура.

foo.php

<?php
$db = new PDO('mysql:host=localhost;dbname=testdb;charset=utf8', 'username', 'password');

// Make your model available
include 'models/FooModel.php';

// Create an instance
$fooModel = new FooModel($db);
// Get the list of Foos
$fooList = $fooModel->getAllFoos();

// Show the view
include 'views/foo-list.php';

models/FooModel.php

<?php
class FooModel
{
    protected $db;

    public function __construct(PDO $db)
    {
        $this->db = $db;
    }

    public function getAllFoos() {
        return $this->db->query('SELECT * FROM table');
    }
}

views/foo-list.php

<?php foreach ($fooList as $row): ?>
    <?= $row['field1'] ?> - <?= $row['field1'] ?>
<?php endforeach ?>

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

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

уровень абстракции базы данных

Многие фреймворки предоставляют собственный уровень абстракции базы данных, некоторые из которых разработаны вPDOверхнего слоя. Эти уровни абстракции обычно оборачивают ваш запрос в метод PHP, который позволяет вашей базе данных иметь некоторые ранее неподдерживаемые функции, имитируя ее. Эта абстракция является реальной абстракцией базы данных, а не просто абстракцией соединения с базой данных, предоставляемой PDO. Этот тип абстракции добавляет определенную нагрузку на производительность, но если вы разрабатываете приложение, которое одновременно использует MySQL, PostgreSQL и SQLite, небольшая дополнительная потеря производительности стоит чистоты вашего кода.

Есть несколько уровней абстракции, которые используютPSR-0илиPSR-4стандарт пространства имен, поэтому их можно установить в любом нужном вам приложении.

назад навигация

Используйте шаблоны

Шаблоны обеспечивают простой способ отделить логику представления от логики контроллера и бизнес-логики.

Как правило, шаблоны содержат код HTML для приложения, но могут использоваться и другие форматы, такие как XML.

Шаблоны также часто называют «представлениями», т.е.Модель-представление-контроллер(MVC) шаблон архитектуры программного обеспечения второго элементаотдельно.

выгода

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

Шаблоны также улучшают организацию внешнего кода. В основном шаблоны помещаются в папку "views", а каждый шаблон помещается в отдельный файл. Этот подход поощряет повторное использование кода, разбивая большие блоки кода на более мелкие повторно используемые фрагменты, часто называемые частичными шаблонами. Например, блоки верхнего и нижнего колонтитула веб-сайта можно настроить как шаблон, а затем разместить над и под каждым шаблоном страницы.

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

Нативные PHP-шаблоны

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

Современные PHP-фреймворки используют некоторую систему шаблонов, большинство из которых используют родной синтаксис PHP. Вне фреймворка некоторые библиотеки классов, такие какPlatesилиAura.View, который предоставляет общие функции современных шаблонов, такие как наследование, макет и расширение, что упрощает использование собственных шаблонов PHP.

Простой пример нативного PHP-шаблона

использоватьPlatesбиблиотека классов.

<?php // user_profile.php ?>

<?php $this->insert('header', ['title' => 'User Profile']) ?>

<h1>User Profile</h1>
<p>Hello, <?=$this->escape($name)?></p>

<?php $this->insert('footer') ?>

Примеры нативных PHP-шаблонов с использованием наследования

использоватьPlatesбиблиотека классов.

<?php // template.php ?>

<html>
<head>
    <title><?=$title?></title>
</head>
<body>

<main>
    <?=$this->section('content')?>
</main>

</body>
</html>
<?php // user_profile.php ?>

<?php $this->layout('template', ['title' => 'User Profile']) ?>

<h1>User Profile</h1>
<p>Hello, <?=$this->escape($name)?></p>

скомпилированный шаблон

Хотя PHP продолжает развиваться в полноценный объектно-ориентированный язык, он служит языком шаблонов.не сильно улучшилось. Скомпилированные шаблоны, такие какTwig,BrainyилиSmarty, который предоставляет новый синтаксис для конкретного шаблона, который заполняет этот пробел. От автоматического экранирования до наследования и упрощенных структур управления — скомпилированные шаблоны разработаны таким образом, чтобы их было проще писать, они были более читабельными и безопасными в использовании. Скомпилированные шаблоны можно даже использовать на разных языках,Mustacheхороший пример. Так как эти шаблоны необходимо компилировать, производительность немного снижается, но при правильном использовании кэширования потери становятся очень незначительными.

Хотя Smarty обеспечивает автоматическое экранирование, по умолчанию эта функция отключена.

Простой пример скомпилированного шаблона

использоватьTwigбиблиотека классов.

{% include 'header.html' with {'title': 'User Profile'} %}

<h1>User Profile</h1>
<p>Hello, {{ name }}</p>

{% include 'footer.html' %}

Пример компиляции шаблонов с использованием наследования

использоватьTwigбиблиотека классов.

// template.html

<html>
<head>
    <title>{% block title %}{% endblock %}</title>
</head>
<body>

<main>
    {% block content %}{% endblock %}
</main>

</body>
</html>
// user_profile.html

{% extends "template.html" %}

{% block title %}User Profile{% endblock %}
{% block content %}
    <h1>User Profile</h1>
    <p>Hello, {{ name }}</p>
{% endblock %}

дальнейшее чтение

Статьи и учебные пособия

библиотека классов

назад навигация

Ошибки и исключения

ошибка

Во многих языках программирования с большим количеством исключений исключения генерируются всякий раз, когда возникает ошибка. Это действительно осуществимый способ. Но PHP — это язык «легких исключений». Конечно, у него есть механизм исключений, и при работе с объектами ядро ​​также начинает использовать этот механизм для работы с ними, но PHP сделает все возможное, чтобы игнорировать происходящее, если только это не серьезная ошибка.

Например:

$ php -a
php > echo $foo;
Notice: Undefined variable: foo in php shell code on line 1

Это просто ошибка уровня уведомления, и PHP с радостью продолжит выполнение. Это может сбить с толку тех, у кого есть опыт программирования с «интенсивными исключениями», например, в Python, ссылка на несуществующую переменную вызовет исключение:

$ python
>>> print foo
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'foo' is not defined

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

Серьезность ошибки

PHP имеет несколько уровней серьезности ошибок. Тремя наиболее распространенными типами информации являются ошибки, уведомления и предупреждения. Они имеют разную степень тяжести:E_ERROR,E_NOTICEа такжеE_WARNING. Ошибка — это серьезная проблема во время выполнения, обычно вызванная ошибкой в ​​коде, которую необходимо исправить, иначе PHP перестанет выполняться. Уведомления носят рекомендательный характер, поскольку программный код может вызывать проблемы во время выполнения, но программа не останавливается. Предупреждения являются нефатальными ошибками, и выполнение программы не прерывается.

Другой тип сообщения, о котором может быть сообщено как об ошибке во время компиляции, — «E_STRICT». Эта информация используется для предложения изменений в программном коде для обеспечения оптимального взаимодействия и совместимости с будущими версиями PHP.

Изменить поведение отчетов об ошибках PHP

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

<?php
error_reporting(E_ERROR | E_WARNING);

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

Встроенное подавление ошибок

Вы можете заставить PHP использовать операторы контроля ошибок@для подавления конкретных ошибок. Размещение этого оператора перед выражением не приведет к последующим ошибкам.

<?php
echo @$foo['bar'];

если$foo['bar']существует, программа выведет результат, если переменная$fooили'bar'Если ключ не существует, он возвращает null и ничего не выводит. Это выражение выдает сообщение об ошибке, если не используется оператор управления ошибками.PHP Notice: Undefined variable: fooилиPHP Notice: Undefined index: bar.

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

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

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

<?php
echo isset($foo['bar']) ? $foo['bar'] : '';

когдаfopen()Возможно, разумным примером использования подавителей ошибок является сбой при загрузке файла. Вы можете проверить наличие файла перед попыткой загрузки, но если файл будет удален после проверки, а затемfopen()не был выполнен (звучит маловероятно, но это происходит), когдаfopen()вернет ложьа такжеДействие броска. Это, вероятно, должен обрабатывать сам PHP, но это пример того, где средства подавления ошибок могут быть эффективными.

Ранее мы упоминали, что в формальной среде PHP нет способа отключить операторы контроля ошибок. ноXdebugесть одинxdebug.screamПункт конфигурации ini может отключить оператор контроля ошибок. Вы можете изменить его следующим образомphp.ini.

xdebug.scream = On

Вы также можете пройтиini_setфункция для установки этого значения:

<?php
ini_set('xdebug.scream', '1')

Расширение PHP "Scream" предоставляет функции, аналогичные xDebug, за исключением того, что ini-настройки Scream вызываютсяscream.enabled.

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

Класс исключения ошибки

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

Это обычная практика в большом количестве современных фреймворков, таких как Symfony и Laravel. в режиме отладки(или режим разработки)Ниже эти фреймворки могут отображать краткий и чистыйstack trace.

Существуют также пакеты, которые лучше обрабатывают ошибки и исключения, напримерWhoops!, который по умолчанию установлен в Laravel, а также может использоваться в любом фреймворке.

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

Подробнее о том, как использоватьErrorExceptionДля обработки сведений об ошибках вы можете обратиться кErrorException Class.

аномальный

Исключения являются стандартными для многих популярных языков программирования, но разработчики PHP часто упускают их из виду. Подобно тому, как Ruby — это язык, который очень серьезно относится к исключениям, независимо от того, что пойдет не так, например, неудачный HTTP-запрос, проблема с запросом базы данных или даже не найденный ресурс изображения, Ruby (или используемые драгоценные камни) будут генерировать исключения, вы может мгновенно узнать, что произошло через экран.

PHP решает эту проблему более небрежно, вызываяfile_get_contents()Функция обычно просто даетFALSEзначение и предупреждение. Многие старые PHP-фреймворки, такие как CodeIgniter, просто возвращают false, записывают информацию в проприетарный журнал или позволяют использовать что-то вроде$this->upload->get_error()метод, чтобы увидеть причину ошибки. Проблема здесь в том, что вместо явного раскрытия ошибки вы должны выяснить, в чем заключается ошибка, и просмотреть документацию, чтобы увидеть, какой неправильный метод используется классом.

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

<?php
$email = new Fuel\Email;
$email->subject('My Subject');
$email->body('How the heck are you?');
$email->to('guy@example.com', 'Some Guy');

try
{
    $email->send();
}
catch(Fuel\Email\ValidationFailedException $e)
{
    // 验证失败
}
catch(Fuel\Email\SendingFailedException $e)
{
    // 这个驱动无法发送 email
}
finally
{
    // 无论抛出什么样的异常都会执行,并且在正常程序继续之前执行
}

исключение SPL

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

<?php
class ValidationException extends Exception {}

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

Например, если вы используете__call()Волшебный метод для вызова недопустимого метода, вместо того, чтобы генерировать неясное стандартное исключение или создавать собственные обработчики исключений, вы можете просто броситьthrow new BadMethodCallException;.

назад навигация

Безопасность

Безопасность веб-приложений

Злоумышленники всегда готовы атаковать ваше веб-приложение, поэтому очень важно повысить безопасность вашего веб-приложения. К счастью, изThe Open Web Application Security ProjectРебята из (OWASP) составили исчерпывающий список известных проблем с безопасностью и способы защиты от них. Этот контрольный список обязателен к прочтению разработчиками, заботящимися о безопасности. Составитель Падраик БрэдиSurvive The Deep End: PHP Security— еще одно хорошее руководство по безопасности веб-приложений для php.

хэш пароля

Все заканчивают тем, что добавляют модуль входа пользователя при создании приложения PHP. Учетная запись пользователя и пароль хранятся в базе данных и используются для аутентификации пользователя при входе в систему.

исправить перед сохранением пароляСекретный код хешаочень важно. Операция хеширования пароля является односторонней и необратимой.Хеш-значение представляет собой строку фиксированной длины, и исходный пароль нельзя обратить. Это означает, что вы можете хешировать другую строку паролей и сравнивать, являются ли они одним и тем же паролем, не зная исходного пароля. Если вы не хэшируете пароли, когда неавторизованная третья сторона попадет в вашу базу данных, информация об учетных записях всех пользователей не будет заблокирована. Некоторые пользователи могут (к сожалению) использовать тот же пароль на других сайтах. Поэтому мы должны обратить внимание на вопрос безопасности данных.

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

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

К счастью, теперь это легко сделать в PHP.

использоватьpassword_hashхешировать пароль

password_hashФункции были представлены в PHP 5.5. Эта функция теперь использует BCrypt, самый надежный алгоритм шифрования, который в настоящее время поддерживается PHP. Конечно, в будущем эта функция будет поддерживать больше алгоритмов шифрования.password_compatВ библиотеке появилась поддержка версий PHP >= 5.3.7.

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

<?php
require 'password.php';

$passwordHash = password_hash('secret-password', PASSWORD_DEFAULT);

if (password_verify('bad-password', $passwordHash)) {
    // Correct Password
} else {
    // Wrong password
}

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

Фильтрация данных

Никогда не доверяйте внешнему вводу. Пожалуйста, отфильтруйте и проверьте перед использованием внешнего ввода.filter_var()а такжеfilter_input()Функции могут фильтровать текст и проверять форматирование (например, адреса электронной почты).

Внешний ввод может быть любым:$_GETа также$_POSTПодождите, пока форма для ввода данных,$_SERVERнекоторые значения в суперглобалах, а также черезfopen('php://input', 'r')Результирующее тело HTTP-запроса. Помните, что определение внешнего ввода не ограничивается данными, отправленными пользователем через форму. Загруженные и загруженные документы, значения сеанса, данные файлов cookie и данные сторонних веб-служб — все это входные данные внешнего сервера.

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

Данные могут обрабатываться по-разному для разных целейфильтр. Например, когда необработанный внешний ввод передается в вывод HTML-страницы, он может выполнять сценарии HTML и JavaScript на вашем сайте! Это атака с использованием межсайтовых сценариев (XSS), которая является очень опасным методом атаки. Один из способов избежать XSS-атак — очистить все пользовательские данные перед выводом на страницу, используяstrip_tags()функция для удаления тегов HTML или использованияhtmlentities()илиhtmlspecialchars()для экранирования специальных символов для получения соответствующих объектов HTML.

Другой пример — передача параметров, которые можно выполнить в командной строке. Это очень опасно (и плохая практика), но вы можете использоватьescapeshellarg()

"/", "../",

PDO

HTML Purifier

unserialize()

allowed_classes

  • .php

register_globals

register_globals$_POST, $_GET$_REQUEST

$_GET['foo']$foo register_globalsoff

php.ini

display_errors = On
display_startup_errors = On
error_reporting = -1
log_errors = On

-1E_ALLphp.net

E_STRICTE_ALLE_ALL-1E_ALL | E_STRICT.

Включить отображение всех ошибок в разных версиях PHP

  • < 5.3 -1илиE_ALL
  •   5.3 -1илиE_ALL | E_STRICT
  • > 5.3 -1илиE_ALL

Производственная среда

чтобыПроизводствоСкройте отображение ошибок в окружающей среде, поместитеphp.iniНастройте следующим образом:

display_errors = Off
display_startup_errors = Off
error_reporting = E_ALL
log_errors = On

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

назад навигация

тестовое задание

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

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

Разработка через тестирование

WikipediaЗначение:

Разработка через тестирование (TDD) — это итеративный процесс разработки программного обеспечения с очень короткими циклами разработки: сначала разработчик пишет неудачный автоматизированный тестовый пример для реализуемой функции или нового метода, а затем пишет код для прохождения этих тестовых случаев и, наконец, проводит рефакторинг. код до приемлемого уровня.Kent Beck, создатель или первооткрыватель технологии, заявил в 2003 году, что TDD поощряет простой дизайн и внушает доверие.

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

модульный тест

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

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

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

PHPUnitЭто отраслевой стандарт для фреймворков модульного тестирования для разработки приложений PHP, но есть и другие необязательные фреймворки:

Интеграционное тестирование

WikipediaЗначение:

интеграционное тестирование (иногда называемое интеграцией и тестированием, сокращенноI&T) — это этап тестирования программного обеспечения, на котором различные модули объединяются для общего тестирования. Это происходит после модульных тестов и перед приемочными тестами. Интеграционное тестирование берет модули, которые были протестированы в качестве входных модулей, объединяет их в единое целое, затем запускает интеграционные тестовые случаи, а затем выводит систему, которую можно систематически тестировать.

Многие из одних и тех же инструментов тестирования можно применять как для модульного, так и для интеграционного тестирования.

функциональное тестирование

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

Инструменты для функционального тестирования

  • Selenium
  • Mink
  • Codeception is a full-stack testing framework that includes acceptance testing tools
  • Storyplayer is a full-stack testing framework that includes support for creating and destroying test environments on demand

поведенческое развитие

Существует два разных типа разработки, управляемой поведением (BDD): SpecBDD и StoryBDD. SpecBDD фокусируется на техническом поведении кода, а StoryBDD фокусируется на поведении и взаимодействии бизнес-логики или функциональности. Оба BDD имеют соответствующие фреймворки PHP.

С помощью StoryBDD вы пишете читабельные истории, описывающие поведение вашего приложения. Затем эти истории могут выполняться как реальные тестовые примеры для приложения.Behatэто фреймворк StoryBDD, используемый в PHP-приложениях, он поддерживается Ruby'sCucumberПроект вдохновлен и реализует Gherkin DSL для описания поведения функции.

При использовании SpecBDD вы пишете спецификацию, описывающую, как должен вести себя фактический код. Вы должны описать, как должна вести себя функция или метод, а не тестировать функцию или метод. PHP предоставляетPHPSpecфреймворк для этой цели, который поддерживается Ruby'sRSpec projectВдохновение проекта.

BDD-ссылка

  • Behat, PHP-фреймворк StoryBDD, вдохновленный RubyCucumberВдохновение проекта.
  • PHPSpecFramework Specbdd PHP получил Ruby'sRSpecВдохновение проекта.
  • Codeception— это полнофункциональная среда тестирования, использующая принципы BDD.

Другие инструменты тестирования

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

Адрес инструмента

  • Seleniumэто инструмент автоматизации браузераintegrated with PHPUnit
  • MockeryэтоPHPUnitилиPHPSpecИнтегрированная платформа фиктивных объектов
  • ProphecyЭто очень мощный и гибкий PHP-фреймворк для имитации объектов со своими собственными идеями. он объединяетPHPSpecи может сочетаться сPHPUnitиспользовать вместе

назад навигация

Сервер и развертывание

Существует несколько способов развертывания приложения PHP в производственную среду.

Platform as a Service (PaaS)

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

PaaS стал популярным способом развертывания, размещения и масштабирования PHP-приложений любого размера. ты сможешьРаздел ресурсовПроверитьПоставщик PHP PaaS «Платформа как услуга»список.

Виртуальный или выделенный сервер

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

Nginx и PHP-FPM

PHP хорошо работает с легкими высокопроизводительными веб-серверами благодаря встроенному диспетчеру процессов FastCGI (FPM).nginxСовместное использование. nginx использует меньше памяти, чем Apache, и может лучше обрабатывать одновременные запросы, что особенно важно для виртуальных серверов, у которых мало памяти.

Апач и PHP

PHP и Apache имеют долгую историю совместной работы. Apache легко настраивается и имеет большое количествоМодуль расширения. Это обычный веб-сервер на виртуальном хостинге, который отлично поддерживает различные PHP-фреймворки и приложения с открытым исходным кодом (например, WordPress). К сожалению, по умолчанию Apache потребляет больше ресурсов, чем nginx, и не очень способен на параллельную обработку.

У Apache есть несколько способов запуска PHP, самый распространенный способ — использовать mode_php5.prefork MPMСпособ. Но это не очень эффективное использование памяти, и если вы не хотите углубляться в управление сервером, то этот простой способ может быть вашим лучшим выбором. Обратите внимание, что если вы используете mod_php5, вы должны использовать prefork MPM.

Если вы стремитесь к высокой производительности и высокой стабильности, вы можете выбрать систему FPM, аналогичную nginx для Apache.worker MPMилиevent MPM, которые используют mod_fastcgi и mod_fcgid соответственно. Этот метод может использовать память более эффективно и работать быстрее, но конфигурация относительно сложна.

Если вы используете Apache 2.4 или новее, вы можете использоватьmod_proxy_fcgiПолучите больше эффективности и простоту настройки.

виртуальный хостинг

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

Чтобы определить, доступна ли последняя версия PHP на вашем виртуальном хостинге, см.PHP Versions.

Создание и развертывание приложений

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

Задачи, которые вы, возможно, захотите автоматизировать:

  • управление зависимостями
  • Компилировать и сжимать статические ресурсы
  • выполнить тест
  • генерация документа
  • Пакет
  • развертывать

Инструменты развертывания

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

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

PhingЭто самый простой способ запустить автоматическое развертывание в мире PHP. С Phing вы можете управлять упаковкой, развертыванием или тестированием с помощью простого XML-файла сборки. Phing (на основеApache Ant) предоставляет богатый набор сценариев задач при установке или обновлении веб-приложений и может быть расширен путем написания дополнительных сценариев задач на PHP. Это прочный и надежный инструмент и существует уже давно, однако этот инструмент может показаться немного старомодным из-за того, как он работает с конфигурацией (XML-файлы).

CapistranoэтоПрограммисты среднего и старшего уровняСистема, подготовленная для выполнения команд на одной или нескольких удаленных машинах структурированным образом с возможностью повторного использования. Он предоставляет предопределенные конфигурации для развертывания приложений Ruby on Rails, но его также можно использовать для развертывания приложений PHP. Для успешного использования Capistrano требуются некоторые знания Ruby и Rake. PHP заинтересован в Capistrano Разработчики могут прочитать сообщение в блоге Дэйва Гарднера.PHP Deployment with Capistrano, как хорошее начало.

Rocketeer gets its inspiration and philosophy from the Laravel framework. Its goal is to be fast, elegant and easy to use with smart defaults. It features multiple servers, multiple stages, atomic deploys and deployment can be performed in parallel. Everything in the tool can be hot swapped or extended, and everything is written in PHP.

Deployerэто простой и функциональный инструмент развертывания, написанный на PHP. Выполняйте задачи параллельно, развертывайте атомарно и поддерживайте согласованность на нескольких серверах. Общие сценарии задач предоставляются для Symfony, Laravel, Zend Framework и Yii. Статья Юнеса РафиEasy Deployment of PHP Applications with DeployerЭто отличное руководство по развертыванию приложений с помощью этого инструмента.

Magallanes is another tool written in PHP with simple configuration done in YAML files. It has support for multiple servers and environments, atomic deployment, and has some built in tasks that you can leverage for common tools and frameworks.

дальнейшее чтение

Server Provisioning

Управление серверами и их настройка могут быть сложной задачей при наличии большого количества серверов.Существуют инструменты для решения этой проблемы, поэтому вы можете автоматизировать свою инфраструктуру, чтобы убедиться, что у вас есть нужные серверы и что они правильно настроены. часто интегрируются с более крупными поставщиками облачного хостинга (Amazon Web Services, Heroku, DigitalOcean и т. д.) для управления экземплярами, что значительно упрощает масштабирование приложения.

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

Puppetэто инструмент, который имеет собственный язык и типы файлов для управления серверами и конфигурациями. Его можно использовать в настройке мастер/клиент или в режиме «без мастера». клиенты будут опрашивать центральный мастер (ы) для новой конфигурации с заданными интервалами и обновлять себя, если необходимо.В режиме без мастера вы можете отправлять изменения на свои узлы.

Chef is a powerful Ruby based system integration framework that you can build your whole server environment or virtual boxes with. It integrates well with Amazon Web Services through their service called OpsWorks.

Дальнейшее чтение:

Непрерывная интеграция

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

— Мартин Фаулер

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

Дальнейшее чтение:

назад навигация

технология виртуализации

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

Если вы разрабатываете под Windows, онлайн-средой является Linux (или другие системы, отличные от Windows), или когда команда разрабатывается совместно, рекомендуется использовать виртуальную машину.

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

Введение в бродяга

VagrantЭто позволяет вам развернуть виртуальную среду с одной информацией о конфигурации и, наконец, упаковать ее в так называемый бокс (то есть виртуальную машину, на которой уже развернута среда).Вы можете установить и настроить бокс вручную, или вы можно использовать инструменты автоматического развертывания, такие какPuppetилиChef .

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

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

Нужна дополнительная помощь?

Вот некоторые другие программы, которые могут помочь вам лучше использовать Vagrant:

  • Rove: используйте Chef для автоматизации установки некоторых часто используемых программ, включая PHP.
  • Puphpet: простой веб-интерфейс используется для создания сценариев Puppet для развертывания сред PHP.Этот проект можно использовать не только в разработке, но и в производстве.
  • Protobox: это слой, основанный на vagrant и веб-интерфейсе, который позволяет устанавливать и настраивать программное обеспечение внутри виртуальной машины с помощью файла YAML.
  • Phansible: предоставляет простой веб-интерфейс для создания сценариев автоматического развертывания Ansible, настроенных для проектов PHP.

Введение в Докер

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

Типичное приложение LAMP содержит следующие три контейнера: веб-сервер, процесс PHP-FPM и MySQL. Как и в случае с общими папками в Vagrant, вам не нужно менять расположение ваших файлов, вы просто указываете Docker, где их найти.

Вы можете создавать контейнеры из командной строки (примеры ниже) или, для упрощения обслуживания, создавать контейнеры для своего проекта.docker-compose.ymlфайл для настройки правил создания контейнеров и того, как контейнеры обмениваются данными.

Docker может помочь, если вы разрабатываете несколько веб-сайтов и хотите разделить их, устанавливая каждый из них на отдельной виртуальной машине, но у вас нет необходимого дискового пространства или времени, чтобы поддерживать все в актуальном состоянии. установка и загрузка выполняются быстрее, вам нужно хранить только одну копию каждого образа, как бы часто он ни использовался, контейнерам требуется меньше оперативной памяти и они используют одно и то же ядро ​​ОС, поэтому вы можете иметь больше серверов, работающих одновременно, и это занимает некоторое время. секунд, чтобы остановить и запустить их, не нужно ждать полной загрузки сервера.Docker особенно удобен, когда несколько веб-сайтов требуют разных сред, вы можете запустить несколько виртуальных хостов Docker на одной машине, и они будут работать в совершенно разных средах, использовать разные веб-службы и эффективно использовать совместное использование памяти, пространство на жестком диске или ресурсы ЦП. Эти виртуальные машины также указывали на перезагрузку в секундах.

Пример: запуск приложения PHP в Docker

в вашем успехеУстановить ДокерПосле этого вы можете запустить веб-сервис всего одной командой. Следующая команда загрузит полнофункциональный образ Apache, включая последнюю версию PHP,/path/to/your/php/filesКаталог будет сопоставлен с корнем документа черезhttp://localhost:8080Вы можете увидеть приветственную страницу по адресу:

docker run -d --name my-php-webserver -p 8080:80 -v /path/to/your/php/files:/var/www/html/ php:apache

Приведенное выше имя инициализирует и запускает контейнер.-dПараметр указывает контейнеру работать в фоновом режиме. Чтобы остановить или запустить его, просто выполнитеdocker stop my-php-webserverа такжеdocker start my-php-webserverкоманды достаточно (другие параметры больше не нужны).

Узнайте больше о Докере

Приведенная выше команда показывает один из способов быстрого запуска службы. Docker также предоставляет множество функций, ожидающих вашего открытия (Docker Hub) содержит тысячи уже созданных образов). Потратьте время на изучение терминологии иРуководство пользователя докераВ ваших интересах, и не запускайте код, загруженный из Интернета, без проверки безопасности — неофициальные зеркала иногда не имеют последних обновлений безопасности. Если у вас есть сомнения по поводу зеркалирования, первый выборофициальный репозиторий.

PHPDocker.ioВеб-сайт может автоматически генерировать все файлы, необходимые для сервисного стека LAMP/LEMP, включая версию PHP и модули расширения по вашему выбору.

назад навигация

тайник

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

Кэш кода операции

Когда файл PHP интерпретируется, он сначала компилируется в файл с именемopcode(Инструкции машинного языка для конкретных процессоров) промежуточный код, а затем внизу были только виртуальные машины. Если файл PHP не был изменен, код операции всегда один и тот же. Это означает, что на этапе компиляции ресурсы ЦП тратятся впустую.

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

Кэши pcode часто могут значительно ускорить выполнение приложения. Все версии, начиная с PHP 5.5, имеют встроенный инструмент кэширования кода операции, который называетсяZend OPcache. В зависимости от установочного пакета/дистрибутива PHP, который вы используете, он обычно включен по умолчанию, пожалуйста, проверьтеopcache.enable phpinfo()а такжеphpinfo()Выходная информация подтверждает, был ли он включен. Более ранние версии также можно установить через расширения PECL.

Дополнительная информация о кэшировании кода операции:

кеш объектов

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

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

Наиболее часто используемые системы кэширования объектов в памяти — это APCu и Memcached. APCu — отличный выбор для кэширования объектов, он предоставляет простой API для кэширования данных в памяти, прост в настройке и использовании. Ограничением APCu является то, что он зависит от сервера. Memcached, с другой стороны, устанавливается как отдельная служба, которая может взаимодействовать по сети, что означает, что вы можете централизовать свои данные в одном месте с высокоскоростным доступом и получать их из множества разных систем.

Стоит отметить, что при использовании PHP в виде CGI (FastCGI) у каждого процесса будет свой кеш, например, данные кеша APCu не могут быть разделены между несколькими рабочими процессами. В этом случае вы можете рассмотреть Memcached, так как он не зависит от процесса PHP.

Обычно APCu быстрее Memcached по скорости доступа, но Memcached имеет больше преимуществ в масштабировании. Если вы не хотите, чтобы ваше приложение использовало несколько серверов или вам не нужны другие функции, предоставляемые Memcached, APCu, вероятно, является лучшим выбором.

Пример использования APCu:

<?php
// check if there is data saved as 'expensive_data' in cache
$data = apc_fetch('expensive_data');
if ($data === false) {
    // data is not in cache; save result of expensive call for later use
    apc_add('expensive_data', $data = get_expensive_data());
}
print_r($data);

Обратите внимание, что до версии PHP 5.5 APC обеспечивала как кэширование объектов, так и кэширование байт-кода. APCu — это проект по переносу кеша объектов APC на PHP 5.5+, поскольку PHP теперь имеет встроенную схему кэширования байт-кода (OPcache).

Еще проекты по системам кеширования:

назад навигация

Документация

PHPDoc

PHPDoc — это неофициальный стандарт для комментирования PHP-кода. она имеетмногоразныеотметкаможно использовать. Полный список тегов и примеры можно посмотретьРуководство по PHPDoc.

Ниже приведен способ написания метода класса:

<?php
/**
 * @author A Name <a.name@example.com>
 * @link http://www.phpdoc.org/docs/latest/index.html
 */
class DateTimeHelper
{
    /**
     * @param mixed $anything Anything that we can convert to a \DateTime object
     *
     * @throws \InvalidArgumentException
     *
     * @return \DateTime
     */
    public function dateTimeFromAnything($anything)
    {
        $type = gettype($anything);

        switch ($type) {
            // Some code that tries to return a \DateTime object
        }

        throw new \InvalidArgumentException(
            "Failed Converting param of type '{$type}' to DateTime object"
        );
    }

    /**
     * @param mixed $date Anything that we can convert to a \DateTime object
     *
     * @return void
     */
    public function printISO8601Date($date)
    {
        echo $this->dateTimeFromAnything($date)->format('c');
    }

    /**
     * @param mixed $date Anything that we can convert to a \DateTime object
     */
    public function printRFC2822Date($date)
    {
        echo $this->dateTimeFromAnything($date)->format('r');
    }
}

Этот класс использует@authorа также@linkразметка, чтобы добавить описание ко всему классу.@authorТег используется для указания автора кода, а в случае нескольких разработчиков может быть указано несколько авторов одновременно. Второй@linkРазметка используется для предоставления ссылки на веб-сайт, что дополнительно объясняет взаимосвязь между кодом и веб-сайтом.

В этом классе первый метод@paramФлаги, описывающие тип, имя и параметры, передаваемые в метод. также,@returnа также@throwsТеги описывают тип возвращаемого значения и исключения, которые могут быть выброшены соответственно.

Второй и третий методы очень похожи и используют@paramотметка. Ключевое различие между вторым и третьим способами заключается в использовании/исключении блоков комментариев.@returnотметка.@return voidТег явно сообщает нам, что возвращаемого значения нет, тогда как в прошлом он был опущен.@return voidДекларация имеет тот же эффект (значение не возвращается).

назад навигация

ресурс

Официальный PHP

Известные быки

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

гид

Провайдер Paas для PHP

To see which versions these PaaS hosts are running, head over to PHP Versions.

Рамка

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

Вам не обязательно использовать фреймворк в каждом проекте. Иногда нативный PHP — правильный выбор, но если вам нужен фреймворк, есть три основных типа:

  • микро рамка
  • полная структура стека
  • каркас компонентов

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

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

Платформа компонентов представляет собой комбинацию нескольких независимых библиотек классов. Различные фреймворки компонентов могут использоваться вместе в микро- или фреймворках с полным стеком.

компоненты

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

Оба репозитория компонентов имеют инструменты командной строки для установки и обновления, которые описаны в разделе [Управление зависимостями] в этом разделе.

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

Например, вы можете использовать [Библиотеку классов проверки FuelPHP] вместо всей инфраструктуры FuelPHP.

[Компоненты Illuminate] в Laravel и фреймворк Laravel станут более несвязанными. На данный момент мы перечисляем только те компоненты, которые имеют наименьшую зависимость от фреймворка Laravel.

Другие полезные ресурсы

Cheatsheets

Больше лучших практик

News around the PHP and web development communities

You can subscribe to weekly newsletters to keep yourself informed on new libraries, latest news, events and general announcements, as well as additional resources being published every now and then:

PHP universe

Video Tutorials

YouTube Channels

YouTube видео

платное видео

книги

Существует множество книг по PHP, но, к сожалению, многие из них очень старые и содержат неверный материал. Есть даже книги по "PHP 6", версии PHP, которой просто не существует и никогда не будет. После того, как PHP 5.6 на самом деле "PHP 7",Часть почему объясняется здесь.

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

бесплатные книги

Платные книги

назад навигация

Сообщество

Сообщество PHP разнообразно и велико, и его участники рады и готовы помочь новичкам. Вы можете присоединиться к местному сообществу пользователей PHP (PUG) или посетить крупную конференцию PHP, чтобы узнать больше о лучших практиках. Вы также можете использовать IRC для просмотраirc.freenode.comна канале #phpc также подписывайтесь@phpcТвиттер учетная запись. Попробуйте познакомиться с новыми разработчиками, узнать что-то новое и, короче говоря, завести новых друзей! Другие ресурсы сообщества включают PHP для Google+.Programmer communityтак же какStackOverflow.

Ознакомьтесь с официальным календарем событий PHP

Группа пользователей PHP

Если вы живете в большом городе, поблизости должна быть группа пользователей PHP. вы можете сделать это на основеPHP.ugизusergroup-list at php.netНайдите местную PUG по этому адресу. также черезMeetup.comИли воспользуйтесь поисковиком (например, несуществующийGoogle) поиск我附近的 php 用户组. Если вы живете в маленьком городке, там может еще не быть МОПСа, в таком случае начните его строить.

Здесь особо упоминаются две глобальные группы пользователей:NomadPHPа такжеPHPWomen.NomadPHPПредлагает два раза в месяц онлайн-встречи групп пользователей с презентациями ведущих умов PHP-сообщества.PHPWomenПервоначально неэксклюзивная группа пользователей для женщин-разработчиков PHP. Членство присуждается тем, кто поддерживает разнообразное сообщество. PHPЖенщины Предоставляет платформу для технической поддержки, наставничества и обучения, а также способствует женскому творчеству и профессиональной атмосфере.

Узнайте о группах пользователей на PHP Wiki

PHP-конференция

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

Найдите PHP-конференции

ElePHPants

ElePHPant is that beautiful mascot of the PHP project with elephant in their design. It was originally designed for the PHP project in 1998 by Vincent Pontier - spiritual father of thousands of elePHPants around the world and 10 years later adorable plush elephant toy came to birth as well. Now elePHPants are present at many PHP conferences and with many PHP developers at their computers for fun and inspiration.

Interview with Vincent Pontier