Как стать автором
Обновить

Внедряем namespace в существующий php-код

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

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

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


Последовательность действий



Что надо переводить: классы, интерфейсы, константы, функции.

Что ищем в коде: define('{CONSTANT_NAME}'), class {CLASS_NAME}, interface {INTERFACE_NAME}, function {FUNCTION_NAME}.

Далее составляем таблицу куда вносим все наши сущности, объявление которых мы нашли в предыдущем шаге. Добавляем в объявлениях всех сущностей необходимый namespace.

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

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

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

Что еще надо менять
Объявляя namespace вы ломаете вызов глобальных сущностей, например, если ваш код выполнял «throw new Exception», то при введении namespace такой код сломается. Вам необходимо будет поменять код на «throw new \Exception», потому что класс Exception существует в глобальном namespace. Можно пройтись по коду в поиске следующих конструкций:
new class, class::method, extends class, implements interface и т.п.

В предыдущих шагах мы составляли таблицу объявленных сущностей и потом искали их вызовы по коду. Если в вашем коде встречаются конструкции вида:
<?php
$class = 'Foo';
$class .= $bar;
$instance = new $class();
?>

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

Отдельно стоит выделить проблему «обслуживающего» кода, либо специфического кода, например если у вас часть классов генерируется автоматически на основе какой-нибудь meta-конфигурации, вам придется учить ваш генератор работать с namespace и вносить изменения в саму meta-конфигурацию.

Вывод


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

Также хотелось бы отметить, что если ваш код не предназначен для широкого круга пользования, и ваше желание ввода namespace обосновано лишь эстетическими соображениями наименования классов между проектами, то стоит рассмотреть возможность постепенного частичного использования namespace, например при вводе нового кода вы можете начать использовать namespace именно в этом новом коде.
Теги:phpnamespaceмиграциярефакторинг
Хабы: PHP
Всего голосов 16: ↑11 и ↓5+6
Просмотры2.3K
Комментарии Комментарии 9

Похожие публикации

Лучшие публикации за сутки