подскажите реализую восстановления пароля в админке, и немного словил ступор, на фронтенде у нас есть восстановления пароля и сброс пароля, я так понимаю, что можно у наследоваться от контроллера восстановления пароля или нужно как то свой велосипед писать?
В Yii для этого есть Action-классы. А трейты – для ленивых, не умеющих в декомпозицию и пишущих логику в контроллере.
Да, вместо копирования логики скопировать экшен, дёргающий эту логику, декомпозированную в модель. В нормальном контроллере как в расходном материале для UI логики не будет. Тогда и никакие трейты не понадобятся.
Короче @mixnet, либо копипаста-говнокод, либо глубокий рефакторинг контроллера на фронтенде. Не ленись, повторное использование кода через трейты для трусов.
Немного оффтопик: считаю что удобно иметь один список пользователей, некоторые из которых админы и имеют доп возможности. Роли у них разные, а таблица Пользователи одна. При такой организации восстановление пароля реализуется в одном месте. Без копипасты. Если вы не со старым кодом работаете, а творите с нуля, я бы порекомендовал делать так.
Добавлю: "админка" - это не более чем роуты ограниченные или расширенные ролью / правами пользователя. Тогда вообще не придется ничего дублировать, просто смотри что пользователь может менять и какие данные ему можно возвращать. --- Добавлено --- ок. Я прозрел и теперь буду декомпозировать в модель.
Да-да. Придуманы для тех, кто не умеет в одиночное наследование в PHP. В Java и C# они никому не нужны.
А ты писал то на Java и C#? Java: Код (Text): package com.journaldev.inheritance; public class ClassC extends ClassA, ClassB{ public void с(){ } } а в C# вполне себе множественное наследование интерфейсов. Теоретики, они везде...
Ну вы, видимо, не писали. Compile Error. Наследование интерфейсов, Карл? Множественного наследования реализации в Java и C# из коробки нет. Интерфейсы не наследуют, а реализуют. В отличие от классов и трейтов настоящие интерфейсы по определению реализацию не содержат. Дефолтные методы в интерфейсах придуманы как костыль (компромисс) для поддержания обратной совместимости легаси-кода, а не для штатного повседневного использования. Пипец, каких опытных "практиков" завезли. Даже интерфейс от класса и трейта не отличают.
В yii2-app-advanced это уже реализовано. Логика восстановления там уже вынесена в формы-сервисы PasswordResetRequestForm и ResetPasswordForm. Так что полупустые экшены можно спокойно копировать и копипасты логики не будет.
Ну извините, что мы с @[vs] своими умениями оскорбляем чувства практиков на форуме. Нам надо быть этичнее. Впредь вместо "говнокодер" или "рукожоп" брать более толерантное "практик".
А @[vs] то тут при чем? У меня к нему вопросов нет, это довольно сильный программист, который знает о чем говорит и даже применяет на практике. Как и @artoodetoo и @acho А лить воду приправленную набором не всегда верно между собой связанных терминов - таки не умение ни разу.
При том, что с одной стороны довольно сильные практики с теорией @ElisDN и @[vs] говорят, что трейты - для лентяев и трусов, не умеющих в декомпозицию. А с другой стороны практики @artoodetoo и @acho без теории советуют трейты и несут чушь про наследование интерфейсов. И вы это спокойно лайкаете. Значит просто не осиливаете понять, что эти слова значат и что там всё верно связано. Слишкам сложна и звучит как непонятная абракадабра. Смиритесь.
Просто я прекрасно понимаю о чем сказал @[vs], полностью согласен с тем что написал @artoodetoo (и он дал наиболее правильный совет с точки зрения архитектуры, не абстрактной теоретической, а о том как нужно делать на практике что бы это работало, расширялось и поддерживалось), ну а @acho вообще писал не про это. Тут видишь какая штука, что бы понимать о чем все эти люди говорят, нужно всё это использовать на практике, знать минусы, плюсы и границы применения. И вот тогда приходит не только навык согласия с совершенное разными на первый взгляд позициями, но и скилл отличать опыт от набора слабосвязанных между собой слов )
В общем, всегда старайтесь декомпозировать систему, инкапсулируя бизнес-логику в доменную модель и уменьшая связанность. Сверху для коммуникации с UI накиньте прикладной сервисный слой юзкейсов. Тогда с единым выделенным источником правды сможете безболезненно копипастить тонкие контроллеры, не нарушая DRY. И, как побочный профит, получите возможность тестирования сущности модели юнит-тестами вместо интеграционных.
Первый написал, что трейты для трусов, а второй написал вынести в трейт. Так вы за умных или за красивых? Он и сам не понял, к чему это написал. На слова об отсутствии множественного наследования и трейтов в Java и C# он зачем-то влепил нерабочий код и приплёл интерфейсы, никакого отношения к наследованию и трейтам не имеющие. Штука именно в том, что я всё это и использую на практике. Знаю минусы, плюсы и границы. Из этого опыта всё и говорю. А вам и другим практикам почему-то кажется, что я это просто теоретик и всё это на ходу придумываю. Например, к вашему: говорю, что это вам и ему так кажется, что вариант с трейтом наиболее правильный, расширяемый и поддерживаемый. Просто для вас он самый простой в вашей практической архитектуре. А с точки зрения реальной программной архитектуры он, отнюдь, не расширяемый и туго поддерживаемый: Трейт с экшеном сильно связывает систему, никак отдельно не тестируется, никак не настраивается, не кастомизируется и не умеет подгружать зависимости без синглтонов. Как только во фронте или в админке в этот экшен нужно будет добавить отличающуюся строку (например, переименовать view или заменить confirmUrl в почте или redirectUrl после успеха), параметр или if, так мгновенно образуется геморрой. Сразу приходится делать циклические зависимости, добавляя в контроллер поле protected $resetRedirectUrl и шаблонные методы, которые этот трейт будет дёргать. IDE и анализаторы кода начинают ругаться на вызов и чтение отсутствующего в трейте поля $this->resetRedirectUrl и прочих методов. По сигнатуре трейта перестаёт быть понятно, как он работает. IDE подсвечивает методы и поля контроллера как неиспользуемые. Программисту по сигнатуре контроллера тоже непонятно, кто с этими полями работает. При использовании DIC приходится прокидывать в конструктор контроллера и все зависимости трейта. В итоге изначально простой трейт для экшена превращается в неконтролируемый хаос. Это всё неполная гора минусов. А плюс всего один - изначальная мнимая простота. Реальные архитектурные практики и принципы как раз и придумали, чтобы проект не превращался в непонятную кучу лапшекода. Так что для меня более оптимальный вариант - отделить бизнес-логику процесса от UI-кода контроллера и инкапсулировать в PasswordResetForm или PasswordResetService и вызывать этот сервис из обоих экшенов.
То что мне кажется, я описал выше, а именно, что в архитектуре API приложения не должно быть деления на "админку" и "пользовательскую". Должно быть деление прав доступа к данным на основе ролей и разрешений, тогда и не придется дублировать функционал (@artoodetoo тоже про это говорил) Как это будет делаться трейтами или декомпозицией в модели - мне вообще похер, потому что первое - один из инструментов, а второе - вообще не имеет отношение к реальности и в любом случае это всего лишь код, который как известно вторичен для любого кто умеет его писать. Такие дела. о боже. Вы вот это всё серьезно?