Ответы пользователя по тегу Laravel
  • Как объеденить 2 выражения в Eloquent в одно - создания модели и получение ее контекста совместно с each инструкцией?

    greabock
    @greabock
    Могу
    factory(Attribute::class)->create();
    На сколько я могу понимать вернёт инстанс модели Attribute. Но дальше вы чейните
    factory(Attribute::class)->create()->each(#...)
    Возникает логичный вопрос each (каждый), простите, что? Но даже допустим что у вас опечатка, и вы хотели написать
    $attribute = factory(Attribute::class, 2)->create()->each(#...)

    Но тогда правильно будет
    $attributes = factory(Attribute::class, 2)->create()->each(#...)

    И в $attributes будет коллекция инстансов Attribute.

    Едем дальше... положим мы это дело поправили и написали правильно

    $attributes = factory(Attribute::class, 2)->create()->each(function (Attribute $createdAttribute) {
         $createdAttribute->multiples()->createMany(factory(Multiple::class, $multiples_count)->raw());
    });

    Откуда в кложуре появится $multiples_count?

    ну давайте и это поправим

    $multiples_count = 5;
    $attributes = factory(Attribute::class, 2)->create()->each(function (Attribute $createdAttribute) use ($multiples_count) {
         $createdAttribute->multiples()->createMany(factory(Multiple::class, $multiples_count)->raw());
    });


    Тогда

    $multiples_count = 5;
    $attributes = factory(Attribute::class, 2)->create()->each(function (Attribute $createdAttribute) use ($multiples_count) {
         $createdAttribute->multiples()->createMany(factory(Multiple::class, $multiples_count)->raw());
    });
    
    foreach  ($attributes as $attribute) {
       $attribute->doSomeThing(); // Вот вам и ваш "контекст"
    }


    К слову, "контекст" - термин, в данном случае, неуместный. Инстанс/Объект/Экземпляр - вот подходящие слова.
    "Контекст" же - это про указатели $this/static/self или текущую область видимости. Что именно - зависит от контекста разговора, простите за каламбур )
    Ответ написан
    2 комментария
  • Laravel ViewServiceProvider?

    greabock
    @greabock
    Могу
    Костыль на статике
    View::composer('dashboard', function ($view) {
         static $result;
         if(!$result) {
            $result = getSomeData();
        }
        $view->with($result);
    });


    Кроме того, вместо функции, можно назначить класс, который определить в контейнере как синглтон, и вместо cтатика (как в примере выше), использовать внутренние поля класса.
    Ответ написан
    Комментировать
  • Как правильно настроить сессию в Laravel?

    greabock
    @greabock
    Могу
    $counter = $request->session()->get('counter', 1);
    $request->session()->put('counter', ++$counter);
    Ответ написан
    1 комментарий
  • Как вывести мультиязычное меню?

    greabock
    @greabock
    Могу
    Самый простой путь:
    $menu->{'title_'.$lang}

    Чуть сложнее:
    class Menu {
        public function getTitile ($lang) 
        {
            return $this->getAttribute('title_' . $lang);
        }
    }

    {{$menu->getTitle($lang)}}

    Если совпадает с локалью:
    class Menu {
        public function getTitleAttribute() 
        {
            return $this->getAttribute('title_' . app('locale'));
        }
    }

    {{$menu->title}}

    Но стоит отметить, что мультиязычные приложения пишутся совсем не так.
    Ответ написан
    1 комментарий
  • Как в laravel passport создать refresh_token?

    greabock
    @greabock
    Могу
    1. По умолчанию, персональные токены выдаются сроком на 1 год. (нужно ли беспокоится о времени истечения?)

    2. Персональные токены - это скорее "хак", который позволяет обойти стандартный флоу OAuth 2. Обычно он используется для упрощения доступа к апи, или персональных экспериментов.

    3. Правильный способ сделать то, что вы ( как я предполагаю) хотите, это запросить токен для password grant

    use GuzzleHttp\Psr7\ServerRequest as GuzzleRequest;
    use GuzzleHttp\Psr7\Response as GuzzleResponse;
    use League\OAuth2\Server\AuthorizationServer;
    use Illuminate\Http\Response;
    use Illuminate\Http\Request;
    
    
    $server = app(AuthorizationServer::class);
    
    $psrReponse = $server->respondToAccessTokenRequest((new GuzzleRequest('POST', ''))->withParsedBody([
        'grant_type'    => 'password',
        'client_id'     => '2' // Или какой клиент у вас там за гранты паролей отвечает,
        'client_secret' => '***',
        'username'      => 'god@skies.com',
        'password'      => 'my-very-strong-password',
        'scope'         => '',
    ]), new GuzzleResponse());
    // Можно сразу запросить на вход \Psr\Http\Message\ServerRequestInterface - лара умеет такое инжектить
    // Я накидал его руками - для наглядности
    // Это могут быть любые psr7 совместимые объекты Request и Response, не только Guzzle. 
    // Например Zend\Diactoros (его ижектит лара) тоже подойдет.
    
    // Ну а здесь уже конвертируем ответ в ларовский
    // Ответ будет содержать token_type, access_token, expires_in и refresh_token 
    // expires_in содержит время жизни токена в секундах
    // Например, по умолчанию для одного года это будет 60*60*24*366 = 31622400
    return new Response(
        $psrReponse ->getBody(),
        $psrReponse ->getStatusCode(),
        $psrReponse ->getHeaders()
     );


    Здесь не описана обработка ошибок, так как я предполагаю, что данный сценарий выходит за рамки OAuth спецификации и ответы с ошибками имеют право ей не соответствовать. Это я оставлю на ваше усмотрение.
    Ответ написан
    2 комментария
  • Почему не отображаются разделы и картинки на хостинге?

    greabock
    @greabock
    Могу
    Очень похоже, что проблема в файле .env.
    Посмотрите, чему равна переменная среды APP_URL.
    В вашем конкретном случае, она должна быть равна https://site.hhos.ru.

    P.S.
    Так как файл .env находится не под версией (во всяком случае, так должно быть). У вас может отсутствовать и сам файл .env. В этом случае, нужно создать его, скопировав .env.example и назначив переменным среды актуальные для сервера значения.

    Кроме того, я бы обязательно проверил что кроется за ключом `url` в конфиге app.php.
    А так же, filesystems.php проверить ключ urlдиска public.
    В обоих случаях должно быть что-то в духе:
    'url' => env('APP_URL')
    Ответ написан
  • Laravel 5.2 редирект на предыдущую страницу с сохранением get параметров?

    greabock
    @greabock
    Могу
    Например, в Laravel есть механизм intended. Можно посмотреть как он устроен, и сделать нечто подобное.
    Нас конечно же больше всего интересуют методы guest и intended класса Illuminate\Routing\Redirector.

    /**
         * Create a new redirect response, while putting the current URL in the session.
         *
         * @param  string  $path
         * @param  int     $status
         * @param  array   $headers
         * @param  bool    $secure
         * @return \Illuminate\Http\RedirectResponse
         */
        public function guest($path, $status = 302, $headers = [], $secure = null)
        {
            $this->session->put('url.intended', $this->generator->full());
    
            return $this->to($path, $status, $headers, $secure);
        }
    
       /**
         * Create a new redirect response to the previously intended location.
         *
         * @param  string  $default
         * @param  int     $status
         * @param  array   $headers
         * @param  bool    $secure
         * @return \Illuminate\Http\RedirectResponse
         */
        public function intended($default = '/', $status = 302, $headers = [], $secure = null)
        {
            $path = $this->session->pull('url.intended', $default);
    
            return $this->to($path, $status, $headers, $secure);
        }


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

    Реализуйте схожий механизм со своими нюансами и будет вам счастье.

    Вообще (если ваша задача описана в вашем вопросе в полной мере) будет вполне достаточно сделать так:
    if(auth()->guest()) {
        session()->put('url.intended', url()->full());
    
        return redirect()->route('auth');
    }
    Ответ написан
    3 комментария
  • Почему не подгружается кастомный атрибут?

    greabock
    @greabock
    Могу
    Замыкание, передаваемое в метод "load" модели или в метод "with" построителя запросов, принимает на вход Illuminate\Database\Eloquent\Relations\Relation (в данном случае, возможно HasMany или BelongsToMany). То есть, это тоже самое, как если бы вы написали:
    $clinic->doctors()->each(function ($doctor) {
        $doctor->append('custom_atr');
    })

    Что не привело бы ни к какому результату, в виду того факта, что в Eloquent нет IdentityMap, который позволил бы связать записи вытаскиваемые при обходе each() c записями находящимися в отношении.
    А вот что действительно поможет:
    $clinic = Clinic::with('doctors')->find(1);
    $clinic->doctors->each(function ($doctor) {
        $doctor->append('custom_atr');
    });

    Здесь мы делаем итерации над уже загруженными докторами.
    Вообще, в данном конкретном случае, когда нас интересует одна конкретная клиника, даже `with` - лишний шаг, потому, что на следующей строке доктора все равно будут лениво загружены. Но для ясности можно и оставить.
    Ответ написан
    1 комментарий
  • Где лучше всего инициализировать библиотеку в Laravel?

    greabock
    @greabock
    Могу
    use Illuminate\Support\ServiceProvider;
    
    class ApiClientServiceProvider extends ServiceProvider 
    {
        /** @var boolean  Отложенный, потому не при каждом запросе нам нужно дергать это апи */
        public $deffered = true;
    
        public function register ( ) 
        {
            
            $this->app->singleton(VeryUsefulApi::class, function($app) {
                 // Не очень хорошо дергать env из провайдера, поэтому поместим-ка настройки в конфиг
                // А уж из конфига будем дергать env
                new VeryUsefulApi([$app['config']['services.verify_user']); 
            });
    
            $this->app->singleton(ApiClient::class); // Ну это если нужен именно синглтон
        }
    
         /** @return array | string[]  Сообщаем контейнеру, что если вдруг нужны эти ключи, то они тут */
        public function provides() {
            return [VeryUsefulApi::class, ApiClient::class];
        }
    }

    class ApiClient 
    {
        /** @var VeryUsefulApi */
        protected $api;
    
        public function __construct (VeryUsefulApi $api)  
        {
            $this->api = $api;
        }
        #...
    }

    class SomeController {
    
        /** @var ApiClient */
        protected $client;
    
        public fuction __construct(ApiClient  $client)
        {
              $this->clien = $client;
        }
    }

    Ну это если буквально то, что вы просили.

    С другой стороны, не очень понятно зачем вообще нужна эта обертка.
    Почему бы не дергать VeryUsefulApi напрямую, минуя обертку ApiClient.
    Ну это так, мысли вслух... "Вам из колодца виднее"(с) )
    Ответ написан
    1 комментарий
  • Как создать абстрактный Gate::define() в Laravel?

    greabock
    @greabock
    Могу
    Gate::before(function ($user, $ability) {
        return $user->hasAccess($ability);
    });

    Однако следует понимать, что все прочие шлюзы перестанут работать.
    Поэтому, можно сначала выполнить проверку, присутствует ли такая "возможность" в списке допустимых "конфигурируемых возможностей"
    Gate::before(function ($user, $ability) {
       if(in_array($ability,  ['see_private_posts', 'delete_private_posts'])) {
           return $user->hasAccess($ability);
       }
    });


    Другими словами, если замыкание переданное в метод before вернет булево значение, то это значение будет учтено. Если же это void/null, то оно не будет учтено.
    Ответ написан
    3 комментария
  • Как реализовать ленивую подгрузку неизвестной модели laravel?

    greabock
    @greabock
    Могу
    Во-первых: вы, скорее всего, путаете ленивую подгрузку с жадной. Вам, очевидно, нужна именно жадная.

    А во-вторых: рекомендую ознакомится с этим разделом документации, в котором описываются полиморфные отношения. Очень похоже, что именно они помогут вам решить эту задачу.
    Ответ написан
    1 комментарий
  • Как получить коллекцию связанных элементов к отсортированной коллекции родительских объектов?

    greabock
    @greabock
    Могу
    $posts = Post::with('comments')->get();
    $allCommentsFromAllPosts = $collection->pluck('comments')->flatten();
    Ответ написан
    Комментировать
  • Как реализовать авторизацию по email password в laravel passport?

    greabock
    @greabock
    Могу
    auth()->once($credentials);
    $token = auth()->user()->createToken('Token Name')->accessToken;

    Это если коротко и буквально то, что вы попросили.

    А если правильно, то для этого существует password grant, о котором вы можете прочитать в
    соответствующем разделе документации
    Ответ написан
    Комментировать
  • Как загрузить разные отношения для morphs отношений?

    greabock
    @greabock
    Могу
    Есть, по крайней мере, три способа сделать это.

    1) Использовать `morphedByMany`
    на православном
    на буржуйском
    class Note extends Model
    {
        public function second()
        {
            return $this->morphedByMany(SomeModelSecond::class, 'taggable');
        }
    
        public function first()
        {
            return $this->morphedByMany(SomeModelFirst::class 'taggable');
        }
    }

    Notes::with('first.relationFirst',  'second.relationSecond');

    Хотя это и приводит к изменению структуры дерева отношений, этот способ кажется вполне разумным.
    Вы можете по прежнему использовать `morphTo()` там, где не требуется жадная загрузка различных отношений.

    2) Использование глобальной жадной загрузки
    доки нет - личный опыт и кусочки сырцов:

    class SomeModelFirst extends Model
    {
        public $with = ['relationFirst'];
    
        public function notes()
        {
            return $this->morphMany(App\Note::class, 'noteable');
        }
    
       public function relationFirst()
        {
            return $this->belongsTo(Photo::class);
        }
    }

    class SomeModelSecond extends Model
    {
        public $with = ['relationSecond']
    
        public function notes()
        {
            return $this->morphMany(App\Note::class, 'noteable');
        }
    
       public function relationSecond() {
            return $this->belongsToMany(Comment::class);
       }
    }

    однако, следует понимать что теперь эти связи будут загружаться жадно всегда, за исключением тех случаев, когда вы явно или косвенно вызываете newQueryWithoutRelationships . Например тот же самый метод with() перекрывает $with указанный в модели.
    Таким образом, можно обыграть эту особенность метода, сбросив жадно-загружаемые отношения
    SomeModelFirst::with([])->get();

    3) Ручная группировка коллекций.
    на православном
    на буржуйском
    $notes = Notes::with('noteable');
    
    $notesGrouped = $noted->groupBy(function($model){
        return get_class($model);
    });
    
    $notesGrouped[SomeModelFirst::class]->load('relationFirst');
    $notesGrouped[SomeModelSecond ::class]->load('relationSecond');

    Так как объекты в php передаются по ссылке, в моделях исходной коллекции $notes теперь будут загружены необходимые отношения. Этот способ кажется наименьшей болью.

    Наверняка найдутся и иные способы сделать это. Но прямо сейчас мне довольно лениво думать об этом =)
    Ответ написан
    2 комментария
  • Нужно ли упростить код контроллера для сохранения моделей динамической формы?

    greabock
    @greabock
    Могу
    Мои глаза... Мужик, тебе бы реально базу подтянуть по пыху. Чет совсем все плохо у тебя. Какое-то невнятное жонглирование ненужными переменными.

    public function store(Request $request)
    {
        Product::create($request->only('product_title'))->photos()->saveMany(array_map(function($photo_filename,  $photo_title, $photo_desc){
            return new Photo(compact('photo_filename', 'photo_title', 'photo_desc'));
        },  ...$request->only('photo_filenames', 'photo_titles', 'photo_descs')));
        
        return back();
    }
    Ответ написан
    5 комментариев
  • Как правильно вести разразработку в PhpStorm?

    greabock
    @greabock
    Могу
    Правильно - использовать систему контроля версий. Например git.
    Если совсем правильно, то для деплоя нужно использовать, соответствующий инструмент (например Capistrano или любой другой аналог)
    Для бедных, можно настроить банальный хук.
    При пуше (или мерже) допустим в мастер, на рабочий сервер улетает хук. Обработчик хука в свою очередь стянет все изменения из репозитория системы контроля версий, и запустит все необходимые команды (миграции, прогрев кеша, и вообще всё, что душе угодно).
    Ответ написан
    Комментировать
  • Как изменить данные внутри самой модели?

    greabock
    @greabock
    Могу
    public function setWatched()
    {  
                  $this->defineWatched(1);
    }
    
    public function defineWatched($value)
    {
                  $this->watched = $value;
    }

    Вот так лучше. Нужно же два врапера на публичное свойство. Одного-то мало.
    Ответ написан
    2 комментария
  • Как сортировать по полю связанной таблицы в laravel?

    greabock
    @greabock
    Могу
    Вы пытаетесь выбрать пост с комментариями.
    Вам нужны комментарии? Так и выбирайте комментарии.
    Comment::whereHas('post', function( $query ) use ($id) {
            $query->whereId($id);
    })->orderBy('created_at')->paginate(0, 15);

    Иначе, с порядком вывода может и можно справится, но не с постраничным разбиением.
    Ответ написан