Всем привет.


Я (мы как фирма) допиливаем платформу от поставщика, платформа это плагин для WordPress. С фронтендом, JS, HTML я знаком лишь постольку поскольку, поэтому приведённые решения могут оказаться не грамотными, но суть статьи не в этом.


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


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


Введение


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


Задача


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


Соответственно код нового функционала находиться в новых файлах которые надо подгружать на страничке.


Задача: требуется при загрузке страницы подгружать определённые файлы.


Первый блин комом


+<script src="e-cryptex.js"></script>
+<script src="wp-content/themes/tol-child/js/child_realforex.js"></script>

(строчки с "+" это новые строки в исходном коде)


Решение было протестировано для главной страницы и там оно работало, позже выяснилось что для страниц с адресом example.com/about, решение не работало, потому что браузер пытался подгрузить example.com/about/e-cryptex.js и браузер получал — ошибку 404, потому что файл реально лежал в корне — example.com/e-cryptex.js .


Второй вариант


Посмотрел как файлы к страничке цепляют разработчики платформы:


wp_register_script(FILE-ID,FILE-PATH);
wp_enqueue_script(FILE-ID);

Файлы прикрепляются с использованием функционала WordPress — ок, сделаем так же:


// Было:

-<script src="e-cryptex.js"></script>
-<script src="wp-content/themes/tol-child/js/child_realforex.js"></script>

// Стало :

+<?php
+const E_CRYPTEX_JS ='e-cryptex_js';
+wp_register_script(E_CRYPTEX_JS,'/e-cryptex.js',array(),null);
+wp_enqueue_script(E_CRYPTEX_JS);
+const CHILD_REALFOREX_JS = 'child_realforex_js';
+wp_register_script(
+        CHILD_REALFOREX_JS,
+        '/wp-content/themes/tol-child/js/child_realforex.js',
+        array(E_CRYPTEX_JS),
+        null);
+wp_enqueue_script(CHILD_REALFOREX_JS);
+?>

(строчки с "+" это новые строки в исходном коде, строчки с "-" это строки удалённые из исходного кода).


Проверил — работает, ок.


Было две строчки — стало 12, всё в пределах одного файла.


Рефакторинг


Посмотрел я на этот код, и моё чувство прекрасного взбунтовалось:


  • человек не знакомый с WordPress ни чего не поймёт — придётся лезть в справочник что бы понять назначение функций wp_register_script() и wp_enqueue_script()
  • явно делается одно и то же два раза подряд, аргументы только разные — нарушается DRY

Ок, рефакторим.


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


Делаем класс


+class Migesco {
+
+    const SCRIPT = 'script';
+    const SOURCE = 'source';
+    const DEPENDENCY = 'dependency';
+

// На всех страницах, где был изменён функционал используется 'configuration.js', 
// поэтому для него делаем "жёсткий" вариант подгрузки файла.

+    static function attachConfigurationJS(){
+        $configurationFiles = array(
+            array(Migesco::SCRIPT => 'configuration.js',
+                Migesco::SOURCE=>'/configuration.js'));
+        Migesco::includeScriptFiles($configurationFiles);
+    }

// На вход получаем массив с параметрами файлов и все их по очереди подключаем

+    static function includeScriptFiles($scriptFiles){
+        foreach ($scriptFiles as $scriptFile){
+            $dependency = array_key_exists(self::DEPENDENCY,$scriptFiles)
+                ? $scriptFile[self::DEPENDENCY]
+                : array();
+            self::includeScript($scriptFile[self::SCRIPT],$scriptFile[self::SOURCE],$dependency);
+        }
+    }

// Собственно подключение одного скрипта, 
// реализация скрыта от "пользователя", все как Ленин завещал 
// (метод надо было ещё приватным сделать)

+    static function includeScript($id,$source,$dependency){
+        wp_register_script($id,$source,$dependency,null);
+        wp_enqueue_script($id);
+    }
+}

Подключаем и используем


<?php
//Было:

-const E_CRYPTEX_JS ='e-cryptex_js';
-wp_register_script(E_CRYPTEX_JS,'/e-cryptex.js',array(),null);
-wp_enqueue_script(E_CRYPTEX_JS);
-const CHILD_REALFOREX_JS = 'child_realforex_js';
-wp_register_script(
-        CHILD_REALFOREX_JS,
-        '/wp-content/themes/tol-child/js/child_realforex.js',
-        array(E_CRYPTEX_JS),
-        null);
-wp_enqueue_script(CHILD_REALFOREX_JS);

// Стало:
// Подключаем 

+require_once(ABSPATH . 'configuration.php');

// Используем

+const ECRYPTEX_JS = 'cryptex';
+const TRADEROOM_SCRIPT_FILES = array(
+    array(Migesco::SCRIPT => ECRYPTEX_JS,
+        Migesco::SOURCE=>'/e-cryptex.js'),
+    array(Migesco::SCRIPT => 'child_realforex',
+        Migesco::SOURCE=>'/wp-content/themes/tol-child/js/child_realforex.js',
+        Migesco::DEPENDENCY =>ECRYPTEX_JS)
+);
+Migesco::includeScriptFiles(TRADEROOM_SCRIPT_FILES);
?>

Было 12 строчек исходников в одном файле стало 35, и в двух (поддерживай это потом, ищи рыщи где бы что бы ещё подправить, что бы ни чего не забыть, не пропустить, не упустить).


И ещё раз рефактринг


Посмотрел на новый код:


  • какие то статические методы,
  • какие то константы…

топорно смотрится! Помниться такой совет: "если у конструктора нет аргументов, то нужен ли такой класс ?"


Давайте переделаем, но нормальный класс, с нормальным конструктором и методами.


