Мы принимаем к оплате:
«Подарочный сертификат» от нашего Учебного Центра – это лучший подарок для тех, кто Вам дорог! Оплате обучение и подарите Вашим родным и близким обучение по любому из курсов!!!
«Сертификат на повторное обучение» дает возможность повторно пройти обучение в нашем Учебном Центре со скидкой 1000 рублей!
А также:
Как подключить php класс
Подключаем классы разным макаром (PHP)
Что-то давненько мы здесь не занимались глупостями.
Сегодня мы будем проводить тесты со всеми возможными нарушениями их чистоты и нагло манипулировать статистикой.
Вопрос: как правильно подключать в своём проекте классы, чтобы при этом сэкономить время на их подключение.
Варианты:
- Старый добрый autoload(), как у всех нормальных людей.
- Взять и собрать все классы в один файл, как многие учат.
- Подключать нужные классы явно через require_once().
- И новомодная штучка: Phar-архив.
- Phar-архив ещё можно делать не простой, а со сжатием (GZ или BZ2).
- Ну и phar’ом также два варианта: autoload() или прямое подключение вложенных файлов.
- И поверх этого можно акселератором каким-нибудь пошаманить.
Инструменты
Инструменты для тестов здесь: на гитхабе.
Запуск ./create.php создаёт каталог test, а в нём следующие вещи.
Каталог classes
Структура наших тестируемых классов. Всё по стандарту PSR-0.
Создаётся 5 пространств имён со случайными именами. В каждом создаётся 5 случайных классов со случайным набором методов.
И в каждом из глобальный пространств создаётся ещё 5 вложенных и в них ещё по 5 классов.
Итого 150 классов. Стандартный такой средненький фреймворк.
Файл full.php
Весь «фреймворк» одним файлом.
Файл получился размером 85 K. А общий вес каталога (за счёт большого количества маленьких файлов) 725 К (файловая система ext4).
Несколько спичек уже сэкономили.
Файл exec.php
Это исполняемый скрипт, в котором вызываются нужные классы.
Чтобы добиться какого-то подобия с обычными сценариями: в одном сценарии задействованы не все классы фреймворка, а только 50 (треть). Но к каждому классу может быть несколько обращений.
Работа с каждым классом проста: вызывается статический метод, который выполняет простейшее арифметическое действие. Таким образом время потраченное на работу с классами не должно намного превзойти время потраченное на их подключение (которое мы и тестируем).
Phar-архивы
Из каталога classes создаётся три phar-архива: phar-none.phar, phar-gz.phar, phar-bz.phar (без компрессии, gz, bz).
Размер phar-node.phar: 99 К. Больше чем full.php за счёт дополнительной информации.
Сжатые файлы: 51 К (gz) и 61 К (bz). Нормальные то архиваторы сжимают и получше.
(Нужно расширение Phar и должна быть сброшена настройка phar.readonly в php.ini)
Файлы req.php и phar-req.php
В req.php подключаются все используемые в exec.php файлы (50 штук).
В phar-req.php тоже самое, только подключаются они не из каталога, а из phar-архива.
Тесты
После создания тестового каталога запускаем из консоли тесты: ./run.php [test].
Аргумент [test] может быть следующим:
autoload: подключение файлов из каталога с помощью автолоада. Автолоад простой: заменяет NS1\NS2\Class на DIR/NS1/NS2/Class.php, проверяет наличие файла и подключает его.
full: подключение одного большого файла.
req: подключение нужных файлов через require_once
phar-auto: подключение из phar через автолоад.
phar-req: подключение нужных файлов из phar через require_once.
phar-gz и phar-bz: подключение через автолоад из сжатых архивов.
Так как в цикле прогонять такие тесты бессмысленно, да и вообще чистотой тестов тут уже и не пахнет, просто вызываем несколько раз из консоли (результаты всё равно всегда оказываются похожими).
Результаты
У меня получилось такое (P. Dual Core 2,8Гц, ubuntu, php 5.5.1):
Тест Время (мс)|Прирост памяти (Kb) autoload 6,7 275 full 8,5 776 req 6,1 275 phar-auto 7,6 315 phar-req 7,4 315 phar-gz 10 323 phar-bz 11,7 323Псевдоаналитика
Автолоад vs сборка в один файл
Мало того, что сборка в один файл выела в 3 раза больше памяти (подключаем все классы, когда нужна только треть), так она ещё и по времени проиграла автолоаду с которым призвана бороться.
Дальнейшие тесты показали, что в времени сборка приближается к автолоаду при подключении около 50% от общее числа классов, а потом начинает обходить его.
Автолоад vs requre
require ожидаемо обошло autoload. Логично, ведь при автолоаде происходит много различных телодвижений, которые заканчиваются всё тем же require.
Однако, разница всего лишь 10%. И это при том, что в тесте require_once для каждого класса вызывается только один раз (в реальном проекте, если перед каждым классом вначале подключать нужные ему, один и тот же класс будет запрашиваться многократно и require_once каждый раз будет проверять подключён ли уже файл или нет).
Кроме того, наши тестовые файлы маленькие. На большом файле, его подключение и разбор заняло бы гораздо больше.
Это к теме оптимизации поиска классов: можно убрать из автолоада file_exists(), можно сканировать каталоги и собирать карту классов в массив и использовать его, ещё можно много чего сделать. Но все эти оптимизации будут только в пределах этих 10%. Простое явное require по скорости никак не обойти.
Phar
Phar вполне себе бодренький.
Чуть помедленнее и чуть больше памяти хочет. Но по потреблению памяти до варианта со сборкой в один файл ему далеко.
Хотя тут тоже один файл.
Сжатие: gzip несколько опередил bz2 и здесь (выше у него получился меньший размер файла).
Однако, при сжатии значительно понижается скорость доступа. Да и степень сжатия, как видели выше, как-то не очень (более того, при сжатии нормальным архиватором сжатого phar’а результат получается больше, чем сжатие несжатого).
Так что использовать сжатые phar’ы я бы не рекомендовал. Хотя, возможно, какой-нибудь опкэшер решил бы эту ситуацию.
Zend Opcache
Ну и желательно всё это протестировать со всеми опкэшерами, акселераторами и тому подобным. Но ставить их все лениво, так что проверил только на opcache.
При запуске тестов из консоли следует не забыть включить в php.ini опцию opcache.enable_cli.
Включение opcahce привело к двукратному падению потребления памяти.
Насчёт скорости точных чисел нету, так как результаты начали сильно колебаться, а наши методы не позволяют усреднить их по большому количеству тестов.
Однако, колеблются результаты примерно в тех же пропорциях. Максимально: соответствует времени без opcahce, минимально: в два-три раза меньше. При вызове из консоли могут иногда значительно превосходить по времени вызовы через браузер.
Выводы
1. Нечего париться из-за чепухи. Оптимизация всё равно ничтожная по сравнению с обычным временем выполнения сценария.
2. autoload() — лучшее и самое удобное решение. Тем более все стандарты типа PSR теперь завязаны на него.
3. Производить сборку нескольких файлов в один, построение карт классов и т.п. можно только на продакшене при деплое. Когда всё более существенное уже оптимизировано.
При разработке же: геморроя много, а толку мало.
4. Сборка нескольких файлов в один даёт результат, только если каждый раз используется хотя бы половина вложенных файлов.
5. phar — хорошо (для поставляемых библиотек, которые не нужно изменять).
6. Сжатый phar — не так хорошо.
7. Opcahce вполне себе рулит.
Отказ от обязательств
Автор не считает результаты тестов особо точными, а выводы предельно правильными. И не советует использовать их без проверки в своей деятельности и как аргументы в дискуссии.
Автоматически подключать класс
Автоматически подключать класс можно через функцию spl_autoload_register().
spl_autoload_register(function ($class) { include $_SERVER['DOCUMENT_ROOT'].'/classes/' . $class . '.class.php'; }); $user = new User(); // будет автоматически подключен файл «classes/User.class.php»Данный способ рекомендуется использовать вместо прямого подключения классов через include.
Автоматическое подключение классов через __autoload() признано устаревшим и не рекомендуется к использованию.
Подключение одного php файла в другой
Программисты не пишут код в одном файле, а разбивают проект на десятки файлов и папок. Без этого нельзя обойтись, если хотите ориентироваться в проекте. Если у нас будет 1 файл на 100000 строк кода, то работать с ним будет затруднительно. Один php файл, можно подключить в другой, например так:
include('путь к файлу');Путь к файлу может быть как абсолютным, так и относительным (http://phpfaq.ru/newbie/paths). Но все таки указывать абсолютный путь, это более правильный подход. Так мы можем быть уверены, что подключится именно тот файл, который нам нужен, вне зависимости от точки входа.
Вычислить абсолютный путь для директории и подключить другой файл, который находится в ней, можно следующим образом.
// получаем путь до директории $path = dirname(__FILE__); // подключаем другой php файл, который в ней лежит include($path . '/file.php');Подробности о функции include прочитайте в документации (это обязательно): http://php.net/manual/ru/function.include.php
У функции имеются братья. Такие как include_once, require, require_once.
Отличия заключаются в том, что если использовать require, то в случае если файла нет, будет выдаваться ошибка и выполнение скрипта дальше не пойдет, в отличие от include.
В свою очередь постфикс _once означает, что несмотря на то, сколько раз вы попытаетесь подключить файл, он подключится только 1 раз.
Теперь обратите внимание, что организовывать код проекта, при помощи include и require — неправильный подход. Он был хорош 20 лет назад, когда лучше просто не умели.
Правильным было бы организовать проект так, чтобы у вас не было необходимости подключать необходимый код вручную, при помощи приведенных выше функций. Сделать это можно при помощи функции spl-autoload (http://php.net/manual/ru/function.spl-autoload.php).
С помощью функции autoload, вы сможете сделать так, чтобы когда вы пишите название класса например:
$v = new MyClass();То автоматически, если этого еще не сделано, подключался некий файл, в котором и содержится описание данного класса, а об использовании, для этих целей include, require можно просто забыть.
Приведу простой пример того, как можно сделать автозагрузку классов.
Для этого создаем функцию, в которую будет передавать управления всякий раз, когда в коде встречается название класса, который не был объявлен.
Пример:
spl_autoload_register(function($class){ echo $class; die(); }); $test = new Abracadabra();В данном случае, мы пытаемся создать экземпляр несуществующего класса Abracadabra. С помощью spl_autoload_register определили функцию, которая будет разбираться с этой ситуацией. В переменной $class оказалось название класса, который мы вызываем. Сейчас мы просто печатаем название класса при помощи echo, и нам выведется текст: «Abracadabra».
Если мы вызываем класс, который находится в каком-то пространстве имен, то это также успешно обработается функцией.
Пример:
$test = new MyNamespace\Abracadabra(); // выведет MyNamespace\AbracadabraТеперь осталось доработать нашу функцию автозагрузки так, чтобы она вместо вывода названия класса (нам это ни к чему), организовывала подключение файла с описанием класса.
Она будет выглядеть следующим образом:
spl_autoload_register(function($class){ require __DIR__ . '/src/' . $class . '.php'; });Это очень простой пример, который вы не захотите использовать в настоящих проектах.
У каждого фреймворка могут быть свои способы организовать автозагрузку. Вот описание того, как это работает в yii2: yii2 автозагрузка классов.
Некоторые также придумывают свои велосипеды.
Также существует composer, в котором, при помощи autoload, организована автозагрузка многочисленных расширений.
Как подключить PHP class в Smarty
Подключить php class в smarty очень просто, и это очень удобно использовать в дальнейшей разработке.
На языке разработчиков это называется «зарегистрировать объект класса в smarty». Потом, этот зарегистрированный объект можно использовать в шаблонах smarty, почти также, как и обычный объект класса php: вызывать функция, обращаться к методам и свойствам.
Этот пост родился из комментариев к посту
Как подключить php класс в smarty (как зарегистрировать объект в smarty)
Для регистра объекта класса в smarty нужно вызвать специальную функцию Smarty:
$smarty->assign_by_ref('myobj',$myobj);Где myobj — название объекта, которое вы будете использовать в Smarty, а $myobj — ссылка на объект класса в php.
Как использовать подключенный класс в Smarty (зарегистрированный объект)
Дальше все очень просто. Использование объекта такое же, как и в php.
{$myobj->meth2($bar)}То есть мы ждем выдачу результата от объекта класса, передавая в него параметр.
Вообще говоря, на этом все. Дальнейшее взаимодействие с классом организовывается уже логикой класса и шаблона. Естественно результат работы объекта можно либо вывести на экран сразу, в месте вызова, либо присвоить переменной и вывести позже (только для Smarty версии 3).
Детальнее о регистрации объектов в smarty можно узнать в авторской документации: www.smarty.net/docsv2/ru
Понравилась или помогла статья? Купите мне кофе