Русское сообщество разработки на PHP-фреймворке Laravel.
Ты не вошёл. Вход тут.
Страницы 1
Добрый день. Нет возможности получить авторизованного пользователя на момент запуска сервис провайдера?
Хочу возвращать список меню в зависимости от ролей пользователя и пробросить во все шаблоны.
В провайдере пишу:
View::share( 'mainMenu', $this->app->make( MenuContract::class )->all([ 'title', 'link', 'icon' ]) );
В MenuContract::all user() равен null.
Изменено Miciew (02.03.2017 18:01:01)
Не в сети
нет, такой возможности нет. сервис-провайдеры – неподходящее место для задания переменных в видах, используй view composer
Не в сети
в каком месте его лучше регистрировать тогда?
Не в сети
я добавляю файл /app/Providers/ComposerServiceProvider.php вида
<?php namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class ComposerServiceProvider extends ServiceProvider {
/**
* Register bindings in the container.
*
* @return void
*/
public function boot()
{
view()->composer('admin', 'App\Http\ViewComposers\AdminComposer');
view()->composer('layout', 'App\Http\ViewComposers\LayoutComposer');
view()->composer('front.catalog.cart', 'App\Http\ViewComposers\CatalogCartComposer');
}
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
}
}
и регистрирую его в config/app.php в ключ 'providers'
соответственно у меня есть папка /app/Http/ViewComposers и в ней на каждый вид свой вью композер, например в /app/Http/ViewComposers/CatalogCartComposer.php у меня
<?php namespace App\Http\ViewComposers;
use Illuminate\Contracts\View\View;
class CatalogCartComposer {
/**
* Bind data to the view.
*
* @param View $view
*
* @return void
*/
public function compose($view)
{
$count = cart()->count();
$total = cart()->total();
$items = cart()->items();
$view->with(compact('count', 'total', 'items'));
}
}
где cart() – это хелпер, возвращающий app(\App\Services\Cart::class) – в app/Services у меня находятся классы-сервисы уровня приложения, регистрирую я их синглтонами в AppServiceProvider. примерно вот такая организация кода
Не в сети
Спасибо, разобрался.
Не в сети
Как же ужасно задокументированы View composers... Всё по коду хорошо, но описание применения - совсем невнятное.
В django framework было очень похожее на это: называлось template tags - это такие отдельные части приложения, которые могут появляться на любой странице. Например, список категорий сайта, список последних добавленных новостей и так далее. Суть в том, что их нужно выводить не через view, а они могут использоваться в любом шаблоне. Конечно, там это совсем по-другому реализовано (имхо, гораздо красивее и без надобности определять "области видимости"), но уж что имеем.
Не в сети
Встретил интересную особенность (косяк?) - если я сделал View Composer и включил его, а внутри него выполняется запрос к БД, то в Debug Bar этот запрос выполнится ровно столько раз, сколько Views было загружено и выполнено. Да, я предусматриваю в дальнейшем кеширование, но сам факт того, что композер будет выполняться к каждой отдельной view (шаблону) - меня смущает.
Я что-то делают не так?
PS: View Composer использую как генератор блока "Категории" на всех страницах сайта.
Не в сети
что-то точно не так, твой композер срабатывает на все виды, а не на какой-то конкретный. ты точно регаешь композеры в своём сервис-провайдере в boot() с помощью view()->composer('myview.name', SomeComposer::class) ?
Не в сети
что-то точно не так, твой композер срабатывает на все виды, а не на какой-то конкретный. ты точно регаешь композеры в своём сервис-провайдере в boot() с помощью view()->composer('myview.name', SomeComposer::class) ?
Всё с точностью до наоборот
Я регистрирую его с помощью:
view()->composer('*', 'App\Http\ViewComposers\CategoriesComposer');
Большое спасибо за наводку, в первом аргументе прописал view, в которой будут использоваться данные из выполнения этого view composer и всё встало на свои места.
Я по своей неопытности подумал, что туда нужно передать view, в которых будет использоваться тот @include('view') как результат выполнения композера. Как уже писал выше - в привычной мне django совсем другая логика написания таких вещей, поэтому у меня в голове возник небольшой вакуум, который и привел к такому глупому и опрометчивому поступку.
PS: всё чаще задумываюсь по окончанию проекта написать статью "laravel vs. django", где показать как что-то делается в одном фреймворке и как в другом. Не знаю, правда, соберусь ли в итоге, т.к. времени не так много на такие вещи, но, думаю, и для меня было бы полезно изложить некоторые мысли, которые могли бы продвинуть на следующий уровень (знающие сказали бы как "правильно"), и все бы посмотрели что лучше реализовано в django и взяли на заметку (не знаю есть ли среди ваших-наших рядов ларавел контрибьюторы, но вдруг...).
Не в сети
не знаю про django, а вот с ruby on rails у ларавеля как раз таки очень много общего
Не в сети
не знаю про django, а вот с ruby on rails у ларавеля как раз таки очень много общего
И с джангой очень много общего на самом деле, но некоторые вещи кажутся "недописанными", как, например, миграции в БД - в джанго поля задаются в модели, а потом генерируется миграция запуском команды. Поэтому априори получается в итоге проще, не нужно искать миграцию, чтоб вспомнить что за поля в БД есть в текущий момент - всё в модели прописано.
С рельсами, к сожалению, не знаком )
Не в сети
Интересно, а почему с джанго на лару перешли, раз вы джанго так хорошо знаете?
Не в сети
Интересно, а почему с джанго на лару перешли, раз вы джанго так хорошо знаете?
С джангой опыт работы более 5 лет, наскучило уже)
Ну, а вообще - задача сейчас такая была - сделать на php, т.к. если бы я написал на python, то потом мало кто смог бы что-то поправить или изменить там из-за специфичности. Плюс в django очень мудреная и хитрая связка nginx+uwsgi, которую даже я не понимаю до конца. Также, для джанги нужна кучка зависимостей, поэтому её в принципе не реально на шаред хостинг поставить (даже пробовать не стоит). Ну и наконец, деплой - это очень мощная, но в тоже время тяжелая штука в арсенале джанги. Чтобы развернуть проект на сервере - нужно установить себе проект (это во всех деплоях, что я видел так было - может и есть другие, но давно уже не изучал эту тему), а это значит, что нужно поставить: virutalenv + pip + зависимости проекта.
В целом то джанга мне очень нравится, коммьюнити там очень хорошее и пакетов готовых под неё очень много. Но вот как раз одна из основных причин использования ларавел - это то, что потом нужно, чтобы конечный пользователь проекта смог что-то сменить внутри, а это совсем не питонист будет)
Не в сети
TrueKanonir пишет:Интересно, а почему с джанго на лару перешли, раз вы джанго так хорошо знаете?
С джангой опыт работы более 5 лет, наскучило уже)
Ну, а вообще - задача сейчас такая была - сделать на php, т.к. если бы я написал на python, то потом мало кто смог бы что-то поправить или изменить там из-за специфичности. Плюс в django очень мудреная и хитрая связка nginx+uwsgi, которую даже я не понимаю до конца. Также, для джанги нужна кучка зависимостей, поэтому её в принципе не реально на шаред хостинг поставить (даже пробовать не стоит). Ну и наконец, деплой - это очень мощная, но в тоже время тяжелая штука в арсенале джанги. Чтобы развернуть проект на сервере - нужно установить себе проект (это во всех деплоях, что я видел так было - может и есть другие, но давно уже не изучал эту тему), а это значит, что нужно поставить: virutalenv + pip + зависимости проекта.В целом то джанга мне очень нравится, коммьюнити там очень хорошее и пакетов готовых под неё очень много. Но вот как раз одна из основных причин использования ларавел - это то, что потом нужно, чтобы конечный пользователь проекта смог что-то сменить внутри, а это совсем не питонист будет)
Ого, круто) Теперь понятно. Спасибо за развернутый ответ)
Не в сети
Ого, круто) Теперь понятно. Спасибо за развернутый ответ)
Пожалуйста)
Вообще, советую попробовать выполнить официальный туториал от неё: https://docs.djangoproject.com/en/1.11/#first-steps - даже в нем можно подчерпнуть много полезного.
PS: несомненный плюс джанги в том, что там есть автогенерируемая админка, которая покрывает 99% процентов задач при работе с ней без всякого волшебства.
Изменено Lord_Alfred (17.04.2017 13:46:31)
Не в сети
И с джангой очень много общего на самом деле, но некоторые вещи кажутся "недописанными", как, например, миграции в БД - в джанго поля задаются в модели, а потом генерируется миграция запуском команды. Поэтому априори получается в итоге проще, не нужно искать миграцию, чтоб вспомнить что за поля в БД есть в текущий момент - всё в модели прописано.
С рельсами, к сожалению, не знаком )
как раз механизм миграций в ларавеле почти полностью скопирован с рельсы. причина того что сделано именно так как раз в том чтобы в модели поля описывать было не нужно от слова вообще. базовая рабочая модель в ларе выглядит так:
class Post extends Model {}
и это всё. эта модель ходит в таблицу posts за записями с первичным ключом id и таймстэмпами created_at и updated_at и любыми другими. работает полностью прозрачно для всего кода. плюс – позволяет выбирать поля из базы частично – то есть не только select * from ..., а например select id, title from ... – в этом случае только выбранные поля будут доступны на объектах модели
фактически модели в ларавеле вообще не нужно знать что к ней придёт. она знает откуда её выбрали и любой набор полей превращает в рабочий active record
по-моему как раз те виды active record-ов и data mapper-ов где приходится описывать структуру базы данных в моделях мне кажутся очень неудобными. особенно когда значимые настройки задаются через пхп-комментарии – вот это особенно люто бесит
в моделях ларавеля все донастройки – это опция, их есть смысл трогать только когда структура базы отличается от той, которая получается по дефолту по соглашениям элоквента. я чаще всего задаю $casts для дополнительной безопасности работы с типами, и заодно почти везде в коде использую === а не == – хорошая практика при работе с пхп. всё остальное – когда как
Не в сети
как раз механизм миграций в ларавеле почти полностью скопирован с рельсы. причина того что сделано именно так как раз в том чтобы в модели поля описывать было не нужно от слова вообще. базовая рабочая модель в ларе выглядит так:
class Post extends Model {}
А зачем нужна необходимость не описывать поля модели? В любом случае ведь при работе с моделью Post - мы должны знать какие поля есть в этой модели, чтобы не было вот такого:
$p = new Post();
$p->atata_not_found_field = 1;
Я соглашусь, что если мы пилим приложение поверх существующей структуры БД, то там и миграции не нужны по факту. Но в идеале то - приложение делается с нуля, значит и структура БД прорабатывается вместе с ним.
Ещё так же меня из-за этого крайне бесит задавать массив $fillable. Это какой-то непомерной длинны костыль) Я и так уже в миграции написал все поля, которые будут в этой модели, зачем мне разрешать записывать данные в них? Одно дело - исключать возможность записи - это несомненно полезная возможность. Но вот, имхо, по дефолту - нужно чтобы все поля были "fillable".
плюс – позволяет выбирать поля из базы частично – то есть не только select * from ..., а например select id, title from ... – в этом случае только выбранные поля будут доступны на объектах модели
Выбрать только определенные поля из БД - это везде не проблема, имхо)
по-моему как раз те виды active record-ов и data mapper-ов где приходится описывать структуру базы данных в моделях мне кажутся очень неудобными. особенно когда значимые настройки задаются через пхп-комментарии – вот это особенно люто бесит
С настройками в виде пхп-комментариев - не встречался, жесть :-D
Но вот пример из туториала джанги как там описывается модель и создается миграция:
from django.db import models
class Reporter(models.Model):
full_name = models.CharField(max_length=70)
def __str__(self): # __unicode__ on Python 2
return self.full_name
class Article(models.Model):
pub_date = models.DateField()
headline = models.CharField(max_length=200)
content = models.TextField()
reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)
def __str__(self): # __unicode__ on Python 2
return self.headline
А затем из этих моделей генерируем миграцию:
$ python manage.py makemigrations
И применяем эту миграцию к БД:
$ python manage.py migrate
Всё! Огромный плюс описания полей в модели - это работа с IDE. IDE среда будет знать о полях и будет работать автокомплит, что очень полезно, когда у тебя в модели 50+ полей (реальный рабочий пример, причем там и вправду все поля нужные были и большинство вещей и так были вынесены в отдельные модели, просто структура была крайне сложная и нужно было хранить в модели большое число данных).
в моделях ларавеля все донастройки – это опция, их есть смысл трогать только когда структура базы отличается от той, которая получается по дефолту по соглашениям элоквента.
Вот, кстати, хорошо, что упомянули элоквент Я так и не понял зачем нужен DB Query Builder, когда есть Eloquent ORM. Я понимаю, что элоквент как раз таки использует квери билдер, но зачем они разделили эти сущности для работы с БД? Логичнее было бы сделать Query Builder в Eloquent, чтобы не было желания делать raw sql запросы (это меня всегда и везде бесило, 99% задач, что я делал - всегда решались средствами ORM, а если не выходило - нужна была денормализация, которая в итоге приносила только плюсы, т.к. неправильно продуманная структура БД - это априори работа с raw sql в итоге).
Не в сети
Забыл добавить важную особенность: в джанге не нужно писать валидаторы, если делать форму из модели. Т.к. модель знает что за тип данных, обязательное поле или нет, его размерность и т.д. В ларавел же нужно делать $validators и явно прописывать все правила, т.к. модель не знает о своем содержимом.
Не в сети
А зачем нужна необходимость не описывать поля модели? В любом случае ведь при работе с моделью Post - мы должны знать какие поля есть в этой модели, чтобы не было вот такого:
для лучшей масштабируемости вниз. реально на ларавеле вполне возможно за выходные сбацать на коленке прототип идеи и запустить в продакшен. да, он будет не очень красиво написан, но суть в том что ларавель позволяет быстро описать только бизнес-логику не спотыкаясь об фреймворк, набить фронтенд на бутстрапе и сразу показать что-то заказчику. когда проект растёт конечно удобнее когда есть автокомплит и прочие удобства – для этого есть пакет laravel/ide-helper, он генерит докблоки к моделям с учётом casts в том числе – работать становится намного удобнее. но по дефолту главное – «низкий старт»
Я соглашусь, что если мы пилим приложение поверх существующей структуры БД, то там и миграции не нужны по факту.
это кстати не такая уж и редкость. и более того со временем количество легаси в мире увеличивается, а значит вероятность попасть на проект где «уже всё есть» с каждым годом всё больше
Ещё так же меня из-за этого крайне бесит задавать массив $fillable. Это какой-то непомерной длинны костыль) Я и так уже в миграции написал все поля, которые будут в этой модели, зачем мне разрешать записывать данные в них?
вообще – не задавай вот пока не надо зачем-то будет – не задавай. присвоение свойств моделям ($post->title = 'xxx';) работает без $fillable. $fillable нужен только при групповом задании полей с Model::create или $model->fill и тут надо понимать что $fillable не только посылает тебя лесом когда он не задан, но ещё и фильтрует поля по списку когда задан
например на Post если title и text – fillable, то новую запись можно заносить прямо из $request->all() – нужные поля на нём провалидируются валидатором до обработки а если хитропопый пользователь засунет в форму например created_at чтобы оформить пост задним числом, $fillable отбросит это поле. таким образом процесс сохранения какой-то формы в базу получается буквально в несколько строк: раз – авторизация (всё через политики), два – вызов $this->validate, три – Post::create
плюс когда нужно именно массово задать поля которых нет в $fillable и мы заранее исключили из входных данных всё лишнее – есть Model::unguard(). и наконец есть хак (ни разу им не пользовался) – если в разных местах кода у нас разные наборы заполняемых полей – вообще-то $fillable – публичное свойство, перед $model->fill его вполне можно подменить
как видишь – множество вариантов на все случаи жизни и «secure by default» и если охота чего-то – не проблема
Выбрать только определенные поля из БД - это везде не проблема, имхо)
ты не всё значит видел в этой жизни )))
А затем из этих моделей генерируем миграцию:
вопрос в том будет ли правильно генерироваться миграция на изменение имеющейся структуры и правильно ли она будет обрабатывать сложные ситуации. вот например – мы применяем миграцию к production-базе, у которой уже есть записи в posts и мы туда добавляем поле announce которое должно быть без default значения но при этом не быть nullable. напрямую этого сделать нельзя – любая база тебе выдаст ошибку. но когда мы прописываем миграции руками, нам не проблема сделать сначала миграцию с default чтобы забить значения имеющимся записям а вторым действием этот default убрать
это немножко искусственный пример, но на самом деле я как раз сейчас работаю с легаси цмс-кой которая пытается автоматом накатывать изменения в структуру базы – там такого гемора хватает на каждом шагу. я догадываюсь что django поумнее чем чей-то древний кривой велосипед, но есть пределы возможностей всё равно
и ещё бонус в том, что миграция – это строго говоря необязательно изменение структуры базы. это же просто пхп-код, в нём можно делать что угодно – например, если часть данных хранишь в редисе, можно в миграции занести туда какой-то базовый набор, можно в миграциях данные конвертировать из старого формата в новый, можно с laravel envoy вообще цепляться к удалённому серваку и там настройки софта менять – возможности неограничены в общем-то
Огромный плюс описания полей в модели - это работа с IDE. IDE среда будет знать о полях и будет работать автокомплит, что очень полезно, когда у тебя в модели 50+ полей
многовато, подозреваю что в ларавеле можно было часть из них объединить в один json-блоб и одно поле. что касается автокомплита в IDE – смотри пакет laravel/ide-helper. я правда им последнее время не пользуюсь – предпочитаю использовать DI+интерфейсы вместо фасадов, а докблоки на моделях руками писать – так точнее выходит, но для начала вполне можно опробовать чтобы понять как оно работает
Я так и не понял зачем нужен DB Query Builder, когда есть Eloquent ORM. Я понимаю, что элоквент как раз таки использует квери билдер, но зачем они разделили эти сущности для работы с БД?
на самом деле это разные вещи для разных задач. при этом они связаны довольно тесно – например любая выборка с модели до того как ты вызвал на ней ->first() или ->get() – это тоже билдер. Post::newQuery() вернёт тебе билдер с заданной на нём $table. отношения на моделях тоже возвращают билдеры: $post->comments – это коллекция всех комментариев, а $post->comments() – билдер для выборки комментариев конкретного поста (настроены $table и $where). поэтому на отношениях например можно сразу настраивать дефолтные параметры выборки типа $this->hasMany(Comment::class)->latest() и так далее
но модели не описывают все возможности взаимодействия с базой – во многих проектах находятся вещи, которые невозможно выразить через элоквент – например выборки на моделях не позволяют использовать join или group, поскольку нарушают правило «один результат из базы – один экземпляр модели». и тут ларавель даёт возможность спуститься на ступеньку пониже – выбрать результаты конкретного запроса, а билдер тут помогает написать его абстрагируясь от конкретной СУБД – такой проект скорее всего будет не проблема однажды перевести с mysql на postgres. если и построитель не помогает – ещё на ступеньку ниже есть \DB::connection() на котором можно делать сырые SQL-запросы, правда и тут поддерживается биндинг параметров для защиты от SQL-инъекций. обычно вниз спускаться не приходится, но если нужно – бери пользуйся
Логичнее было бы сделать Query Builder в Eloquent
как видишь, любой запрос в элоквент уже является query builder-ом
Забыл добавить важную особенность: в джанге не нужно писать валидаторы, если делать форму из модели. Т.к. модель знает что за тип данных, обязательное поле или нет, его размерность и т.д.
не знаю, мне это наоборот кажется нелогичным – где модели и где формы. в ларавеле стараются разделять функционал на пакеты. например в 4.х в элоквенте была возможность сразу закэшировать результаты выборки – её удалили во-первых, потому что кэширование находится за пределами зоны ответственности модели, а во-вторых потому что тогда пакет database приобретает зависимость от пакета cache даже если ты этим не пользуешься. не забывай что элоквент вполне успешно можно использовать за пределами ларавеля. я например его применял с успехом при работе с Yii и с битриксом
наверное есть какие-то пакеты, которые умеют делать формы из моделей и миграций. наверняка в каких-то из пакетов для быстрого создания админок что-то такое есть, я просто никогда ими не пользовался потому и не знаю, но это не такая сложная задача как кажется
Не в сети
Оооох, какой большой ответ) Часть из него не смогу парировать, т.к. не совсем понимаю о чем речь))) Поэтому оставим этот разговор на потом)
Добавлю только то, что django - тоже как раз сделан по принципу, что за выходные можно собрать прототип (и это подтверждено неоднократно), мб поэтому они так и схожи с laravel
К слову, мне было бы интересно узнать о первых впечатлениях от джанги от тех, кто до этого много писал на laravel. Т.к. я свои впечатления о ларавел рассказал, интересно каково с обратной стороны
Не в сети
Оооох, какой большой ответ) Часть из него не смогу парировать, т.к. не совсем понимаю о чем речь)))
ну ты читай не торопясь, вдумчиво ) спрашивай если где непонятно )
Добавлю только то, что django - тоже как раз сделан по принципу, что за выходные можно собрать прототип (и это подтверждено неоднократно), мб поэтому они так и схожи с laravel
это и неудивительно, в мире веб-разработки «перекрёстное опыление» очень распространено. в конце концов делаются схожие вещи, приходится оперировать одними и теми же абстракциями
Не в сети
Очень интересное обсуждение, жаль что оно со временем потеряется среди остальных постов.
PS: всё чаще задумываюсь по окончанию проекта написать статью "laravel vs. django", где показать как что-то делается в одном фреймворке и как в другом. Не знаю, правда, соберусь ли в итоге, т.к. времени не так много на такие вещи, но, думаю, и для меня было бы полезно изложить некоторые мысли, которые могли бы продвинуть на следующий уровень (знающие сказали бы как "правильно"), и все бы посмотрели что лучше реализовано в django и взяли на заметку (не знаю есть ли среди ваших-наших рядов ларавел контрибьюторы, но вдруг...).
Во всяком случае были (в моём лице). Статья была бы очень кстати, сам бы прочитал с удовольствием.
Не в сети
TrueKanonir пишет:Ого, круто) Теперь понятно. Спасибо за развернутый ответ)
Пожалуйста)
Вообще, советую попробовать выполнить официальный туториал от неё: https://docs.djangoproject.com/en/1.11/#first-steps - даже в нем можно подчерпнуть много полезного.PS: несомненный плюс джанги в том, что там есть автогенерируемая админка, которая покрывает 99% процентов задач при работе с ней без всякого волшебства.
Спасибо за ссыль. Да, я уже давно собираюсь развиваться в сторону питона и джанго, не как не могу собраться)) но вы своими отзывами дали так сказать "волшебный пендаль" мне)) думаю в ближайший уик енд начну изучать его))
Не в сети
Спасибо за ссыль. Да, я уже давно собираюсь развиваться в сторону питона и джанго, не как не могу собраться)) но вы своими отзывами дали так сказать "волшебный пендаль" мне)) думаю в ближайший уик енд начну изучать его))
Вот это круто!) Главное - не откладывать. Мне будет интересно узнать ощущения после прохождения туториала - что понравилось/что не понравилось. Самое важное, не ставить всё в систему глобально, а юзать virtualenv - если бага какая-то ловится, то она гуглежом решается быстро - на stackoverflow очень много ответов по джанге/питону
Не в сети
Страницы 1