• Почему дублируются заявки с сайта?

    iNickolay
    @iNickolay
    Возможно, отсутствует favicon сайта.
    Ответ написан
    2 комментария
  • В таблице может быть несколько первичных ключей?

    megafax
    @megafax
    web-программист
    Первичный ключ может быть только один.
    НО
    Первичный ключ может быть по нескольким полям. Это иногда может вводить в заблуждение, что их несколько, но это не так. Он всегда только один.
    Ответ написан
    3 комментария
  • Как правильно протестировать метод?

    SerafimArts
    @SerafimArts
    Senior Notepad Reader
    mockery?
    Ответ написан
    Комментировать
  • Как въехать в программирование (ООП, паттерны)?

    GTRxShock
    @GTRxShock
    SA
    если программируете на php 2-3 года, то пора бы перед сном почитать РНР: объекты, шаблоны и методики программирования (Зандстра) желательно в бумажном варианте.

    + Паттерны проектирования (Фримен) для общего/наглядного понимания паттернов
    + www.phptherightway.com основные тезисы
    + Рефакторинг: улучшение проекта существующего кода (Фаулер) & https://refactoring.guru/ru на будущее, к чему стремиться :)
    Ответ написан
    4 комментария
  • Как подружить REST API и концепцию DDD?

    @vova07
    Приветствую!

    Попробую как можно короче объяснить суть и упущенные моменты которые наблюдаются в вашем примере.

    Ответ 1:
    Прочитайте про так называемые доменные сервисы (Domain Services) и приложенческие сервисы (Application Services). В других статьях ответ на ваш вопрос люди называют Use Cases.
    Юз кйэс (Use Case) - это отдельный сервис который не нарушает stateless и у которого одна конкретная задача.

    Я напишу все примеры на PHP (это самый простой язык который вероятнее всего знаете и вы - извиняюсь за это но думаю лучше Go, Swift, Haskell для этого случая):

    final class CreateCustomer
    {
    	/**
    	 * @var IWriteRepository Интерфейс репозитория, где на самом деле хранистя конкретная имплементация записи сущности.
    	 */
    	private $repository;
    
    	public function __construct(IWriteRepository $repositorym Validator $validator)
    	{
    		$this->repository = $repository;
    		...
    	}
    
    	/**
    	 * @param string $id ИД будущей записи.
    	 * @param array $data ПОТ данные которые мы получаем в момент АПи запроса.
    	 */
    	public function handle(string $id, array $data) : void
    	{
    		/**
    		 * Валидация выбрасывает исключение если данные не валидны или возвращает массив валидных данных.
    		 */
    		$dto = $this->validator->validate($data);
    
    		$customer = new CustomerEntity(new UUID($id));
    		/* Ентити это сущность которое содержить исключительно только бизнес логику и безнесс поведения. 
    		 * В вашем примере у вас были разные сеттеры, в правильном подходе это лишенно смысла,
    		 * и совсем неправильно. Думайте об методах аггрегата (Сушность с которой работает репозиторий это ни * что инное как аггрегат) как проекция бизесс логики. 
    		 * для примера в реальном мире принято говорить `Новый клиент зарегистрировался в системе`, мы никогда * не перечисляем цепь проделанных событий. Кто-то говорит `Клиент заполнил свой аддрес, ФИО, потом
    		 * телефон, и отправил данные` ?!
    		 * 
    		 * Если вы заметили правильно, то в конструкторе сущности передается только идентификатор.
    		 * Такой подход похож на реальную ситуацию, что позволяет легко проектировать бизнес логику.
    		 * регистрация клиента можно сравнить с регистрацией карточки пользователя в магазине.
    		 * - Берём бумагу (или специальный блокнот)
    		 * - Указываем номер клиента (обычно его как-то генерят например дата, время, или номер карточки 
    		 * которую ему выдают)
    		 * - начинаем спрашивать клиента кго персональные данные и заполняем все в ОДНОМ процессе.
    		 * - Потом кидаем блокнот/бумагу оратно или в колецию где лежит другая похожая инфа.
    		 */
    		$customer->register($dto['name'], ...);
    
    		/**
    		 * Именно этот метод делает сохранение нового клиента.
    		 * Сама реализация интереса живет в персистентном слое (`persistence layer`).
    		 */
    		$this->repository->store($customer);
    	}
    }


    Пример выше демонстрирует обычный юз кйэс который является (Application Service) и который живет в слое приложения. Хочу заметить что он делает ровно одну операцию (создает нового клиента) и ничего не возвращает.

    Примечание: Если обратите внимание то юз кйэс в своем методе "handle" принимает только скалярные данные, это важный момент который позволяет писать реюзабельные юз кйэсы. Самый простой пример это веб АПИ и консольная команда которая вводится в терминале.
    Валидация данных делается в том же классе (это не отменяет доменную валидацию но показывает один из хороших мест это можно делать в слое приложения.)
    Другое примечание сводится к тому что очень важно соблюдать простое правило: (SRP) - один юз кэйс одна операция.

    Ответ на вопрос который вероятнее всего будет: Как быть если нам надо создать клиента и вернуть ответ, то есть в обычной REST ситуации ?

    final class PostController extend Controller
    {
    	public function __construct(IWriteRepository, CreateCustomer $createCustomUseCase, RetrieveCustomer $retrieveCustomerUseCase)
    	{
    		...
    	}
    
    	public function __invoke(array $data)
    	{
    		$id = $this->repository->pickNextId();
    		
    		$this->createCustomUseCase->handle($id, $data);
    
    		return $this->retrieveCustomerUseCase->handle($id);
    	}
    }


    Примечание: В реальном мире есть два типа репозиторием, один который записывает данные и делает все манипуляции с данными - WriteRepository и второй Тольятти для чтения который используется во всех других юз кйэсах где нужно только выбирать данные - ReadRepository

    Ответ 2:
    REST API - не подразумевает то что вы описываете.
    В REST идеологии на запрос клиента надо вернуть тот же ответ. То есть сокращенно это подразумевает получение целого ресурса (ресурс - так называемая схема запроса/ответа) и возврат его же. (Ответ может содержать дополнительные данные но они вспомогательные, такие как хедеры, пагинация, и так далее.)

    Ответ 3:
    Все что не является бизнес логикой надо старится вынести из сущности.
    Сущность это состояние безнос процесса.
    Если некие атрибуты не имеют смысла для бизнеса, то их надо избегать.

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

    Если там входит логи, временные тэги, дополнительные данные для других последующих операций, то сущность спроектирована неправильно.

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

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

    Итог:
    разные сущности могут содержать в себе (инкапсулировать) разные Value Objects разделение классов по строгим типам очень важно. Если есть цикл жизни и идентификатор то это сущность, если нету цикла то это ВО (VO = Value Object).

    Ваш CustomerState не имеет цикла жизни что сразу ограничивает вас в использовании сущности. Это сирого ВО. А если в логике появляются разные "if", "else" (лично мое мнение которое разделяют другие разработчики) то это признак плохой архитектуры, и повод задуматься над разделением Во на два или на подтипы. "VipState", "RegularState" но это больше правда для ситуаций с количеством от Ю 2 значений, если их два, то имеет место сделать белковый флаг который будет указывать на то или другое значение.

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

    П.С.С: Все выше сказанное это личные наблюдения, и персональная интерпретация теории. Вы МОЖЕТЕ учитывать мои ИДЕИ но НЕ НАДО СЛЕДОВАТЬ моим интерпретациям.
    ДДД это принцип мышления, еще никто в мире не смог доказать и описать 100% правильный подход, который бы должен быть быть эталоном, даже автор мышления.
    Пробуйте, экспериментируйте и делитесь опытом!

    Удачи!
    Ответ написан
    Комментировать
  • Чем Laravel лучше Symfony?

    dmitriylanets
    @dmitriylanets
    веб-разработчик
    Laravel - для стартапов
    Symfony - для Enterprice с сложной логикой
    Ответ написан
    2 комментария
  • Почему не работает метод save() в связанных моделей?

    SerafimArts
    @SerafimArts
    Senior Notepad Reader
    Потому что argument 1 to Illuminate\Database\Eloquent\Realtions\BelongsToMany::save() must be an instance of Illuminate\Database\Eloquent\Model, but an array given.

    Всегда рад помочь, не благодари.
    Ответ написан
    Комментировать
  • Как отсортировать массив php?

    usdglander
    @usdglander Куратор тега PHP
    Yipee-ki-yay
    usort($array, function($a, $b) { 
        return $a['time'] > $b['time']; 
    });
    Ответ написан
    Комментировать
  • Как добавить валидацию на уникальное поле в doctrine?

    @jaxel
    У вас валидатор UniqueEntity сразу на два поля указан. Он проверяет уникальность комбинации "username" и "phone". Вам нужно разделить их на два отдельных валидатора, а не указывать оба поля в одном.
    Ответ написан
    Комментировать
  • Как сделать корзину для анонимус юзеров?

    Taraflex
    @Taraflex
    Ищу работу. Контакты в профиле.
    Никак не делать. Хранить локально в браузере в localstorage.
    После логина отправлять на сервер.
    Ответ написан
    8 комментариев
  • Есть ли какие либо права на ПО у заказчика?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Любые права на использование ПО пользователь приобретает исключительно по договору либо по лицензионному соглашению (согласие с которым трактуется как присоединение к договору-оферте). Нет договора - ПО используется незаконно, пользователя можно привлечь по статье.
    Исключение - если ПО разработано в рамках служебных обязанностей, тогда имущественные права по умолчанию принадлежат работодателю.
    Ответ написан
  • Телефон в качестве логина - как порешать?

    @bkosun
    Пользователь должен указывать телефон в международном формате, Вам достаточно просто удалять все лишние символы при регистрации/авторизации, а проверять телефон можно так (все страны):

    function phone_number($phone)
        {
            return (bool)preg_match("/^\+?([87](?!95[4-79]|99[08]|907|94[^0]|336|986)([348]\d|9[0-6789]|7[0247])\d{8}|[1246]\d{9,13}|68\d{7}|5[1-46-9]\d{8,12}|55[1-9]\d{9}|55[12]19\d{8}|500[56]\d{4}|5016\d{6}|5068\d{7}|502[45]\d{7}|5037\d{7}|50[4567]\d{8}|50855\d{4}|509[34]\d{7}|376\d{6}|855\d{8}|856\d{10}|85[0-4789]\d{8,10}|8[68]\d{10,11}|8[14]\d{10}|82\d{9,10}|852\d{8}|90\d{10}|96(0[79]|17[01]|13)\d{6}|96[23]\d{9}|964\d{10}|96(5[69]|89)\d{7}|96(65|77)\d{8}|92[023]\d{9}|91[1879]\d{9}|9[34]7\d{8}|959\d{7}|989\d{9}|97\d{8,12}|99[^4568]\d{7,11}|994\d{9}|9955\d{8}|996[57]\d{8}|9989\d{8}|380[3-79]\d{8}|381\d{9}|385\d{8,9}|375[234]\d{8}|372\d{7,8}|37[0-4]\d{8}|37[6-9]\d{7,11}|30[69]\d{9}|34[67]\d{8}|3[12359]\d{8,12}|36\d{9}|38[1679]\d{8}|382\d{8,9}|46719\d{10})$/", $phone);
        }
    Ответ написан
    Комментировать
  • Чем организовать многопоточность в php?

    @Wexter
    Ответ написан
    Комментировать
  • Как перехватить все url запросы в Laravel?

    wielski
    @wielski
    ✔ Совет: Вам помогли? Отметьте ответы решением.
    Route::group(['middleware' => ['auth']], function() {
      // тут все ваши роуты
    });
    Ответ написан
    5 комментариев
  • Почему Intervention Image Cache не кеширует изображения?

    @Nc_Soft
    Вот смотрю я на такие попытки кеширования и у меня просто недоумение это вызывает. Вы серьезно собираетесь дергать пхп на каждый запрос к картинке?
    Если хотите ресайзить картинки автоматически, то кешируйте через nginx, а через эту бесполезную функцию cache
    fastcgi_cache_path  /home/www/nginx levels=1:2 keys_zone=CACHE:256m max_size=100m inactive=100d; 
    
        server {
            server_name domain.ltd;
            listen 80;
    
            location ~ /image/resize/([0-9]+) {
                fastcgi_cache CACHE;
                fastcgi_cache_key "domain.ltd$request_uri";
                fastcgi_cache_use_stale updating error timeout http_500;
                fastcgi_cache_valid 200 302 304 30d;
                fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
                add_header X-Cache $upstream_cache_status;
    
                fastcgi_pass  127.0.0.1:9000;
                fastcgi_index index.php;
               fastcgi_param SCRIPT_FILENAME /home/www/domain.ltd/public/index.php; 
                include fastcgi_params;


    Ну и сам скрипт который ресайзит (от отрабатывает один раз, потом nginx отдаёт картинку из кеша, не дергая пхп)
    $img = Image::make($path)->resize(420, 360);
    return $img->response('jpg');
    Ответ написан
    1 комментарий
  • Как получить API не регистрируясь в системе, которая предоставляет API?

    SerafimArts
    @SerafimArts
    Senior Notepad Reader
    Конечно можно!

    1) Выучиться
    2) Пройти собеседование и устроиться на работу в заведение, где хочется получить доступ к АПИ
    3) Доработать до должности, где будет возможность получить доступ к проду
    4) Пушишь в БД ключик и вуаля! Без регистрации и смс, да ещё и денег дадут.
    Ответ написан
    1 комментарий
  • Как сделать редирект с задержкой в Laravel?

    Sanasol
    @Sanasol Куратор тега Laravel
    нельзя просто так взять и загуглить ошибку
    Либо делаете редирект 301, либо показываете страницу на которй meta/js редирект, и это уже не будет 301 редирект.
    Третьего не дано.


    view('production.pages.home.test');  
    sleep(3); 
    Redirect::to('https://final.com', 301);


    26326068d049fcc7301199f97240.png
    Ответ написан
    Комментировать
  • Как при помощи gulp собрать bower зависимости?

    yarkov
    @yarkov
    Помог ответ? Отметь решением.
    Вот тут мой ответ почитайте. И не надо ничего копировать из папки в папку ))
    Ответ написан
    Комментировать
  • Как при помощи gulp собрать bower зависимости?

    пакет main-bower-files возьмет все main-файлы установленных пакетов, дальше делай с ними что хочешь
    Ответ написан
    2 комментария