• Как правильно сделать структуру баз данных?

    Maksclub
    @Maksclub
    maksfedorov.ru
    Для такой задачи хорошо подходит паттерн Фаулера Class Table Inheritance, задача которого -- сделать некое наследование в таблицах БД.

    Принцип в ваших терминах:
    Создается некая сущность Client, и у нее наследуются сущности ЮрЛица и ФизЛица, связаны они 1 к 1, то есть на 1 клиента приходится либо одно физлицо, либо одно юрлицо, разруливается это неким маппингом через условное поле type в таблице клиента, нужно только соблюсти момент, чтобы id у физлица не пересекались с юрлицом, например используя uuid или любым другим способом создавать id, например через автоинкремент таблицы клиента.

    Если вы будете реализовывать бекенд на языке PHP, то ORM Doctrine из коробки умеет работать с такой структурой: Документация.
    Ответ написан
    Комментировать
  • NuxtJS Deploy на сервере?

    Maksclub
    @Maksclub
    maksfedorov.ru
    В случае сервера на NodeJS -- поднимаете новый релиз на другом порту (например 3001) и используя супервизор меняете unix-сокеты:
    josephralph.co.uk/supervisor-monitoring-and-runnin...

    Тут опущены нюансы с выкаткой изменений БД. Мой опыт, именно руками, колхозный -- 1 БД и просто выкатывал миграции на ту же БД, в случае провала релиза, проблем не было, были бы -- искал бы решение. А на работе этим занимаются девопсы.
    Ответ написан
    2 комментария
  • Как в Symfony дебажить event?

    Maksclub
    @Maksclub
    maksfedorov.ru
    Продебажить event или все же listener/subscriber?
    Если последнее, то напишите тест, в котором соберёте нужный евент, и передадите его в слушателя, попутно проверив, что все выполняется...

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

    Если без тестов — Запилите простенький контроллер, в котором киньте событие, и продебажьте результат, этот способ займёт 5 минут...

    UPD: С телефона нашёл пример: www.inanzzz.com/index.php/post/04ad/testing-event-...
    суть передает
    Ответ написан
    Комментировать
  • Vagrant, что это?

    Maksclub
    @Maksclub
    maksfedorov.ru
    Vagrant — программный слой, который рулит виртуалбоксом (любой другой системы виртуальных машин).
    Вы в файле описываете конфигурацию популярных сборок, которые хрнатяся на неком хабе + можно свою собрать и сохранить, плюс доустанавливаете (опять же в файле, программно) нужные модули/софтины. Сам факт, что кроме виртуалбокса будет другая система — тоже нужная функциональность, то есть одна и та же конфигурация, но разные драйвера.

    Благодаря этому вы можете одной командой развернуть точную копию ОС с точными версиями софта с нужной конфигурацией и шарить ее, например, между членами команды и разрабатывать всегда в одной среде, которая может быть эмуляцией боевой среды.
    Ответ написан
  • Как в Symfony посмотреть лог миграций?

    Maksclub
    @Maksclub
    maksfedorov.ru
    Все выполненные лежат в таблице migration_versions
    Ответ написан
    Комментировать
  • Как указать дополнительный путь к миграциям?

    Maksclub
    @Maksclub
    maksfedorov.ru
    Вам нужно указать путь к настройкам с вашими миграциями (если они лежат например в бандле)
    Например завести конфиг yml с содержанием, где важное самое migrations_directory

    migrations_directory: "<path>"
    migrations_namespace: Application\Migrations
    table_name: migration_versions


    И потом можете указать его при запуске миграций:
    doctrine:migrations:migrate  --configuration=<path_to_configuration_of_migration_yml>
    Ответ написан
    9 комментариев
  • Зачем использовать callback функции?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    Крайне хорошее описание по таким вещам есть в Википедии. А теперь к примерам:

    1. Передача параметром
    Такие функции удобно передавать параметром/возвращать из других функций. Тут лучше углубиться в тему: Функция высшего порядка

    Например для удобной передачи асбтрактной функциональности, которая будет применяться например к каждому члену итератора/массива. Это используется например в таких стандартных функциях array_{map/filter/reduce}. В коллбеке то, что будет применяться к каждому члену массива.

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

    2. Отложенный/ленивый вызов
    Например в PHP приложениях используется в роутерах/контейнере/логере, да много где. Суть в том, что в соллбеке спрятана функциональность, иногда очень большая. Элементов и этих фукцниональности тоже может быть много, а нужно все зарегистрировать. Чтобы не плодить тысячи объектов при регистрации — каждый кусочек функциональности заворачивают в коллбек, и только при вызове (например роута), вызывается коллбек и соответственно все, что в нем начинает работать.

    class Container
    {
         private $callableServices;
    
         public function add(string $serviceName, callable $service)
         {
              $this->callableServices[$serviceName] = $service;
         }
    
         public function get(string $serviceName)
         {
              $service = $this->callableServices[$serviceName];
    
              return $service();
         }
    }
    
    $container = new Container();
    // объект тут не создается, тк он внутри функции, которая не вызывается
    $container->add('a', function() {
         return new FirstBigService();
    });
    // объект тут не создается, тк он внутри функции, которая не вызывается
    $container->add('b', function() {
         return new SecondBigService();
    });
    
    // Внутри метода get() идет не просто доставание нужного элемента, 
    // а еще и его вызов (тк лежат функции), то есть именно сейчас 
    // произойдет new FirstBigService()
    $service = $container->get('a');


    3. Изоляция контекста
    // тут левый код
    ...
    
    // Код ниже работает изолировано и на него ничего не может подействоват,
    // т.к. внутри свой контекст
    (function() {
        $app = new Application();
        $app->run();
    });
    Ответ написан
    Комментировать
  • Dependency Injection Container, попробовал на практике - не понял смысла?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    Контейнер
    Главная задача контейнера — переиспользовать сервисы более одного раза, например некий провайдер более чем в 1 месте или некий Sender в 20 местах по всему приложению. И упростить к ним доступ.

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

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

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

    Dependency Injection
    И в будущем удобно будет тестировать ?

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

    Главное не объединяйте эти два понятия. Сам паттерн — просто частный случай инверсии зависимости, класс получил зависимость через конструктор/сеттер, и все, он не знает деталей, потому и тестить проще — просто подменил на пустышку.
    А контейнер — средство для работы со сложным приложением, которое внедряет как раз таки, то есть выполняет работу внедрения. Центральное в нем — слово контейнер.

    Несколько точек входа
    По поводу ваших точек входа: несколько точек входи = несколько иницализаций.
    Как-бы они разные по своей сути приложения уже по определению получаются.
    Но вы можете упростить, и вынести инициализацию контейнера в абстракцию — в некий класс App/Kernel и там это делать, а в точке входа инициализировать не контейнер раз за разом, а именно конкретное приложение.
    Ответ написан
    7 комментариев
  • Как сделать unit test метода в котором нужен заполненный массив?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    По-хорошему $this->solutions должно устанавливаться через конструктор, потому вам не составит труда заинжектить это состояние в тестируемый объект.

    Если у вас "пришлось", то можете заюзать некий хак, например через рефлексию/closure::bind установить состояние в тестируемый объект.

    Вот на скорую руку накидал (Разместите его в своем TestCase или прямо в тесте)
    protected function setPrivateProperty(object $object, string $propertyName, $value): void
    {
        $reflectionClass = new \ReflectionClass(get_class($object));
        $property = $reflectionClass->getProperty($propertyName);
        
        $property->setAccessible(true);
        $property->setValue($object, $value);
        $property->setAccessible(false);
    }


    ПРИМЕР
    Класс и метод, который нужно протестить и приватная переменная которого заполняется не через конструктор
    class System 
    {
        // Не важно, как оно будет заполнено, важно, 
        // что в методе мы проверяем некоторые значения  
        // и мы создадим ниже в тестах эти ситуации разными тест-кейсами
        private $solutions;
    
        public function checkRecords(): string
        {
            if (count($this->solutions) === 3) {
                return 'full';
            }
    
            if (count($this->solutions) === 6) {
                return 'overflow';
            }
    
            throw new IncorrectCountException('Incorrect solutions count.');
        }
    }


    Тесты
    public function testCheckRecordsFull(): void
        {
            // 3 элемента
            $data = [1, 2, 3];
            $system = new System();
            $this->setPrivateProperty($system, 'solutions',  $data);
    
            $status = $system->checkRecords();
    
            $this->assertEquals('full', $status);
        }
    
        public function testCheckRecordsOverFlow(): void
        {
            // 6 элементов
            $data = [1, 2, 3, 4, 5, 6];
            $system = new System();
            $this->setPrivateProperty($system, 'solutions',  $data);
    
            $status = $system->checkRecords();
    
            $this->assertEquals('overflow', $status);
        }
    
        public function testCheckRecordsIncorrectCOunt(): void
        {
            // сколько-то элементов, но не 3 и не 6
            $data = [1];
            $system = new System();
            $this->setPrivateProperty($system, 'solutions',  $data);
    
            $this->expectException(IncorrectCountException::class);
            $system->checkRecords();
        }

    Код тестовый, просто отобразить принцип, возможно у вас в классе зависимости -- нужно будет сделать моки и т.д. Тут некоторые повторения можно вынести в setUp().
    Также хочу обратить внимание, что тесты построены по принципу ААА (Arrange, Act, Assert).
    Как итог, 3 ситуации, все протестированы, методу не важно, как заполнлась приватная переменная, но вся его логика протестирована. Все легко и просто.
    Ответ написан
    7 комментариев
  • Зачем frontend девелоперу такой большой опыт?

    Maksclub
    @Maksclub Куратор тега Карьера в IT
    maksfedorov.ru
    Ну как бы человек просто глупеет с возрастом. Мозг хуже работает информация хуже усваивается.

    При всем уважении, я освоил программирование в 27 лет :) Мне сейчас 29, не чувствую отсталости ума :):) Вы можете сказать, что меня уделаете, но я могу утверждать, что вы меня и 19 летнего бы уделали с большей скоростью :)

    Его дело книжки писать бесполезные.
    Наверно ушатаю. Его школьник олимпиданик ушатает 200% на им же созданном языке )

    Вы же довольно умный, зачем вы соревнуетесь с остальными, а не с собой, улучшайте себя!
    Устройтесь в Гугл, напишите новую опен-сорс библиотеку, заработайте через год больше, чем сейчас, кого вы обогнать хотите? Есть куча людей, которые зарабатывают БОЛЕЕ несправедливые деньги БОЛЕЕ несправедливым способом и которые при этом БОЛЕЕ глупее, почему вы выбрали относительно честных и работающих людей в цели для уничижения?!

    Зачем frontend девелоперу такой большой опыт?

    я бы не отказался поработать пол годика с такой зп


    Кроме того, все олимпиадники или в ВК, или в Jetbrains или в Google, точно не без работы, и их всего лишь десятки. А в между прочим вакансий за 2 недели по одной только Java около 3000 штук только на одну Москву. И то в рынке HR воют, что нет инженеров.

    UPD:
    Проглядывается не просто максимализм, а некий снобизм, некая ненависть к тем,
    кто ПО ВАШЕМУ взгляду бездарь. Зря вы так.
    Ответ написан
    21 комментарий
  • Какие нужны знания для крепкого web senior?

    Maksclub
    @Maksclub Куратор тега Веб-разработка
    maksfedorov.ru
    Думаю не стоит задавать вопрос, выпятив в первой строке: "уже пару лет работаю senior full-stack", тк в принципе об этом не стоит писать (отдает тщеславием) и далее читая содержание вопроса — оно не коррелирует с тем, что вы написали в первом предложении, тк именно сеньоры и подсказывают, как и что делать.
    Крч всем пофигу на ваши достижения, и так помогли бы, но помогать сеньору — оксюморон получается...


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

    Если тимлидерство выберете — вам путь к менеджменту, руководству, управлению и вот этому всему.

    Кроме того по обоим направлениям вы можете рассказывать о своих достижениях или своей команды на конференциях, семинарах. (Например Highload/fwdays, phprussia, badoo митапы)
    Ответ написан
    Комментировать
  • Как Tomcat перевести на https?

    Maksclub
    @Maksclub
    maksfedorov.ru
    Поставьте nginx с https как proxy перед Tomcat
    Для убунты это (nginx + ssl) делается очень просто
    Ответ написан
    Комментировать
  • Правильно ли я понимаю суть Интерфейсов в ООП?

    Maksclub
    @Maksclub
    maksfedorov.ru
    Интерфейс — основа полиморфизма.
    Есть один интерфейс, с ним умеет работать некий код. Вуаля, любая реализация этого интерфейса подходит для этого самого кода.

    Пример: есть некий класс заказа Order, он работает с неким отправителем Sender, мы можем жестко "научить" его работать с ним в коде этого Order, а можем просто передавать ему отправителя через конструктор (привет DI), но передавать не сам класс/реализацию, а лишь его абстракцию — интерфейс, то, что будет отправлять, но как — не важно, это будет SenderInterface.

    Теперь мы в Order можем юзать полиморфизм: использовать любой Sender, который реализует этот самый SenderInterface

    Код:
    interface SenderInterface
    {
         public function send(): void {};
    }
    
    class Order
    {
         // тут будет любой, но обязан реализовать SenderInterface
         private $sender;
    
         public function __constuctor(SenderInterface $sender) {
              $this->sender = $sender;
         }
     
         public function save(): void 
        {
            // какой в приватном поле сидит, тот и отправит, 
            // а кто -- текущему объекту все равно, это есть инверсия зависимости 
            // и принцип единственной ответственности, данный класс не отправляет, а поручает
            $this->sender->send();
        }
    }
    
    class MailSender implement SenderInterface
    {
         public function send(): void
         {
               // тут отправка почтой
         }
    }
    
    class TelegramSender implement SenderInterface
    {
         public function send(): void
         {
               // тут отправка телегой
         }
    }
    
    
    // Пример полиморфной работы Order
    $order = new Order(new TelegramSender());
    $order->save(); // тут отправка телеграмом
    
    $order = new Order(new MailSender());
    $order->save(); // тут отправка mail


    Как видите, мы можем добавлять новые сендеры, в них что-то делать, а с ордером будем работать как прежде $order->save() , и вообще его код не трогать

    Дополнение
    Интерфейс есть у любого класса (публичны/приватный), интерфейс наследуется у абстрактного/обычного класса ребенком (кроме того, что наследует поведение), почему полиморфизм иногда (на самом деле ооочень часто) объясняют именно на наследовании одного класса и множественной реализации в виде детей. На самом деле все дело в этом самом интерфейсе.
    Ответ написан
    1 комментарий
  • Какой PHP-микро-фреймворк взять для простенького REST API с авторизацией, и чтобы не из "большой тройки"?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    Symfony 4 в стандартной поставке— это микрофреймворк, серьезно
    Ответ написан
    2 комментария
  • Composer update. Rejected by your constraint. Как исправить?

    Maksclub
    @Maksclub
    maksfedorov.ru
    • Верните к тому виду, как было.
    • Посмотрите веосии всех ваших зависимостей в composer.lock и аккуратно эти версии укажите строго в composer.json
    • Добейтесь того, чтобы все после этих действий работало ровно так, как все работает сейчас
    • Вернитесь к вопросу обновления пакета


    Просто при апдейте вы тянете у нестабильных зависимостей свежий код, а у свежего уже их зависимости далеко ушли вперед
    Ответ написан
  • Как получить сертификат Let’s Encrypt для домена?

    Maksclub
    @Maksclub
    maksfedorov.ru
    Поставьте бота certbot, он автоматом вам все поставит (или в вашем случае повторно зарегает)...
    Правда про панель не скажу, не юзаю их совсем...
    Ответ написан
    4 комментария
  • Если работодатель не разрешает забрать домой изучить договор?

    Maksclub
    @Maksclub Куратор тега Карьера в IT
    maksfedorov.ru
    Встречается часто, решение за вами, в общем, как всегда

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

    Вы вправе предлагать и считать все так, как вы считаете (каламбур :). Это нормально.

    UPD: Но. Можно все же делать красиво и дипломатично -- заявлять об этом не в момент, когда ждут подпись, а например написать за сутки/неделю об этом.

    Человек -- крайне импульсивное существо, видящее узкий контекст и не способно оценивать сложную ситуацию, особенно ту, которую они не знают (а наши HR точно мало видят такие ситуации). помните об этом.
    Ответ написан
    Комментировать
  • Как сгенерировать миграции по сущности вне src/Entity?

    Maksclub
    @Maksclub
    maksfedorov.ru
    Нужно добавить маппинг в настройках /config/doctrine.yml (ну или в том файле, где эти настройки лежат):
    Для 4 версии: https://github.com/symfony/demo/blob/master/config...

    doctrine:
         orm:
                mappings:
                      UserEntities:
                           type: annotation
                           dir: "%kernel.root_dir%/../src/Models/User/Entity"
                           is_bundle: false
                           prefix: <YOUR_NAMESPACE>\Models\User\Entity
    Ответ написан
    1 комментарий
  • Как парсить смс ВК?

    Maksclub
    @Maksclub
    maksfedorov.ru
    Воспользуйтесь внешним сервисом, которые полностью предоставляют API для смс, вот например методы получения сообщения:
    https://smsc.ru/api/http/get_data/inbox/#menu

    И напишите под него некое решение, которое и будет в вашей схеме работать...
    Ответ написан
  • Подвисает NPM, как понять почему?

    Maksclub
    @Maksclub
    maksfedorov.ru
    Добавтье к команде -ddd, это подробный вывод работы команды
    Ответ написан
    Комментировать