Класс


// Было:

-class Migesco {
-
-    const SCRIPT = 'script';
-    const SOURCE = 'source';
-    const DEPENDENCY = 'dependency';
-
-    static function attachConfigurationJS(){
-        $configurationFiles = array(
-            array(Migesco::SCRIPT => 'configuration.js',
-                Migesco::SOURCE=>'/configuration.js'));
-        Migesco::includeScriptFiles($configurationFiles);
-    }
-    static function includeScriptFiles($scriptFiles){
-        foreach ($scriptFiles as $scriptFile){
-            $dependency = array_key_exists(self::DEPENDENCY,$scriptFiles)
-                ? $scriptFile[self::DEPENDENCY]
-                : array();
-            self::includeScript($scriptFile[self::SCRIPT],$scriptFile[self::SOURCE],$dependency);
-        }
-    }
-    static function includeScript($id,$source,$dependency){
-        wp_register_script($id,$source,$dependency,null);
-        wp_enqueue_script($id);
-    }
-}

//Стало:
// Один класс пришлось разделить на три:
// Один управляет
// Другой выполняет
// Третий данные хранит
//Для объединения классов делаем отдельное пространство имён

+namespace Migesco;
+
+

// Класс Управляет прикреплением файлов к html-страничке

+class Configurator
+{

// Тот самый жёсткий метод для привязки файла общего для всех страниц с изменённым функционалом

+    static function attachConfigurationJS()
+    {
+        $configurationFiles = array(
+            (new WebResource('configuration.js'))->setSource('/configuration.js'));
+        self::attachFiles($configurationFiles);
+    }
+

// Метод для прикрепления файла к html-страничке

+    static function attachFiles($resourceList)
+    {
+        (new Registrar($resourceList))->toRegistrate();
+    }
+}
+

// Класс Выполняет прикрепление файла к html-страничке

+class Registrar
+{

// Массив файлов для прикрепления

+    public $list = array();

// это свойство должно быть private (задел на будущий рефакторинг)

+    /** @var WebResource $resource */
+    public $resource = null;
+
+    public function __construct($list)
+    {
+        $isArray = is_array($list);
+        if ($isArray) {
+            $this->list = $list;
+        }
+    }
+

// Метод для регистрации файла в WordPress

+    function registerScript()
+    {
+        wp_register_script(
+            $this->resource->getName(),
+            $this->resource->getSource(),
+            $this->resource->getDependency(),
+            null);
+    }
+

// Метод для прикрепления файла

+    function enqueueScript()
+    {
+        wp_enqueue_script($this->resource->getName());
+    }
+

// Метод для прикрепления списка файлов

+    function toRegistrate()
+    {
+        $result = false;
+        foreach ($this->list as $resource) {
+            /** @var WebResource $resource */
+            $isResource = $resource instanceof WebResource;
+            if ($isResource) {
+                $this->resource = $resource;
+                $this->registerScript();
+                $this->enqueueScript();
+
+                $result = true;
+            }
+        }
+        return $result;
+    }
+}
+

// Класс для Хранения данных

+class WebResource
+{

// Путь к файлу

+    public $source = '';

// Идентификатор файла

+    public $name = '';

// Зависимости файла

+    public $dependency = array();
+
+    public function __construct($name)
+    {
+        $this->setName($name);
+    }
+
+    /**
+     * @param string $source
+     * @return WebResource
+     */
+    public function setSource($source)
+    {
+        $this->source = strval($source);
+        return $this;
+    }
+
+    /**
+     * @param string $name
+     * @return WebResource
+     */
+    public function setName($name)
+    {
+        $this->name = strval($name);
+        return $this;
+    }
+
+    /**
+     * @param array $dependency
+     * @return WebResource
+     */
+    public function setDependency($dependency)
+    {
+        $isArray = is_array($dependency);
+        if ($isArray) {
+            $this->dependency = $dependency;
+        }
+        return $this;
+    }
+
+    /**
+     * @return string
+     */
+    public function getSource()
+    {
+        return $this->source;
+    }
+
+    /**
+     * @return string
+     */
+    public function getName()
+    {
+        return $this->name;
+    }
+
+    /**
+     * @return array
+     */
+    public function getDependency()
+    {
+        return $this->dependency;
+    }
+}

Использование


 <?php
// Было:

-const TRADEROOM_SCRIPT_FILES = array(
-    array(Migesco::SCRIPT => ECRYPTEX_JS,
-        Migesco::SOURCE=>'/e-cryptex.js'),
-    array(Migesco::SCRIPT => 'child_realforex',
-        Migesco::SOURCE=>'/wp-content/themes/tol-child/js/child_realforex.js',
-        Migesco::DEPENDENCY =>ECRYPTEX_JS)
-);
-Migesco::includeScriptFiles(TRADEROOM_SCRIPT_FILES);

// Стало:

+$traderoomScriptFiles = array(
+    (new Migesco\WebResource(ECRYPTEX_JS))
+        ->setSource('/e-cryptex.js'),
+    (new Migesco\WebResource('child_realforex'))
+        ->setSource('/wp-content/themes/tol-child/js/child_realforex.js')
+        ->setDependency(array(ECRYPTEX_JS))
+);
+Migesco\Configurator::attachFiles($traderoomScriptFiles);
 ?>

Можно ещё раз сделать рефакторинг(платформа работает на PHP 5.6 — с удовольствием бы везде расставил типы, но к сожалению нельзя, можно статичный класс Configurator, сделать более "человеческим", например, инициализировать от списка файлов — веб-ресурсов и метод attachFiles сделать не статическим), но идеальные вещи для идеального мира, мы живём в реальном, и это вносит свои коррективы — время на задачу потрачено — работа по задаче прекращена.


