Ответы пользователя по тегу PHP
  • Что можно использовать от фреймворка в DDD?

    dmitriylanets
    @dmitriylanets
    веб-разработчик
    ваше направление и мысли полностью совпадают с моими, поэтому дополню то что уже писал k2lhu
    DDD это больше про агрегаты и контекст, может вам нужна гексогональная архитектура и все что связанно с clean architecture. Принцип простой, ваша бизнес логика не должна зависеть от деталей реализации, попробуйте написать код без фраймворка например сохранение , отображение простых сущностей, пользователей. У вас будет репозитории не работающие с базой а просто Mock-репозитоиии, но реализующие интерфейсы. Так у вас появится Domain layer и очень тонкий Infrastructure Layer. Далее попробуйте реализовать бизнес логику и сценариции для работы с вашими сущностями, например регистрация пользователя, у вас появится Application Layer. Далее вам нужно организовать контроллеры или модули который будут отображать элементы интерфейса, вы создадите контролеры, вьюхи, модули(виджеты) и тд. например форма регистрации пользователя, так у вас появиться Presentation Layer. Далее вы переведете на динамику ваши репозитории, адаптеры и реализуете сохранение ваших пользователей в базу с помощью Activerecord или DataMapper. Так появиться Infrastructure Layer.
    Плюсы, бизнес логика не зависит от фраймворка, на каждом этапе слоя вы можете подключать фраймворк на уровне как минимум в Infrastructure Layer, Presentation Layer. При смене фраймворка будите менять только их.
    Тесты можно внедрять без проблем особенно на уровне домена и бизнес логики.

    Золотые слова дядюшки Боба:
    Когда вы пишите приложение на фраймворке для заказчика вы гарантируете разработку приложения и его поддержку в течении жизненного цикла, но какую гарантию дает вам разработчик фраймворка?
    Ответ написан
  • Корректно ли передавать объекты (с приватными свойствами и геттерами) во view только для чтения?

    dmitriylanets
    @dmitriylanets
    веб-разработчик
    вытягивать сущности базы данных в слой представления это такое себе, измените поле и все шаблоны использующие накроются, причем накроются что вы не заметите например уведомление будет приходить клиенту а там пропадет его имя.
    поэтому я в вьюху стараюсь передать нужную структуру массив/DTO
    Ответ написан
  • Вопрос по архитектуре, как реализовать класс коннектор для api стороннего сервиса?

    dmitriylanets
    @dmitriylanets
    веб-разработчик
    в луковой используется расслоение с минимум на три слоя:
    Domain - ваши Entity, RepositoryInterface, Service
    Application - бизнес логика приложения
    Infrastructure - реализация контрактов, драйверов,Repository

    Допустим есть необходимость коннектиться к стороннему api сервиса для обработки каких-то данных

    то-что вы описали это инфраструктура, где храните и как ваше дело, конфиги могут быть в ini файле могут быть в бд.
    Ответ написан
  • Всегда ли нужно использовать фреймворки?

    dmitriylanets
    @dmitriylanets
    веб-разработчик
    я тебе скажу одно, можешь даже на чистом php писать
    Ответ написан
  • Как сделать класс управления записями?

    dmitriylanets
    @dmitriylanets
    веб-разработчик
    второй более норм, но есть моменты:
    1. это репозиторий, класс который сохраняет сущности в хранилище
    поэтому
    BookRepository
    2. create update сделать приватными и можно заменить на save
    public function save(Model $model): void{
       if($model->getId()>0){
          $this->update($model);
       }
       else{
         $this->create($model);
       }
    }

    3. public function initDatabase(PDO $db) - это контруктор
    public function __construct(PDO $db)
    4. public function get(Book $book) - что это? public function findById($id): ?Book - более правильно
    5. public function getAll() - правильных ход, но если 1млн записей, все вытащите? нужна критерия выборки и коллекция на выходе а не массив
    public function getAll(Criteria $criteria): BookCollection

    п.с вообще то если ООП то у вас Book должна быть богатой моделью предметной области в данном случае это Rich Model где поведение модели размазано по слоям
    Ответ написан
  • Существуют ли CDN для PHP библиотек?

    dmitriylanets
    @dmitriylanets
    веб-разработчик
    JavaScript мне нужен какой-то плагин

    нужно отталкиваться от цели которую преследуете, Например, если на JavaScript мне нужен какой-то плагин - не аргумент, все таки не забывайте php - серверный язык а пример вы берете практики из клиентского ЯП.
    Ответ написан
  • Как лучше хранить спец цены если их 1000 для каждого клиента?

    dmitriylanets
    @dmitriylanets
    веб-разработчик
    два варианта:
    1. Статически. Запускаем скрипт который в бд формирует цены и хранит конечную.
    2. Динамически. Есть базовая цена и расчет конечной на лету.
    3. Совмещение 1 и 2

    по структуре
    товар - ценовая позиция
    Ответ написан
  • Почему Service Locator это зло и что использовать вместо?

    dmitriylanets
    @dmitriylanets
    веб-разработчик
    Основные минусы:
    - В результате, между классом и его клиентом существует формальный или неформальный «контракт», который выражается в виде предусловий (требований к клиенту) и постусловий (гарантий выполнения работы). Однако если класс принимает экземпляр сервис локатора, или, хуже того, использует глобальный локатор, то этот контракт, а точнее требования, которые нужно выполнить клиенту класса, становятся неясными
    - Когда наш класс использует сервис локатор, то стабильность класса становится неопределенной. Наш класс, теоретически, может использовать что угодно, поэтому изменение любого класса (или интерфейса) в нашем проекте может затронуть произвольное количество классов и модулей
    - Самое страшное в Сервис Локаторе то, что он дает видимость хорошего дизайна. У нас никто не знает о конкретных классах, все завязаны на интерфейсы, все «нормально» тестируется и «расширяется». Но когда вы попробуете использовать ваш код в другом контексте или когда кто-то попробует использовать его повторно, вы с ужасом поймете, что у вас есть дикая «логическая» связанность, о которой вы и не подозревали
    - Для меня ясность и понятность интерфейса класса важнее количества параметров конструктора. Я не исключаю, что бывают случаи, когда сервис локатор является наименьшим злом, но я бы в любом случае постарался свести его использования к минимуму.
    Ответ написан
  • Как реализовать алгоритм бонусов?

    dmitriylanets
    @dmitriylanets
    веб-разработчик
    function calcBonus(float $sumOrd):float {
    $bonusesSum = [
    1000 => 0.03,
    5000 => 0.05,
    10000 => 0.06
    ];
    $correct = 0;
    foreach($bonusesSum as $sum => $per){
        if($sumOrd >= $sum){
            $correct =  $per;
        }
    }
    return $sumOrd * (1 + $correct) - $sumOrd;    
    }
    print_r(calcBonus(10000));
    Ответ написан
  • Как организовать и хранить конфиг по каждому пользователю, чтобы что-то делать один или несколько раз?

    dmitriylanets
    @dmitriylanets
    веб-разработчик
    я делал через вариант {par1: false, par2: true}

    Я конечно могу через запрос всем добавить другой объект со свойством par3 и новый функционал будет добавлен

    - не обязательно обновлять, если при получении нет свойства например view_modal у объекта значит просто он считается не просмотренный, при просмотре и подтверждении занесите свойство view_modal=true
    Ответ написан
  • Как правильно создавать объект-сущность?

    dmitriylanets
    @dmitriylanets
    веб-разработчик
    на самом деле выглядит громоздко, но в этом есть ряд приимуществ.
    1. вы не зависите от слоя хранения, получения
    2. легко накатить тесты

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

    из приемуществ: тестируемый код , маштабируемость в будущем.
    Ответ написан
  • Где проверять авторизацию пользователя?

    dmitriylanets
    @dmitriylanets
    веб-разработчик
    Иногда логика отображания может быть очень сложной, и вроде бы все просто есть контроллер, есть шаблон, есть данные. Подходов для решения может быть много, я бы выбрал следующий:
    1. Контроллер принимает запрос от пользозователя и обращается к сервису для получения контента
    2. Сервис контента, формирует контент но при этом проверяет права доступа, авторизиван не авторизован, дата,время, группа пользователя если атворизован, его пол и все что угодно. Отдает обратно контент согласно условиям.
    3. Контроллер получив контент передает в шаблон.
    Ответ написан
  • Достоверно известно, что некоторый API периодически отваливается по таймауту или с 5хх ошибкой, как решить?

    dmitriylanets
    @dmitriylanets
    веб-разработчик
    обработать ответ 500 ,подождать несколько секунд и попробовать снова, итак N попыток
    Ответ написан
  • Какие инструменты использовать для разбора писем с помощью php?

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

    вот сообственно библиотеки который использовал:
    1. php_imap нативное php расширение, использовали в самом начале, не читало вложения некоторых писем, не работал imap_search для некторых серверов
    2. eden/mail - не читало некоторые вложения
    3. zend-mail (он же laminas-mail) - настроен на очень строгий rfc, если письмо отходит от стандарта кидает исключение.

    В текущйи момент остановились на измененном zend-mail драйвере но временами ловим письма которые не читаются, приходится адаптивровать драйвер.
    Ответ написан
  • Правильно ли я делаю с точки зрения ООП?

    dmitriylanets
    @dmitriylanets
    веб-разработчик
    хелпер может существовать без данных, наверно вряд ли + метод получения ошибок
    тогда будет так
    $validation = new Validation($this->request->post());
    if(!$validation->validate()){
       //var_dump($validation->getErrors());
        return 'error';
    }


    про Helper молчу, вообще непонятно что делает
    Ответ написан
  • Как создать модульность в mvc?

    dmitriylanets
    @dmitriylanets
    веб-разработчик
    хороший подход, использую очень давно, делается просто, я использую из твига такой вызов

    {{ module('Local.Slider',{speed:400}) }}

    или из php
    <?=module('Local.Slider',['speed'=>400]')?>

    Структура
    Local/Modules/Slider/Slider.php
    Local/Modules/Slider/tpl/default.twig

    тут нет модели. так как модель хранится чуть выше уровнем в пакете Local
    Ответ написан
  • Правильно ли так организовывать код?

    dmitriylanets
    @dmitriylanets
    веб-разработчик
    1) из класса Partner должно идти как минимум одно исключение PartnerException
    все исключения в классе Partner будут "переварены в одно" PartnerException
    в вашем случае вы можете добавить еще наследника и PartnerNotFoundException
    логика становиться более лаконичной:
    //App\Services\Partner
    public function getSong(string $singer, string $song_name) : array
        {
            try {
                $json = file_get_contents('partner-domain.com/api?singer=' . $singer);
            } catch (\Exception $e) {
                throw new PartnerException($e->getMessage());
            }
    
            $songs = json_decode($json, true);
    
            //Filter songs by given name
            $result = array_filter($songs, function($song) use ($song_name) {
                return mb_strtolower($song['name'] === mb_strtolower($song_name));
            });
    
            //We need to return only 1 song
            if (!isset($result[0])) {
                  throw new PartnerNotFoundException(sprintf(
                       'parnter not found by %s and %s', $singer, $song_name
                ));
            } 
    
           return [
                    'status' => 'ok',
                    'data' => $result[0];
          ];
    }


    - в контроллере try catch если нужно поймать
    public function getSong(string $singer, string $song_name) : string
        {
             try{
                 $song = $this->partnerService->getSong($singer, $song_name);
             }
            catch(PartnerNotFoundException $ex){
    
                //п.с не помню как в лаевел но смысл поняли
                 return response()->status(404)->send();
            }
    
             return response()->json($song);
        }

    2) через конструктор
    3) аналогично п1
    4) метод называется getSong получить песню, это значит все альтернативные варианты загоняем в исключения, нет песни - исключение, ошибка сервиса, исключение
    Ответ написан
  • Как лучше реализовать проверку данных в классе-сущности?

    dmitriylanets
    @dmitriylanets
    веб-разработчик
    а у вас не должно быть такого что заказ остался а покупателя удалили,
    это то же самое что удалить заказ а позиции заказа остались.

    при удалении покупателя нужно удалять все его заказы
    Ответ написан