• Нарушают ли конструкторы инкапсуляцию?

    greabock
    @greabock
    Могу
    1. Сеттеры не нарушают инкапсуляцию.
    Если вы устанавливаете свойство через сеттер, вы вообще уверены, что оно хранится в свойстве с тем же именем того же класса?
    object.setProperty(value)

    Вот я, глядя снаружи вообще хз, где и как хранится это свойство, если вообще хранится. А вы?

    2. Конструктор не нарушает инкапсуляцию. Ровно по тем же причинам.

    По понятным причинам, у вас не на всё должны быть сеттеры, а только те, что вы хотите менять снаружи. Если же у вас сеттеры, на все подряд свойства, то это вы нарушаете инкапсуляцию. Сеттеры тут не при чем.
    Ответ написан
    3 комментария
  • Как объеденить 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 комментарий
  • Существуют ли фулстек фреймворки для node.js?

    greabock
    @greabock
    Могу
    Таки фуллстек фреймворки существуют. Вот самые яркие примеры:

    https://www.meteor.com/
    https://derbyjs.com

    А вот стоит ли их сегодня изучать - это отдельный вопрос.

    Кроме того, существует множество обвязок, соединяющих в себе фреймворки для бэка и фронта. Яркие примеры:
    https://nextjs.org (react+express)
    https://nuxtjs.org (vue+express)
    Таких - просто тьма.

    На сегодняшний день, часто пишут "бэкенд дня фронтенда". То есть - это рендер-сервер (иногда с сессиями), который берет данные по api у "настоящего" бэкенда.
    Ответ написан
    2 комментария
  • Как вывести мультиязычное меню?

    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')
    Ответ написан
  • Почему readfile() выдает ошибку ssl?

    greabock
    @greabock
    Могу
    Если вы запускаете код локально, то чаще всего, причиной испорченных сертификатов TLS являются антивирусы. Попробуйте отключить сканирование защищенных (зашифрованных) соединений в настройках антивируса.
    Ответ написан
  • 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 комментария
  • Vue dev tools - не работает кнопка "Open in Editor". Как это можно пофиксить?

    greabock
    @greabock
    Могу
    To specify an editor, sepcify the EDITOR env variable or add "editor" field to your Vue project config.

    Я взял на себя смелость вставить эту строку в гугл-переводчик, и вот что у меня вышло:

    Чтобы указать редактор, укажите переменную env EDITOR или добавьте поле «editor» в конфигурацию проекта Vue.

    Вообще не стесняйтесь пользоваться переводчиком. Он, никогда не осудит Вас, что бы Вы ему ни скормили.
    Ответ написан
    3 комментария
  • Как реализовать ленивую подгрузку неизвестной модели laravel?

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

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

    greabock
    @greabock
    Могу
    Задать вопрос:
    "может ли он сделать качественный интернет-магазин который не будет тормозить и лагать на woocomerce".
    Если ответ "Да" - спец хреновый )
    Ответ написан
    4 комментария
  • Как получить коллекцию связанных элементов к отсортированной коллекции родительских объектов?

    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
    Могу
    Меня бы впечатлило участие в востребованном опенсорс-проексте. GitHub - наше всё )
    Однако, вопрос не совсем подходящий для тостера, ибо не имеет четкого и определенного ответа.
    Ответ написан
    2 комментария