Итого: было 35 строк в исходниках в двух файлах, стало ~170, также в двух файлах.


Что мы получили ?


  1. Теперь не надо лезть в хэлп WordPress`а, что бы понять назначение параметров "функций".
  2. Теперь у нас есть обёртка для подключения файлов и мы можем без болезненно изменять алгоритм подключения файлов — не придётся править все вызовы wp_register_script и wp_enqueue_script
  3. Теперь мы можем сменить WordPress на что угодно и переписать придётся только класс
    Registrar, не надо заменять все вызовы wp_register_script и wp_enqueue_script и следовать логике WordPress`а.

Стоило оно того?


У каждого свой подход к поддержке кодовой базы и своё мнение.


Мой ответ — да.

Комментарии (63)


  1. AlexLeonov
    05.01.2019 23:34
    +2

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

    Очень рекомендую вам почитать про стандарты PSR. Даже тот факт, что вы работаете в среде Wordpress и на PHP 5.6 не может быть оправданием того, что вы, к примеру, не используете пространства имён или не пишете обязательные модификаторы видимости у методов в классах…

    И это я еще не придираюсь к бесконечным «array», выжигающим глаза ))


    1. SbWereWolf Автор
      05.01.2019 23:41
      -2

      «не используете пространства имён» серьёзно не использую?
      "+namespace Migesco;" — такой строчки в исходниках нет?

      И вот это: "// это свойство должно быть private (задел на будущий рефакторинг)" в коментах к коду не встречается?

      чем плох «array»?

      В какой строке кода какой из PSR я игнорирую?


      1. AlexLeonov
        06.01.2019 13:36
        +1

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

        >> "+namespace Migesco;" — такой строчки в исходниках нет?
        Такая строчка, безусловно, есть. И даже есть определение класса непосредственно после нее. Однако следующий же класс «class Registrar» у вас следует без предварительного объявления пространства имён.
        Из этого следует, что либо вы часть классов размещаете в неймспейсах, а часть — нет, либо то, что у вас несколько классов находятся в одном и том же файле. Оба варианта плохи, оба являются серьезной стилистической ошибкой и нарушением стандартов.

        Далее.
        У вас многократно встречаются определения методов без ключевого слова public:

        static function attachConfigurationJS()
        

        function registerScript()
        

        это прямое нарушение PSR-2

        >> чем плох «array»?
        Тем, что вот уже 6 лет как у нас есть замечательный лаконичный синтаксис с квадратными скобками.


        1. SbWereWolf Автор
          06.01.2019 18:44
          -2

          «что у вас несколько классов находятся в одном и том же файле»
          проект на WP написан (на процедурах, ООП нет ни в каком виде), мне надо было заморочиться за написание своего автозагрузчика? или надо было подключить Композер которого там отродясь не было?
          На весь проект, это все три его класса, подключаются одной строчкой (require_once), у вас боль вызывает что я 200 строчек насочинял, а подключить Композер ради трёх классов которые используются в паре мест это норм?

          Вам нравиться объявлять массив как [], мне нравиться — array(), это преступление?

          «без ключевого слова public»
          согласен, можно добавить, это всё что нарушается из PSR-1 / 2? это повод сказать что мой код не соответствует PSR? мне тут перечислить в чём соответствует?

          Граммар-наци, казалось бы взрослые люди…


          1. t_kanstantsin
            07.01.2019 16:40
            +1

            Если не соответсвует хотя бы по 1 параметру, то результат: не соответствует.
            Или я что-то упустил? Иначе кто определит тот порог количества "соответствий", чтобы можно было проигнорировать остальные пункты? А может какие-то пункты более/менее важны, чем остальные?


            1. SbWereWolf Автор
              07.01.2019 17:22
              -1

              это вопрос качества, допустим 39 требований из 40 выполнены, качество = 39/40*100% = 97,5%

              кто то видит мир в чёрных и белых цветах, а кто то в 50 оттенках :)


              1. AlexLeonov
                07.01.2019 17:51

                К сожалению, в реальной жизни всё не так, как вам кажется.

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

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


                1. SbWereWolf Автор
                  08.01.2019 02:22

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


                  1. t_kanstantsin
                    08.01.2019 03:05

                    Извините, не заметил, что исхдиники написаны на go с ассемблерными вставками.


                    Я ошибочно посчитал, что речь идёт он php и php-comunity. Даже не знаю, как такое могло случиться


    1. Alexufo
      06.01.2019 22:27

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


  1. Griboks
    06.01.2019 00:02
    +2

    Слишком сложное использование у вас получилось, слишком много строчек. Проведём ещё немного рефакторинга: автогенерация идентификаторов, последовательное по порядку назначение зависимостей.

    Migesco\Configurator::attachFiles('/e-cryptex.js', '/wp-content/themes/tol-child/js/child_realforex.js');

    Вуаля! Получился практически исходный код. Что принесла нового ваша работа? Ничего. Вот так сюрприз)


    1. SbWereWolf Автор
      06.01.2019 01:06
      -3

      По поводу автогенерации не понял в чём юмор, избавились от аргумента в вызове — это не плюс?
      Про назначение зависимостей по порядку не очень согласен, если файлы между собой не зависимы, то пусть грузятся все десять в параллель.
      У меня не было цели поменять функционал, была цель сделать его более наглядным, и попутно получилось сделать более гибким. Нет ну не знаю, пишите стены кода, зачем нам модульность, правда?

      Теперь, такой вариант, что нам надо прицепить 10-ть файлов, это по версии WP 20 строчек, по моей версии это 10-ть строчек в генерации массива и одна строчка на добавление к странице.
      Было 20, стало 11, это ничего?
      Ок.

      Теперь в 4-х разных шаблонах повторим этот фокус — раньше код добавлении файлов на страницу занимал пол экрана (20 строк), теперь только четверть (11), писать меньше, читать меньше, это ничего?
      Ок.

      У меня привычка думать шире поставленной задачи, на короткой дистанции — проигрышно, но я на короткие не бегаю, только марафоны :)


      1. Griboks
        06.01.2019 11:22

        Вы молодец, мыслите как программист. Только вот, по сути, вы всего лишь перенесли тег script на бэкенд. Все ваши достижения уже по-умолчанию реализованы всеми браузерами. Тот же base или async загрузка скриптов.

        Ирония в том, что вы, судя по статье, этого и не поняли) Я тоже люблю писать велосипеды. Естественно, велосипед работает хуже. Что можно доработать? Кэширование, подключение в 1 строку без массивов, балансировка нагрузки, подстановка шаблона script в клиентский код, какая-нибудь версионность…


  1. vintage
    06.01.2019 00:03
    +16

    Не хотелось бы вас расстраивать, но держите патч:


    -<script src="e-cryptex.js"></script>
    -<script src="wp-content/themes/tol-child/js/child_realforex.js"></script>
    +<script src="/e-cryptex.js"></script>
    +<script src="/wp-content/themes/tol-child/js/child_realforex.js"></script>


    1. VBKesha
      06.01.2019 00:12

      И как потом в отчет написать два дня на исследование проблемы и два на реализацию?
      PS. Не хочу никого обидеть, просто юмор.


    1. L2jLiga
      06.01.2019 00:32
      -3

      А потом оказалось, что сайт находится не в корне, а например example.com/my-site


      1. Zibx
        06.01.2019 06:27
        +1

        Тэг Base спасёт.


    1. SbWereWolf Автор
      06.01.2019 01:12
      -3

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


  1. APXEOLOG
    06.01.2019 00:03
    +8

    Посмотрел я на этот код, и моё чувство прекрасного взбунтовалось:
    человек не знакомый с WordPress ни чего не поймёт — придётся лезть в справочник что бы понять назначение функций wp_register_script() и wp_enqueue_script()
    явно делается одно и то же два раза подряд, аргументы только разные — нарушается DRY

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

    По итогу — обе поставленные цели не достигнуты


    Решение было протестировано для главной страницы и там оно работало, позже выяснилось что для страниц с адресом example.com/about, решение не работало, потому что браузер пытался подгрузить example.com/about/e-cryptex.js и браузер получал — ошибку 404, потому что файл реально лежал в корне — example.com/e-cryptex.js .

    Насколько я знаю HTML, для этого достаточно немного изменить путь


    +<script src="/e-cryptex.js"></script>
    +<script src="/wp-content/themes/tol-child/js/child_realforex.js"></script>
    


    1. SbWereWolf Автор
      06.01.2019 00:51
      -1

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

      wp_register_script(FILE-ID,FILE-PATH);
      wp_enqueue_script(FILE-ID);

      wp_register_script — функция называется регистрировать скрипт, но может регать в глобальном списке любой файл
      wp_enqueue_script — функция называется зауникалить скрипт, по сути прикрепляет файл к странице и может не уникалить
      Функции вызываются от какого то перечисления констант (в исходниках платформы), какая константа какой имеет смысл? не понятно.
      Сравним с:
      $traderoomScriptFiles = array(
          (new Migesco\WebResource('child_realforex'))
              ->setSource('/wp-content/themes/tol-child/js/child_realforex.js')
              ->setDependency(array(ECRYPTEX_JS))
      );
      Migesco\Configurator::attachFiles($traderoomScriptFiles);

      И тут:
      1)создать ресурс, установить источник, установить зависимость;
      2)добавить файлы;

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


      1. APXEOLOG
        06.01.2019 01:13
        +1

        Функции вызываются от какого то перечисления констант (в исходниках платформы), какая константа какой имеет смысл? не понятно.

        Вы могли бы просто добавить комментарий


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

        Тут, как говорится, дело вкуса. По моему личному мнению вы просто нарушили KISS и скорее всего YAGNI, а DRY от этого ничего не выиграл


      1. skymal4ik
        06.01.2019 01:14

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

        Тем более их имена говорят сами за себя.

        Ps enqueue это не про уникальность (unique), а про очередь (queue), т.е. добавить в очередь.


        1. SbWereWolf Автор
          06.01.2019 01:18
          -1

          «enqueue» — спасибо, тогда, да, это хорошее название для функции.


  1. legolegs
    06.01.2019 00:06
    +4

    В можно было бы сделать так:
    +<script src="/e-cryptex.js"></script>
    +<script src="/wp-content/themes/tol-child/js/child_realforex.js"></script>

    конечно, святыни PHP, вордпресса в частности и ынтырпрайза в целом были бы поруганы, зато лично я спал бы спокойнее.

    PS а потом мы удивляемся, почему веб такой жирный и нужны все ресурсы как клиента, так и сервера.


  1. ThunderCat
    06.01.2019 00:21
    +7

    «Почему я не знал про корневой слэш и поэтому сделал 200 строчек из 2»


  1. agmt
    06.01.2019 00:25

    Поиск по «html absolute path» даёт ответ в 1-й ссылке.
    Или это пост из 2к29, в котором гугл забанен?
    UPD: по логике надо было б использовать «html root path», но в таком случае более надёжный источник становится 2-м.


  1. mkshma
    06.01.2019 00:36
    +5

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


  1. hardegor
    06.01.2019 01:24
    +1

    явно делается одно и то же два раза подряд, аргументы только разные — нарушается DRY

    У вас фундаментальный пробел — функции придуманы как-раз для того чтобы не дублировать код, т.е. Don’t repeat yourself
    И поэтому вы придумали еще 200 строк чтобы продублировать существующие функции…


    1. SbWereWolf Автор
      06.01.2019 10:06
      -3

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


      1. hardegor
        06.01.2019 12:16

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


        1. SbWereWolf Автор
          06.01.2019 18:25

          Вы свою мысль как то чётче выразите.
          Я придумал 200 строк кода, что бы унифицировать, то с какими аргументами вызываются функции WP для управления ассетами.
          Для того что бы скрыть реализацию функционала через WP функции, тем самым сделать код шаблона независимым от WP
          Что делает мой код? берёт массив с аргументами и делает вызовы функций, вызов функции в коде это одна строчка, а не *цать строчек как было бы на WP.
          Что с чем не стыкуется?


          1. hardegor
            06.01.2019 20:07

            Они уже существуют и унифицированы, вы просто нарастили поверх функций дополнительную обертку, чтобы вам было удобно не изучать справочник функций WP.
            Или спрошу по другому:
            Зачем скрывать функции WP в шаблоне WP и делать код независимым от WP?
            Ощущаете абсурдность?


            1. SbWereWolf Автор
              06.01.2019 21:17

              может быть потому что из этого шаблона WP надо сделать шаблон независимый от WP? html он есть html, что там делает WP? ассеты цепляет? ссылку на en локализацию добавляет? header footer body склеивает? в основе всё равно куски html и эти куски от смены фреймворка не поменяются.

              " дополнительную обертку, чтобы вам было удобно не изучать справочник функций WP"
              а что бы обёртку накрутить, оборачиваемые функции WP изучить не надо было?
              Ощущаете абсурдность?


              1. Alexufo
                08.01.2019 01:36

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

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


  1. zagayevskiy
    06.01.2019 01:26
    +3

    Жесть какая.

    человек не знакомый с WordPress ни чего не поймёт — придётся лезть в справочник что бы понять назначение функций wp_register_script() и wp_enqueue_script()
    явно делается одно и то же два раза подряд, аргументы только разные — нарушается DRY

    Человек, который не вы, что должен здесь понять?
    +$traderoomScriptFiles = array(
    +    (new Migesco\WebResource(ECRYPTEX_JS))
    +        ->setSource('/e-cryptex.js'),
    +    (new Migesco\WebResource('child_realforex'))
    +        ->setSource('/wp-content/themes/tol-child/js/child_realforex.js')
    +        ->setDependency(array(ECRYPTEX_JS))
    +);
    +Migesco\Configurator::attachFiles($traderoomScriptFiles);
     ?>

    И в какой справочник ему смотреть? В «документацию» вида
    /**
    +     * @param string $name
    +     * @return WebResource
    +     */

    что ли?
    А как же DRY? два раза же повторяете одно и то же, аргументы только меняются!%)


    1. FAngel
      06.01.2019 09:21

      А как же DRY? два раза же повторяете одно и то же, аргументы только меняются!%)

      Уберите это! А то следующая статья будет «как из 200 строчек сделать 20 000...» :)

      А так… действительно — «жесть какая». Вроде и красиво написано. Всякие injection, классики, но читать — сложно. От создания кучи страшных обьектов просто чтоб передать строку, да еще и без видимого смысла сейчас и призрачного выигрыша в будущем — просто коробит Что оно такое и как работает — не понятно. Наверное, единственное оправдание этому всему — разные платформы. Но если их нет и не предвидится — просто потеря времени.

      З.Ы.: ТС, спрячьте название скриптов — уже от одного названия realforex хочется нажать «минус»)


      1. SbWereWolf Автор
        06.01.2019 09:31
        -1

        «уже от одного названия realforex хочется нажать «минус»»
        не мой скрипт, не мне менять.
        вот кому призрачные шансы, а мне потом везде копипастить генерацию версии? спасибо, один класс, один метод поправлю и молодец.
        Кому то не нужна единая стратегия подгрузки файлов? ок, мне нужна, не хочу по всему коду править вызовы wp_*, хочу просто поправить один метод, а если стратегий будет две, то добавить ещё один метод и не ловить баги от того что где то поправил, а где то нет.
        Сейчас на WordPress? наша цель свою платформу написать, что бы вендору помахать рукой, и в качестве фреймворка будет точно не процедурный WP и точно не JQuery.


  1. vyatsek
    06.01.2019 03:44
    +1

    +wp_register_script(
    + CHILD_REALFOREX_JS,
    + '/wp-content/themes/tol-child/js/child_realforex.js',
    + array(E_CRYPTEX_JS),
    + null);
    +wp_enqueue_script(CHILD_REALFOREX_JS);

    Простите вы код в консоли 25 на 80 пишите, почему тут нужен силь Маяковского?

    я не спец в js но неуежели нельзя вытащить '/wp-content/themes/tol-child/js/child_realforex.js' в константы, потом переименовали файл, и ищи его full text search, а что еще хуже, непонтен весь скоуп файлов, которые так передаются. Именование отдельная тема.
    wp_register_script(CHILD_REALFOREX_JS,Somefiles.ChildRealForex, array(E_CRYPTEX_JS),null);
    // итого 91 символ, даже на 1024*768 вполне можно смотреть.


  1. edogs
    06.01.2019 06:18

    Это слишком трэшово что бы воспринимать это искренне.
    Автор, признайтесь, эта статья высокоуровневый сарказм или пародия на что-нибудь?
    Понятнее код не стал, меньше код не стал.
    Если была цель написать класс-оболочку — это хоть как-то можно было понять, но у Вас даже не заявлена такая цель.


    1. SbWereWolf Автор
      06.01.2019 09:36

      обратите внимание на главу — «Что мы получили ?», пункт 2.



  1. Palych_tw
    06.01.2019 09:32

    Жесть.

    Решение было протестировано для главной страницы и там оно работало, позже выяснилось что для страниц с адресом example.com/about, решение не работало, потому что браузер пытался подгрузить example.com/about/e-cryptex.js и браузер получал — ошибку 404, потому что файл реально лежал в корне — example.com/e-cryptex.js .

    про относительный и абсолютный адрес не слышали?

    человек не знакомый с WordPress ни чего не поймёт — придётся лезть в справочник что бы понять назначение функций wp_register_script() и wp_enqueue_script()

    судя по всему, такой человек именно вы.

    явно делается одно и то же два раза подряд, аргументы только разные — нарушается DRY

    вытекает из предыдущего. Нет, делается не одно и то же.

    '/wp-content/themes/tol-child/js/child_realforex.js',

    Еще, неплохо бы формировать абсолютный адрес для подключаемых ассетов. Сделать это можно через
    get_template_directory_uri()
    для тем, или
    plugin_dir_url()
    для плагинов.

    И да, оно того не стоило. Сейчас ваша статья выглядит как — «я не знаю как подключать ассеты в WP, поэтому я изобрету свой велосипед»


    1. SbWereWolf Автор
      06.01.2019 09:58
      -1

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

      Если посмотреть на главу «Второй вариант», то кажется как подключать — нашёл способ, но этот способ не удовлетворяет моих требований к гибкости.
      Кто то пишет на языке программирования, кто то пишет на фреймворке, а мне удобно писать с использованием языка программирования и с использованием фреймворка.
      Нравиться WP прибитый гвоздями к коду? Нравятся вызовы WP, не нравиться лишняя абстракция? о вкусах не спорят.

      «вытекает из предыдущего. Нет, делается не одно и то же.»
      Смысл в том что бы аргументы засунуть в массив и в цикле сделать вызовы с этими аргументами. Количество строк с данными останется прежним, а количество строк кода сократиться в разы. Это ни чего не меняет? в результате работы кода ни чего не меняет, в количестве работы для поддержки кода меняет — количество правок сокращается, нет?


      1. Palych_tw
        06.01.2019 10:37

        Самое смешное когда ты видишь в и-нете примеры реализации, видишь документацию, которой эта реализация соответствует, но у тебя это не работает


        Скорее всего вы что-то недопоняли. Подключить скрипт — нет ничего проще. Начиная с того, что можно просто прописать тег script в файле с хедером/футером темы (если речь про плагин, то так не получится), но при этом задать правильный адрес к файлу, что бы он не отваливался.

        Или же, если нужно сделать все по-правильному, что бы можно было управлять версиями, зависимостями, порядком, положением (в head или перед /body), локализовать скрипты, кешировать и минифицировать — то нужно использовать register и enqueue script/style. А вам достаточно было написать два вызова
        wp_enqueue_script()
        БЕЗ использования
        wp_register_script()


        Если пишите тему, то идете в functions.php и добавляете свой экшн в хук 'wp_enqueue_scripts'

        Выглядит это, примерно, так
        
        /**
         * Enqueue scripts and styles.
         */
        function my_wp_scripts() {
            /*
             * Styles
             */
            //вызовы wp_enqueue_style()
        
            /*
             * Scripts
             */
        //примеры подключения скриптов
            wp_enqueue_script( 'jquery-countdown-js', get_template_directory_uri() . '/js/plugins/jquery.countdown.min.js', array('jquery'), '20151215', true );
            wp_enqueue_script( 'jquery-flexslider-js', get_template_directory_uri() . '/js/plugins/jquery.flexslider-min.js', array('jquery'), '20151215', true );
            wp_enqueue_script( 'main-js', get_template_directory_uri() . '/js/js.js', array(), '1.2', true );
        }
        add_action( 'wp_enqueue_scripts', 'my_wp_scripts' );
        


        и все.

        не нравиться лишняя абстракция?

        Одно дело если бы вы написали свою абстракцию, которая бы не зависела от CMS/фреймворка. Это было бы оправданно.
        Но вы же написали тонну кода поверх существующих абстракций WP. Ваше решение же нельзя перенести на другую CMS/фреймворк без правок вашего класса.

        Теперь мы можем сменить WordPress на что угодно и переписать придётся только класс
        Registrar, не надо заменять все вызовы wp_register_script и wp_enqueue_script и следовать логике WordPress`а.

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

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


        1. SbWereWolf Автор
          06.01.2019 10:48
          -1

          проблема была не с тем что бы подключить скрипт, а с тем что бы он не уникалился. В документации написано передать false (или null не хочу вспоминать), и версия не будет добавлена к ссылке на файл, но ссылка добавлялась.
          Смысл абстракции в том что бы шаблон не переписывать (переписывать поменьше), когда смениться фреймворк.


          1. dopusteam
            06.01.2019 11:58
            +1

            Откуда вдруг появилась проблема с 'не уникалился'? Вы её только что придумали?
            Вы действительно думаете, что с Вашей реализацией будет проще сменить фреймворк?


  1. opiy
    06.01.2019 10:15
    +1

    Когда платят не за результат, а за каждую строчку кода…


  1. zenn
    06.01.2019 10:52

    Не понимаю зачем вы это сделали вообще. Но к комментариям выше относительно кода, PSR и прочего есть вопрос к вот такой конструкции:

    class WebResource
    {
        public $dependency = array();
    	
        public function setDependency($dependency)
        {
            $isArray = is_array($dependency);
            if ($isArray) {
                $this->dependency = $dependency;
            }
            return $this;
        }
    }
    

    даже в php уровня 5.5 и выше она выглядит как то излишне избыточной, зачем вы объявляете переменную сразу как пустой массив (ведь на null куда проще проверять чем на count() пустой массив) и объявляете ее публичной, уже тогда делали вот так:
    class WebResource
    {
        private $dependency;
    	
        public function setDependency($dependency)
        {
    	$this->dependency = (is_array($dependency) ? $dependency : null)
    	return $this;
        }
    }
    

    ну а в эпоху php 7.x можно запросто делать вот так:
    class WebResource
    {
        private $dependency;
    	
        public function setDependency(?array $dependency): self
        {
    	$this->dependency = $dependency;
    	return $this;
        }
    }
    


    Похоже вам действительно платят либо за время, либо за количество строк кода. Не делайте так, пожалуйста, такие труды явно не заслуживают публикации в 2019ом на хабре.


    1. SbWereWolf Автор
      06.01.2019 11:22

      по версии для PHP 5.5 ваше предложение это сделать свойство приватным и использовать тернарный оператор?
      про сделать приватным — можно конечно, если коменты в коде почитать то даже можно найти:
      "// это свойство должно быть private (задел на будущий рефакторинг)"
      и сделать вывод что автор в курсе, что некоторые свойства и методы стоит делать приватными. А можно сделать другой вывод, на ваш выбор.
      Стать рассказывает идею, а не демонстрирует идеальную реализацию, вы ожидаете идеальную реализацию, извините, вы ошиблись статьёй.

      Про тернарный оператор.
      Если весь код это такие цепочки:

      $isSuccess = someMethod();
      if($isSuccess ){
          $isSuccess = otherMethod();
      }
      if($isSuccess ){
          $isSuccess = differentMethod();
      }
      

      , то почему я должен использовать тернарный оператор?
      Я пишу так:
      if($isSuccess ){
          whenSuccess();
      }
      if(!$isSuccess ){
          whenFail();
      }

      и по необходимости могу или удалить первый условный оператор, или второй, в результате правок может остаться только негативный вариант.
      if(!$isSuccess ){
          whenFail();
      }

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


      1. zenn
        06.01.2019 12:23

        Никто не заставляет вас его использовать, но как минимум объявлять переменную лишь для того, чтобы ее использовать в последующем условии — звучит бредово, при условии что метод возвращает булевый результат:

        $result = someMethod($args)
        if ($result) {
            // do something
        }
        // а почему не вот так?
        if (someMethod($args)) {
            // do something
        }
        // при однородности условия тернарник выглядит вполне себе вменяемо:
        $doAnything = (someMethod() ? action1() : action2()); 
        

        Впереди вас еще ждут «магические» методы __isset(), __get(), __set() и тогда вы еще больше сократите этот «макаронный» код — ваш WebResource превратиться в 8-10 строчек с 3мя методами…
        Я это к чему — код выше совершенно не выдерживает критики ни с какой стороны: ни с точки зрения целесообразности такой реализации, ни с точки зрения его качества и принципов проектирования. Не следует воспринимать комментарии как личную критику, вам скорей дают советы «как не нужно делать в 2019» на php.


        1. SbWereWolf Автор
          06.01.2019 18:17

          вы не понимаете почему я не пользуюсь тернарником.

          // при однородности условия тернарник выглядит вполне себе вменяемо:
          $doAnything = (someMethod() ? action1() : action2()); 

          по моим понятиям должно быть одна строка одно действие, тут в одной строке три действия, мой код это разделяй и властвуй, дроби и разжёвывай.
          Вы предлагаете наворачивать экспрешены, привет тому кто будет это отлаживать, сколько раз придётся нажать F11 что бы понять в какой метод/экшен пойдёт выполнение? а если меня интересует только один из этих трёх вариантов и я ставлю брекпоинт на эту строку, то мне все попадания в этот код придётся просматривать, вместо того что бы поставить один брейкпоинт на том варианте развития событий которое меня интересует и только его дебажить, нет придётся дебажить все три варианта. Спасибо.
          Что такое код тусовать, вы не понимаете, давайте каждый будет работать как ему понятней, как ему удобней?


  1. PaulMaly
    06.01.2019 12:00
    +2

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


  1. webdevium
    06.01.2019 19:21
    -1

    Может покрестить его?


  1. Alexufo
    07.01.2019 01:51

    немного не в тему, но и в тему:

    Сейчас вышел новый редактор Gutenberg в WordPress.

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

    Теперь нельзя разрабатывать под WP одним notepad++. ВСЕ.

    Разрабов так достало, что их тыкают в говноархикетуру, им и сама она не очень… и надо же что-то делать и они сделали финт ушами!

    Gutenberg теперь на реакте. Общение по REST API. Примеры кода на NEXTJS прямо в докуметации, никакого ES5 (редко). Без npm, правильного сборщика, теперь ничего не сделаешь!
    Куча функционала теперь будет на JS. И сейчас крайне бедна документашка шо писец.

    Вот так надо выкручиваться от скучной работы) То есть пыха теперь не достаточно явно для разработки на WP.


  1. Kozack
    08.01.2019 01:27

    От части подытожу всё выше сказанное:

    1. Мотивация. Если я правильно понял, то вы пытались сделать код более «универсальным и гибким». Но в итоге только усложнили ситуацию.

      человек не знакомый с WordPress ни чего не поймёт

      Ваш проект — плагин для WordPress. Какова вероятность, что его поддержку доверят человеку который не знаком с этой CMS? Это ж как доверить доработку сайта на php человеку, который не знаком с php.

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

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

    2. Результат, даже менее гибок, чем изначальный.

      Предположим, что я — разработчик, которому передали проект. Я человек ответственный и решил, действовать по вашему сценарию. Весь новый функционал вынес в отдельный файл. И подключать буду так же, как вы, чтобы соблюдать общий подход.

      Мне нужно подключить файл в подвал страницы. И как мне это сделать? Судя по вашему коду, это не возможно, так как ваш код не предусматривает передачу параметра $in_footer в wp_enqueue_script.

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

      В итоге, при здаче, я смогу отметить 20 часов работы как «Отрефакторил код предыдущего разработчика, и привёл его к виду в соответствии с стандартами разработки под WordPress». Хоят по факту — я просто удалю ваше решение и заменю его на два вызова wp_enqueue_script


    1. SbWereWolf Автор
      08.01.2019 03:30

      «Какова вероятность, что его поддержку доверят человеку который не знаком с этой CMS? Это ж как доверить доработку сайта на php человеку, который не знаком с php»
      Мне доверили разработку SPA и вёрстки, при нулевом опыте JS и CSS (моё резюме), что теперь скажите?
      И да, в моей жизни был опыт доработки сайта на php человеком не знаком с php.
      Расскажите мне об этой жизни ещё, я так мало знаю, так мало видел.

      «Мне нужно подключить файл в подвал страницы» + «обязательно необходимо указывать его версию»
      Моё решение позволяет какую угодно логику накрутить не переписывая все подряд вызовы wp_enqueue_script, это называется гибкость, я не продаю библиотеку, я продаю код который можно дальше без болезненно развивать.

      «я смогу отметить 20 часов работы»
      у меня на все три рефакторинга ушло 6 часов. Если вам на 150 строк банального кода надо столько времени, то таково качество вашей работы.
      При чём из этих 6-ти часов, два минимум ушло на чтение доки и поиск адекватного примера.
      Но бумага всё стерпит, вы пишите.


      1. dopusteam
        08.01.2019 09:17

        Мне доверили разработку SPA и вёрстки, при нулевом опыте JS и CSS (моё резюме), что теперь скажите?

        А Вам удобнее было бы копаться в коде фреймворк, на котором Вам доверили разработку или в подобных обёртках?
        Т.е. Если Вы в коде фронта встретите вызов метода самого фреймворк (который можно найти в гугл на раз два) — в этом будет проще разобраться? Или проще увидеть подобную Вашей обёртку, из за которой придётся лезть в исходники, а там уже найти методы фреймворка?
        Да и ситуация не типичная у Вас, если не сказать хуже

        у меня на все три рефакторинга ушло 6 часов

        А изначально нужно было лишь добавить слеш и base
        И время на поддержку будет лишь расти

        Накручивание любой логики требует времени


        1. SbWereWolf Автор
          08.01.2019 12:13

          Накручивание любой логики требует времени

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

          который можно найти в гугл на раз два

          вы меня не слышите, я два часа от Гугла получал примеры использования, которые в моём случаи не работали. Вообще вся логика событий изложена в посте, это не была революция (от html
          <script>
          к неймспейсу Migesco), это была эволюция в 4 этапа.

          А изначально нужно было лишь добавить

          Знал бы прикуп, жил бы в Сочи, статья не про реализацию, а про подход, про логику событий, 8+1 человек проголосовали за вариант «да» — вот для этих людей эта статья. Не для вас.


          1. Kozack
            08.01.2019 15:37

            А 130+ человек, пытаются до вас донести, что идея, заложенная в материал — в корне не правильная. И что не нужно так делать.


      1. Kozack
        08.01.2019 15:56

        я продаю код который можно дальше без болезненно развивать.

        Так в том то и дело, что болезненно. Я смотрю на ситуацию, с точки зрения WordPress разработчика, который придёт на проект после вас и не видел этой статьи. Пытаюсь представить себя на его месте. И описываю вам те мысли и проблемы возникающие у меня.

        Предположим я открыл ваши исходники. Изучил их. Досконально понимаю что за что отвичает.

        И у меня в такой ситуации остаётся один вопрос — а зачем? Я как сторонний человек, без вашего объяснения, смотря только на ваше решение, не пойму в чем принципиальное отличие между

        $traderoomScriptFiles = array(
            (new Migesco\WebResource(ECRYPTEX_JS))
                ->setSource('/e-cryptex.js'),
            (new Migesco\WebResource('child_realforex'))
                ->setSource('/child_realforex.js')
                ->setDependency(array(ECRYPTEX_JS))
        

        и

        wp_enqueue_script(ECRYPTEX_JS, '/e-cryptex.js');
        wp_enqueue_script('child_realforex', '/child_realforex.js', array(ECRYPTEX_JS));
        


        И что ж мне тогда делать? Оставить ваше решение? Я не могу его просто так удалить, вы ж его для чего-то написали. Связаться с вами для пояснения? Подключать часть файлов по вашему а часть по моему? Или использовать ваше решение? А что если в процессе появится какия-то проблема? Дебадить? Допиливать его?

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


  1. Kenya
    08.01.2019 10:52

    И маленькое дополнение: «Имена пространств имён и имена классов ДОЛЖНЫ следовать стандарту PSR-0. В конечном итоге это означает, что каждый класс должен располагаться в отдельном файле и в пространстве имён с хотя бы одним верхним уровнем (именем производителя).»


  1. SbWereWolf Автор
    08.01.2019 11:12

    про отдельный файл уже поговорили, про имя производителя — Migesco, неймспейс так и именуется, или надо Migesco\Attachments?


    1. Kenya
      08.01.2019 11:40

      Да, каждый класс в отдельный файл со своим нейспейсом Migesco\Класс