• Архитектура приложения. Как сделать независимые модули (сервисы)?

    @maksim92
    По этому вопросу очень долго искал ответа))
    Вам уже скинули статью по независимым модулям, но этого мало. Что вам нужно:

    1. Независимый слой MODEL.
    В этой папке находятся Use Case (Service), Сама сущность Entity (AR), Желательно иметь репозитории для изоляции от базы данных ну и другой доменный слой логики, который не зависит ни от чего. Ни от фреймворка, ни от других модулей и пакетов. Ваша задача написать код в этой части так, чтобы его можно было скопировать в любую папку, настроить зависимости и чтобы этот код заработал хоть на чистом PHP. Если не планируете менять фреймворк, то можно зависить от фреймворка.

    2. Зависимости
    Все зависимости модуля реализовать либо через Interface либо через события, но события лучше. А дальше уже синхронизируйте через приложение или отдельный модуль. Можно и по api.

    3. UI (пользовательский интерфейс)
    Он может быть зависимым от других модулей. В него входят: контроллеры, view, формы, vue.js и так далее. В общем то, с чем взаимодействует пользователь.

    Тем самым получается такая система если опираться на MVC:
    VC - могут быть зависимы от других модулей
    M - не может быть зависима ни от чего, кроме PHP. Желательно и отделять слой базы данных с помощью Repository. Тогда ваш пакет будет очень сильно независим даже от базы. И вам вообще будет без разницы куда вы это храните в user или employee.

    Если будет такой слой, то можно спокойно переносить хоть на будущий Yii3. Однако На Yii1 и Yii2 такое сделать сложно. Надо изворачиваться и займет это больше времени. Так как сам Фреймворк вставляет нам палки и приходится делать костыли из-за его монолитности. К такому подходу не привыкли Yii1 и Yii2 разработчики. Обычно на Yii такое понимание «фигак, фигак и в продакшн».

    Такую архитектуру удобно будет строить на симфони ну и будущем Yii3.

    Вот материал которые мне помогли:
    https://coursehunters.net/course/yii2-internet-market
    https://habr.com/ru/post/276593/
    https://www.yiiframework.ru/forum/viewtopic.php?f=...

    https://habr.com/ru/post/329286/
    Ответ написан
  • Как использовать Di container?

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

    Если вкратце то:
    Вопрос1 - нужно ли всё равно передавать параметр в конструктор вызываемого контроллера или можно просто вызывать без параметров?

    У нас есть контейнер, в нем при запуске приложения мы регистрируем классы (сервисы). При регистрации мы связываем абстракцию (интерфейс) и реализацию (конкретный класс), а также впринципе говорим нашему приложению КАК создать конкретный объект. Потом же мы делаем просто так и получаем готовый объект
    // Получаем объект интерфейса из любой точки приложения
    $container->get(MyInterface::class);


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

    $container->register(MyInterface::class, function () {
      return new MyConcreteClass('какие то параметры');
    });


    Вопрос2 - где вообще надо делать $container->get('что-нибудь'); ? В самом контроллере как-то неправильно, наверное - ибо тогда всё равно зависимость. Где это делать?

    Во-первых, контроллер это обычный класс, во-вторых принцип DI заключается в том, чтобы у вас классы не зависили от конкретных реализаций и явно ЗАВИСИЛИ от АБСТРАКЦИЙ. Это самое важно что нужно понять. Отвечая на вопрос - брать напрямую из контейнера сервисы надо ЗА сервисами, то есть в сервис провайдере и выше

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

    Вот короче пример написал который впринципе все объясняет, если непонятно спрашивай

    interface CartRepository
    {
        public function add(CartItem $item);
        public function getAll();
    }
    
    class SessionCartRepository implements CartRepository
    {
        ...
    }
    
    class DbCartRepository implements CartRepository
    {
        ...
    }
    
    class Cart
    {
        public function __construct(CartRepository $repository) 
        {
            ...
        }
    
        public function getTotal()
        {
            ...
        }
    }
    
    // Service provider
    $container->register(CartRepository::class, function ($container) {
        if ($user = $container->get('auth')->getUser()) {
            $repository = new DbCartRepository($container->get('db'), $user->id)
        } else {
            $repository = new SessionCartRepository();
        }
    
        return $repository;
    });
    
    $container->register(Cart::class, function ($container) {
        return new Cart($container->get(CartRepository::class));
    });
    Ответ написан
  • Как начать зарабатывать начинающему web-разработчику в 17 лет?

    Wolfnsex
    @Wolfnsex
    Если не хочешь быть первым - не вставай в очередь!
    Хочу устроиться джуном в веб-студию удаленно
    Не уверен, что удалённо Вы чему-то научитесь особо. Удалённо обычно работают либо матёрые профи, либо те кто не понимает, чем им всё это грозит...

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

    но обрубать мосты так сразу не хочу
    ЕГЭ можно пересдать...

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

    портфолио есть
    Качественное? Покажите?

    Не знаю что делать
    Выбрать что-то одно, либо учёбу, либо работу.

    вряд ли в студию возьмут на 3 месяца
    В офис скорее всего взяли бы, особенно если не говорить им, что на 3 мес. (хотя это было бы не очень честно с Вашей стороны). Но з/п там была бы скорее всего такая... что называется "на мороженое".

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

    Как начать зарабатывать на фрилансе?
    Примерно так:
    1. Зарегистрироваться на фрилансе
    2. Сделать несколько заказов (лучше мелких) за "спасибо" (или около того)
    3. Собрать несколько положительных отзывов от заказчиков
    4. Начинать потихоньку зарабатывать...
    *когда я продвигал веб-студию (собственную) - мелкие заказы мы не редко делали в прямом смысле "за спасибо", лишь бы на рынок выйти...

    Какие предложения и советы или варианты у вас есть?
    Искать работу в ближайшем офисе, если Вам предложат з/п которой хватит, что бы снять комнату + купить поесть + на проезд на работу и обратно (если поблизости студий нет) - считайте, что уже неплохо. Либо заниматься учёбой и попутно саморазвитием.

    P.S.
    Привет! Мне 17
    Привет! Вам точно 17? Не считая пробелов перед знаками препинания, грамотная речь, для человека в возрасте 17 лет...
    Ответ написан
  • Как сохранить id в модель?

    slo_nik
    @slo_nik Куратор тега Yii
    Доброе утро.
    Естественно у Вас не будет сохранять потому, что Вы не загружаете модель из POST, её там просто нет. Для этого Вам и потребовался скрытый input, что бы можно было загрузить необходимую модель через $model->load(). Поэтому со скрытым input всё работает.
    Если Вы уберёте из кода загрузку модели, в которой только один id, то всё сработает.
    Например, модель с единственным атрибутом id у Вас Direction. Значит в действии надо сделать так
    $model = new Direction();
    $modelLang = new DirectionLang();
    
    if ($modelLang->load(Yii::$app->request->post()) && $model->save()) {
         $modelLang->lang_id = 2;
         $modelLang->direction_id = $model->id;
         $modelLang->save();
          var_dump($model->getErrors());
          var_dump($modelLang->getErrors());
    
         return $this->redirect(['view', 'id' => $model->id]);
    }

    В этом случае всё сработает и можно удалить скрытый input из формы.
    Ответ написан
  • Как спроектировать проверку?

    @ddd329
    Привет! Ну если вопрос касается проектирования, то тут сразу бросается в глаза понятие Service. В предметной области его желательно не использовать, т.к. данный термин очень перегруженный и имеет много понятий в программировании. Я видел в одном проекте его заменили на Product, но ладно не суть...
    Паттерн "Спецификация" я думаю тут не особо уместен. Можно сделать так, что каждый Сотрудник содержит в себе поле со списком Документов, и для того чтобы выяснить может ли сотрудник оказывать услугу, то можно примерно так:
    if (employee.СanProvideService(service)) ...
    Ответ написан
  • YII2:Как получать настройки модуля в контроллере?

    slo_nik
    @slo_nik Куратор тега Yii
    Добрый день.
    Если Вы указываете свойство в модели, то обращаться надо так:
    public $filename;
    
    $model = new Image();
    $model->filename;

    Если Вы желаете указать это параметром модуля, то указывайте в классе модуля. Или в конфигурационном файле как параметр
    'main' => [
                'class' => 'app\modules\main\MainModule',
                'layout' => 'main.php',
                'layoutPath' => '@app/modules/main/views/layouts',
                'params' => [
                    'test' => 'test1',
                    'test2' => 'test22'
                ]
            ],

    Тогда обратиться можно так:
    // Если указали в классе модуля public $filename
    $main = Yii::$app->getModule('main');
    echo $main->filename;

    Или так:
    // Если указали параметром в конфигурационном файле.
    $main = Yii::$app->getModule('main');
    echo $main->params['test'];
    Ответ написан
  • В какой сфере можно заработать на фрилансе?

    sim3x
    @sim3x
    знаю HTML, CSS, JQUERY
    сомневаюсь

    без особых трудностей развиваться как фрилансер
    ни в какой. Везде будут трудности
    Ответ написан
  • Как улучшить архитектуру и убрать дублирование?

    BoShurik
    @BoShurik Куратор тега Symfony
    Symfony developer
    Я бы сделал так. Тем более, если там добавятся еще методы, то вы утоните в if-ах при вашем подходе

    <?php
    
    namespace App\Controller;
    
    use App\Entity\User;
    use App\Service\UserService;
    use Symfony\Component\DependencyInjection\ServiceLocator;
    use Symfony\Component\HttpFoundation\Response;
    use Symfony\Component\Security\Core\Exception\AccessDeniedException;
    use Symfony\Component\Security\Core\Security;
    use Twig\Environment;
    
    interface AdminControllerInterface
    {
        public function index(): Response;
    
        public function read(string $id): Response;
    }
    
    class UserController implements AdminControllerInterface
    {
        /**
         * Security - объект-helper, он содержит в себе AuthorizationCheckerInterface
         *
         * @var Security
         */
        private $security;
    
        /**
         * @var ServiceLocator
         */
        private $controllerLocators;
    
        public function __construct(Security $security, ServiceLocator $controllerLocators)
        {
            $this->security = $security;
            $this->controllerLocators = $controllerLocators;
        }
    
        public function index(): Response
        {
            $role = $this->getRole();
    
            if (!$this->controllerLocators->has($role)) {
                throw new AccessDeniedException();
            }
    
            /** @var AdminControllerInterface $controller */
            $controller = $this->controllerLocators->get($role);
    
            return $controller->index();
        }
    
        public function read(string $id): Response
        {
            $role = $this->getRole();
    
            if (!$this->controllerLocators->has($role)) {
                throw new AccessDeniedException();
            }
    
            /** @var AdminControllerInterface $controller */
            $controller = $this->controllerLocators->get($role);
    
            return $controller->read($id);
        }
    
        private function getRole(): string
        {
            // Для простоты представим, что роль у пользователя одна. Иначе искать среди ролей
            // ROLE_SUPER_ADMIN и ROLE_CUSTOMER_ADMIN и возвращаем с соответствующим приоритетом
            return current($this->security->getToken()->getRoles());
        }
    }
    
    class SuperAdminController implements AdminControllerInterface
    {
        private $userService;
    
        /**
         * @var Environment
         */
        private $twig;
    
        public function __construct(
            UserService $userService,
            Environment $twig
        ) {
            $this->userService = $userService;
            $this->twig = $twig;
        }
    
        public function index(): Response
        {
            $users = $this->userService->getAll();
    
            return new Response($this->twig->render('admin/users.html.twig', [
                'users' => $users
            ]));
        }
    
        public function read(string $id): Response
        {
            $user = $this->userService->getById($id);
    
            return new Response($this->twig->render('admin/user.html.twig', [
                'user' => $user
            ]));
        }
    }
    
    class CustomerAdminController implements AdminControllerInterface
    {
        private $userService;
    
        /**
         * @var Security
         */
        private $security;
    
        /**
         * @var Environment
         */
        private $twig;
    
        public function __construct(
            UserService $userService,
            Environment $twig
        ) {
            $this->userService = $userService;
            $this->twig = $twig;
        }
    
        public function index(): Response
        {
            /** @var User $user */
            $user = $this->security->getUser();
    
            $users = $this->userService->findByRoleAndWorkspaceId(
                User::ROLE_TEAM_MEMBER,
                $user->getWorkspace()->getId()
            );
    
            return new Response($this->twig->render('user/users.html.twig', [
                'users' => $users
            ]));
        }
    
        public function read(string $id): Response
        {
            $user = $this->userService->getByIdAndWorkspaceId($id);
    
            return new Response($this->twig->render('user/user.html.twig', [
                'user' => $user
            ]));
        }
    }


    app.admin_controller_locator:
        class: Symfony\Component\DependencyInjection\ServiceLocator
        arguments:
            -
                ROLE_SUPER_ADMIN: '@App\Controller\SuperAdminController'
                ROLE_CUSTOMER_ADMIN: '@App\Controller\CustomerAdminController'
        tags: ['container.service_locator']
    Ответ написан
  • Как сделать вывод страниц из бд по ЧПУ php?

    php666
    @php666
    PHP-макака
    ЧПУ на PHP.

    тяжко мне дается php
    Ст. 12-13 От дней же Иоанна Крестителя доныне Царство Небесное силою берется, и употребляющие усилие восхищают его...
    Ответ написан
  • А как верстают такой дизайн? Svg?

    Mirkom63
    @Mirkom63
    Я программист
    Не обязательно svg, можно и png просто картинкой на фон положить. Но я бы сделал svg, дабы качество было хорошее и без всяких png-шных размытий. Да и такая большая картинка в svg будет меньше размером чем png.

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

    StivinKing
    @StivinKing
    На основе вашего примера - ссылка. Пример с ControlValueAccessor и добавил пример с FromGroup (файл input-control.component.ts)
    Ответ написан
  • Как реализовать ControlValueAccessor?

    @antoart
    Web developer
    Привет.
    Буду опираться на твой же код.

    Реализация данного интерфейса позволяет ангуляровской форме взаимодействовать с кастомным компонентом. В метод
    writeValue(value: any) {
       this.formControlName = value;
      }

    прокидывается то значение, которое ты передаешь в formControlName. Заметь, это не Binding, как между компонентами. Чтобы значение передалось надо сказать форме прямо и конкретно
    form.setValue({email: "email", password: 'passworddd'})
    // или 
    form.patchValue({email: "email"})


    А чтобы динамически считать значение, которое ты прокинешь через функцию this.propagateChange(val) , надо уже работать с изменением формы
    this.filterForm.valueChanges
          .pipe(
            takeUntil(this._onDestroy$)
          )
          .subscribe((val) => {
           console.log(val);
          });


    И ты пойми что же ты хочешь. Прокидывать параметры в компонент (binding) или прокидывать значение формы в компонент (ControlValueAccessor).

    p.s. напиши в своем коде, и посмотри как в консоль валятся значения формы из уже дочернего компонента.
    initForm() {
        this.SignupReactiveForm = this.fb.group({
          password: ['password', [
            Validators.required,
            Validators.pattern(/[A-z]/)
          ]
          ],
          email: ['email', [
            Validators.required, Validators.email
          ]
          ],
          
    
        });
      }
    
    }
    Ответ написан
  • Что значит моделирование обьектов реального мира в ООП?

    @luna3956
    Представьте, что Вам нужно написать программу, в которой ведется учет частных домов на какой-нибудь улице. Ключевой единицей будет дом - объект из реального мира. Чтобы описать его с помощью программного кода для этого отлично подходит ООП. В нем есть такое понятие как класс, он является по сути моделью/структурой объекта из реального мира. В нашем примере с домом это будет примерно такой класс:
    class House {
    
      string address;
      int numOfRooms;
      ...
    
      House(string address, int numOfRooms)
      {
        this.address = address;
        this.numOfRooms = numOfRooms;
      }
    
    }


    Теперь же в самой программе чтобы оперировать таким объектом из реального мира как дом вам достаточно написать примерно следующее:

    House h = new House("Улица Вязов дом 13", 5);

    То есть в переменной h у нас теперь хранится объект/ссылка на объект, являющийся представлением объекта из реального мира - пятикомнатного дома, который находится по адресу "Улица Вязов дом 13".

    Или например собаку(тоже объект из реального мира) можно описать таким классом:

    class Dog {
    
      string name;
      string breed;
    
      Dog(string name, string breed)
      {
        this.name = name;
        this.breed = breed;
      }
    
    }


    И теперь чтобы в программе "создать собаку" с каким-то именем и породой достаточно написать:

    Dog d = new Dog("Бобик", "Бульдог")

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

    P.S сам код это не ява а просто псевдокод для наглядности
    Ответ написан
  • Может ли такой банер уложиться в 65 кб?

    Exploding
    @Exploding
    wtf?
    Так там от "банера" 2 картинки в jpg всего-то.
    Попробовал ужать в PS, вышло 19Кб, остальное в css/html.
    65Кб - жируют однако:)
    Ответ написан
  • Какова логика доступа к личному кабинету?

    @Abcdefgk
    Да надо просто градацию "ролей" придумать и у юзеров в схеме сделать поле role
    Проверять значение этого поля у юзера при входе на страницу - и в зависимости от него показывать столько или столько... или вообще всё.
    Ответ написан
  • Какова логика доступа к личному кабинету?

    Taraflex
    @Taraflex
    Ищу работу. Контакты в профиле.
    Если пользователей accessArray не десятки тысяч. То проще всего взять для базы PostgreSQL которая поддерживает массивы в качестве типов данных. https://www.postgresql.org/docs/9.1/static/arrays.html
    И проверять доступность прямо в sql запросе
    Ответ написан
  • Как передать значение в шаблон?

    navix
    @navix
    Angular & TypeScript
    В конструкторе еще нет значения Input-параметров. Поэтому тут лучший вариант использовать хук ngOnChanges.

    ...
    ngOnChanges() {
      this.svg = this.sanitizer.bypassSecurityTrustHtml(this.svgshow);
    }
    Ответ написан
  • Как подсчитать количество объектов в массиве?

    navix
    @navix
    Angular & TypeScript
    ngOnInit() {
      this.quizService.getData().subscribe((data: Response) => {
        this.quiz = data.json();
        this.countPages = this.quiz.textCategory.length;
      });
    Ответ написан