Обсуждение PHP - передача параметров в виде массива или класса «Конфигурация» - PullRequest
0 голосов
/ 27 января 2019

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

Во-вторых, я задаю этот вопрос о "качестве кода", а не "Производительность ".

В-третьих, это на самом деле не связано с PHP, но поскольку у каждого языка есть свои" Хорошие практики ", я предпочитаю указывать его.

Наконец, если есть похожий вопрос,извините за это, я не нашел его.

Теперь вопрос:

Лучше ли иметь параметр метода в виде массива или в качестве "Configuration" класса?

Например, я работаю с Doctrine и в своем репозитории, у меня часто есть один метод, который принимает «критерии», и другой метод prepareCriteria, который использует массив $criteria для построения QueryBuilder.

И чем больше я работаю с массивом в этих случаях, тем больше мне интересно, не лучше ли было бы иметь CriteriaBuilder (или CriteriaConfiguration или что-то еще), чтобы полностью контролировать типирование передаваемых параметров и не полагаться напростой строковый ключ массива.

Что вы думаете о тhat?

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

1 Ответ

0 голосов
/ 27 января 2019

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

Просто чтобы показать пример:

php.ini

zend.assertions  = 1
assert.warning   = 1
assert.exception = 1
assert.bail      = 1

PHP

function foobar(array $config)
{    
  assert
  (
    (function($keys_allowed, $keys_expected)use($config)
    {
      // do not stop execution until all issues are output
      $opt_expt = assert_options(ASSERT_EXCEPTION, 0);
      $opt_bail = assert_options(ASSERT_BAIL     , 0);

      $ok = 1;

      $ok &= assert( empty( $diff = array_diff_key(array_fill_keys($keys_expected, 1), $config) ),
                     new AssertionError('Missing mandatory keys: (' . join(', ', array_keys($diff)) . ')'));

      $ok &= assert( empty( $diff = array_diff_key($config, $keys_allowed) ),
                     new AssertionError('Disallowed keys: (' . join(', ', array_keys($diff)) . ')'));

      $ok &= assert( empty( $diff = array_filter
                                    ( $config,
                                      function($v, $k)use($keys_allowed)
                                      {
                                        return isset($keys_allowed[$k]) && $keys_allowed[$k] !== gettype($v);
                                      },
                                      ARRAY_FILTER_USE_BOTH)
                                    ),
                     new AssertionError('Type error on items: (' . join(', ', array_keys($diff)) . ')'));

      //restore configured behaviour    
      assert_options(ASSERT_EXCEPTION, $opt_expt);
      assert_options(ASSERT_BAIL     , $opt_bail);
      return $ok;
    })
    (
      [ 'foo' => 'string', 'bar' => 'integer', 'baz' => 'boolean' ],   [ 'baz' ]
    )
    , new AssertionError('Arguments assertion in function `' . __FUNCTION__ . '` failed.')
  );


  // foobar function stuff
  echo 'Ok!', PHP_EOL;
}

// test
foobar(['foo' => '1',              'baz' => true                     ] );  // Ok!
foobar([              'bar' => 1 , 'baz' => true                     ] );  // Ok!


foobar(['foo' => 1  ,              'baz' => true                     ] );  // Warning: type ; Fatal error
foobar(['foo' => '1', 'bar' => 1                                     ] );  // Warning: missing ; Fatal error
foobar(['foo' => 1  , 'bar' => '1'               , 'forbidden' => 'x'] );  // Warnings: missing, disallowed, type ; Fatal error

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

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

...