PSR-1: 2.3. Побочные эффекты: переменная внутри файла конфигурации - PullRequest
4 голосов
/ 25 марта 2020

PSR-1 включает рекомендацию 2.3. Побочные эффекты :

Файл ДОЛЖЕН объявлять новые символы (классы, функции, константы и т. Д. c.) И не вызывать других побочных эффектов, либо ДОЛЖЕН выполнять logi c с побочными эффектами, но НЕ СЛЕДУЕТ делать и то, и другое.

Рассмотрим этот пример (мой собственный) внутри файла конфигурации. php file:

/**
 * Parsing the database URL.
 * DATABASE_URL is in the form:
 *  postgres://user:password@hostname:port/database
 * e.g.:
 *  postgres://u123:pabc@ec2.eu-west-1.compute.amazonaws.com:5432/dxyz
 */
$url = parse_url(getenv('DATABASE_URL'));
define('DB_HOST', $url['host']);
define('DB_NAME', substr($url['path'], 1)); // get rid of initial slash
define('DB_USER', $url['user']);
define('DB_PASSWORD', $url['pass']);

Если я это сделаю это, я фактически не уважаю рекомендацию. phpcs по праву будет жаловаться на это из-за переменной:

FILE: config.php
-----------------------------------------------------------------------------------------------------------------
FOUND 0 ERRORS AND 1 WARNING AFFECTING 1 LINE
-----------------------------------------------------------------------------------------------------------------
 1 | WARNING | A file should declare new symbols (classes, functions, constants, etc.) and cause no other side
   |         | effects, or it should execute logic with side effects, but should not do both. The first symbol
   |         | is defined on line 17 and the first side effect is on line 162.
-----------------------------------------------------------------------------------------------------------------

Альтернативой может быть следующее:

define('DB_HOST', parse_url(getenv('DATABASE_URL'))['host']);
define('DB_NAME', substr(parse_url(getenv('DATABASE_URL'))['path'], 1));
define('DB_USER', parse_url(getenv('DATABASE_URL'))['user']);
define('DB_PASSWORD', parse_url(getenv('DATABASE_URL'))['pass']);

Без переменной, без проблем. Но это ВЛАЖНО и трудно читать.

Я понимаю, что рекомендация именно такая, и в ней говорится "ДОЛЖНО", а не "ДОЛЖНО" Но это все еще меня беспокоит ... Во-первых, всякий раз, когда я проверяю файл, phpcs будет жаловаться на него, но сообщать об этом только один раз в строке, оставляя дверь открытой для добавления дополнительных «побочных эффектов», которых нет в конфигурационном файле.

Я все еще новичок во всей этой PSR.

Я пропустил какой-нибудь умный способ избавиться от переменной, сохраняя при этом что-то читаемое?

Следствие будет : как с этим справляются серьезные проекты, которые настаивают на следующих рекомендациях к письму?

Ответы [ 2 ]

5 голосов
/ 29 марта 2020

1. Это нормально, не парься

Ты уже упоминал об этом в своем вопросе, но эта рекомендация СЛЕДУЕТ, а НЕ ДОЛЖНА. Если это единственная проблема PSR-1 во всем вашем проекте: хорошая работа!

Но ваш вопрос был: как другие проекты go об этом?

2. Отойдите от определения для конфигурации

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

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

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

Symfony проектов на основе:

  • либо YAML (рекомендуется), либо XML файлы конфигурации для настройте контейнер внедрения зависимости вместе с
  • переменными среды , чтобы задать параметры конфигурации, определяющие c для каждой среды, в которой должно выполняться приложение. Эти env vars определены в специфичных для среды c .env файлах.

Например, чтобы настроить службу базы данных в Symfony В проекте вы создадите файл YAML, который содержит:

services:
    My\Database\Factory: # <-- the class we are configuring
        arguments:
            $url: '%env(DATABASE_URL)' # <-- configure the $url constructor argument

Symfony компилирует это в код PHP, вводя переменную окружения DATABASE_URL в класс, который требует этого.

Затем вы проанализируете DATABASE_URL в конструкторе класса My\Database\Factory и воспользуетесь результатом для создания класса вашей базы данных.

Плюсы:

  • Конфигурация отделена от кода
  • Конфигурация легко изменяется
  • Конфигурация легко читается

Минусы:

  • Внедрение зависимостей и использование DI-контейнера имеет кривую обучения и требует изменения ваших взглядов на конструирование объектов.
1 голос
/ 04 апреля 2020

Как указано в методологии из двенадцати факторов :

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

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

Вы на правильном пути в отношении лучших практик, вам просто нужно исправить некоторые ошибки.

1. Используйте переменные для переменных среды

Вы хотите использовать константы для вещей, которые не являются. Значение имени базы данных может варьироваться в зависимости от среды. Это НЕ константа, это переменная (окружения), вы должны использовать $dbName = getenv('DB_NAME').
Напротив, число π является константой, оно никогда не изменится и может быть жестко закодировано.

Вы можете иметь Посмотрите на исходный код проектов с открытым исходным кодом, таких как Composer или Symfony компонентов, вы увидите, getenv() используется только для заполнения переменных.

2. Используйте непосредственно элементы, ожидаемые в конфигурации

В вашем случае не следует использовать полный URL-адрес базы данных в качестве отдельного элемента конфигурации. Вместо этого вы должны отделить каждый элемент в переменных окружения, таких как DB_HOST, DB_NAME, DB_PORT, как того требует конфигурация.

...