PHP - именованные константы (define) плюсы и минусы

PHP - именованные константы (define) плюсы и минусы

PHP - именованные константы (define) плюсы и минусыВ рамках данной статьи, я расскажу про плюсы и минусы использования именованных констант (define) в языке программирования PHP.

Немногим ранее, я уже писал про автозагрузку и поддержку динамических имен переменных в PHP. Это весьма гибкие и удобные механизмы, однако чье некорректное использование может существенно усложнить код или же и вовсе привести к проблемам безопасности. Поэтому в продолжении этих материалов, я хотел бы упомянуть об еще одном весьма полезном и удобном механизме - именованные константы (объявляемые с помощью define).

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

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

Есть основной файл index.php

<?php
define ('_INDEX_OPEN', 1);
// Далее идет некий основной код
...

И есть какой-нибудь файл движка engine.php, где в первых же строках проверяется наличие этой константы

defined('_INDEX_OPEN') or die('Незя');
// Далее идет некий код
...

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

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

Но, возвращаясь.

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

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

1. Константы нельзя переопределять.

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

Вы все оттестировали, померили скорость, порадовались результату и прочее.

Прошло время и люди стали использовать вашу библиотеку не только в своих самописных проектах, но и в дополнении к различным CMS. Все радовались и бегали по лужам. Однако, в один момент оказалось, что в одной из CMS была добавлена константа в файле конфигурации, из-за которой библиотека сыпалась с "Fatal Error". После долгих разбирательств, вы обнаружили, что смело использовали короткое и удобное название одной из констант.

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

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

define('HOST', 'abc'); // Плохо, может привести к проблемам
define('DB_PASSWORD, 'abc'); // Плохо, может привести к проблемам
define('MY_MODULE_HOST', 'abc'); // Хорошо, так как вряд ли будут такие же имена
define('MY_MODULE_DB_PASSWORD, 'abc'); // Хорошо, так как вряд ли будут такие же имена

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

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

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

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

Во-вторых, вопрос архитектуры. Если в коде есть большое количество констант, то это один из признаков, что архитектура проекта имеет проблемы. И речь не идет о количестве настроек. Так, например, в любой CMS с кучей установленных модулей, настроек невероятно много. Однако, все эти настройки распределены между разными механизмами, такими как банальная таблица в БД. Поэтому код остается читаемым, легко настраиваемым и относительно универсальным.

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

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

3. Константы не хранят объекты, только простые данные.

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

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

// Некий набор параметров
define('PARAM_1' , 1);
define('PARAM_2' , 2);
define('PARAM_3' , 3);
// Определение класса
class MyClass
{
// Идет определение методов
...
// Где-то 200-400 строка
if (defined('PARAM_1') && PARAM_1 > 0) {
...
}
// Идет определение методов
...
// Где-то 670 строка
if ( ! defined('PARAM_1') ) {
define('PARAM_1', 1);
}
// Идет определение методов
...
// Где-то 1000 строка
if (defined('PARAM_2') && defined('PARAM_1') && PARAM_1 > PARAM_2) {
...
}
// Идет определение методов
...
}

Такой подход невероятно усложняет поиск ошибок и проблем, особенно учитывая то, что сами эти PARAM`s могут определяться динамически.

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

Как видите, у именованных констант есть свои нюансы, которые необходимо учитывать.

☕ Понравился обзор? Поделитесь с друзьями!

Комментарии / отзывы  

0 # Протон 28.09.2017 13:52
Порой сталкиваешься с такими проектами, где распиханы константы, и хочется дать в бубен. Автору респект
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору

Добавить комментарий / отзыв

Комментарий - это вежливое и наполненное смыслом сообщение (правила).



* Нажимая на кнопку "Отправить", Вы соглашаетесь с политикой конфиденциальности.
Присоединяйтесь
 

 

Программы (Freeware, OpenSource...)