Our Black Friday sale is now live! All individual subscriptions are 50% OFF. This week only!

Tippin

Tippin

Member Since 8 Months Ago

TAMPA

Experience Points
16,770
Total
Experience

3,230 experience to go until the next level!

In case you were wondering, you earn Laracasts experience when you:

  • Complete a lesson — 100pts
  • Create a forum thread — 50pts
  • Reply to a thread — 10pts
  • Leave a reply that is liked — 50pts
  • Receive a "Best Reply" award — 500pts
Lessons Completed
24
Lessons
Completed
Best Reply Awards
24
Best Reply
Awards
  • start your engines Created with Sketch.

    Start Your Engines

    Earned once you have completed your first Laracasts lesson.

  • first-thousand Created with Sketch.

    First Thousand

    Earned once you have earned your first 1000 experience points.

  • 1-year Created with Sketch.

    One Year Member

    Earned when you have been with Laracasts for 1 year.

  • 2-years Created with Sketch.

    Two Year Member

    Earned when you have been with Laracasts for 2 years.

  • 3-years Created with Sketch.

    Three Year Member

    Earned when you have been with Laracasts for 3 years.

  • 4-years Created with Sketch.

    Four Year Member

    Earned when you have been with Laracasts for 4 years.

  • 5-years Created with Sketch.

    Five Year Member

    Earned when you have been with Laracasts for 5 years.

  • school-in-session Created with Sketch.

    School In Session

    Earned when at least one Laracasts series has been fully completed.

  • welcome-newcomer Created with Sketch.

    Welcome To The Community

    Earned after your first post on the Laracasts forum.

  • full-time-student Created with Sketch.

    Full Time Learner

    Earned once 100 Laracasts lessons have been completed.

  • pay-it-forward Created with Sketch.

    Pay It Forward

    Earned once you receive your first "Best Reply" award on the Laracasts forum.

  • subscriber Created with Sketch.

    Subscriber

    Earned if you are a paying Laracasts subscriber.

  • lifer Created with Sketch.

    Lifer

    Earned if you have a lifetime subscription to Laracasts.

  • evangelist Created with Sketch.

    Laracasts Evangelist

    Earned if you share a link to Laracasts on social media. Please email [email protected] with your username and post URL to be awarded this badge.

  • chatty-cathy Created with Sketch.

    Chatty Cathy

    Earned once you have achieved 500 forum replies.

  • lara-veteran Created with Sketch.

    Laracasts Veteran

    Earned once your experience points passes 100,000.

  • 10k-strong Created with Sketch.

    Ten Thousand Strong

    Earned once your experience points hits 10,000.

  • lara-master Created with Sketch.

    Laracasts Master

    Earned once 1000 Laracasts lessons have been completed.

  • laracasts-tutor Created with Sketch.

    Laracasts Tutor

    Earned once your "Best Reply" award count is 100 or more.

  • laracasts-sensei Created with Sketch.

    Laracasts Sensei

    Earned once your experience points passes 1 million.

  • top-50 Created with Sketch.

    Top 50

    Earned once your experience points ranks in the top 50 of all Laracasts users.

Level 4
16,770 XP
Nov
20
5 days ago
Activity icon

Replied to Stop Adding Poor Quality Laravel Addons

@goppi The main part that calls the passport controller is this trait: https://github.com/RTippin/laravel-api-auth/blob/master/app/Http/Controllers/Auth/Concerns/HandlesApiAuth.php

I merge the base laravel http request from API with what passport expects "grant_type, scope etc". then I use the container to create the controller and ServerRequestInterface that passports method wants. Notice I am calling passports AccessTokenController

    /**
     * Request access token from oauth server
     *
     * @param Request $request
     * @return Response
     */
    protected function issueTokenFromServer(Request $request)
    {
        try
        {
            return $this->tokenServer()->issueToken($this->serverRequest());
        }
        catch (Exception $e)
        {
            $this->incrementAttempts($request);

            throw new HttpException(422, $e->getMessage());
        }
    }

    /**
     * Get the AccessTokenController instance
     *
     * @return Application|AccessTokenController|mixed
     */
    protected function tokenServer()
    {
        return app(AccessTokenController::class);
    }

    /**
     * Get the ServerRequestInterface instance
     *
     * @return Application|mixed|ServerRequestInterface
     */
    protected function serverRequest()
    {
        return app(ServerRequestInterface::class);
    }

The JWT part you see is not part of the login actually. You see no calls to it because I use it for events I emit. Basically that snippet lets me get the passport token ID out of the returned accessToken.

        $this->fireTokenDeviceEvent(
            $request,
            $this->guard()->user(),
            $this->parseJwtTokenId($this->jwt, $token)
        );

After login, in my app I fire this request so that a queued listener can do work on the database / link devices since I hand it directly the access token ID parsed using JWT, which is what passport uses behind the scenes to encode the accessToken. Usually when you login with passport, you do not have access to the oauth_access_token it created right away, thus using JWT you can get it back out from access token.

Activity icon

Replied to Stop Adding Poor Quality Laravel Addons

@goppi Went ahead and removed some stuff that you will not need. Please note that the way I did this, I set my PASSPORT_PASSWORD_GRANT_CLIENT_ID and PASSPORT_PASSWORD_GRANT_CLIENT_SECRET in my env / passport.php config file, as I only require the secret to be posted (first party password grants like a mobile app). I merge the request with the ServerRequest interface and use the app container to create the passport controller and call its method. But feel free to checkout my API controllers and how I call passport behind the scenes. I'm sure there are better ways of doing this, but this is how I solved this issue 6 months ago and have not changed any code since then. (I did paste this into a fresh laravel 8 so tested nothing)

https://github.com/RTippin/laravel-api-auth

Activity icon

Replied to Stop Adding Poor Quality Laravel Addons

@goppi I will add that I personally use passport without using their published routes, however I only use the password grant / login / refresh capabilities. I found it was quite easy to wrap my own logic in my controllers and call to the base passport controller for authorization. I then can catch any errors myself and do things I want to happen, not what passport wants to happen. If you just need the simple login/refresh with passport, I can share how I did it myself.

Nov
19
6 days ago
Activity icon

Replied to Real World Usage Of Interface And It's Meaning

@rymercyble Other than the given "force classes to implement methods defined in the interface", the beauty in laravel is using the dependency injection through contracts/concretes(implementations).

Real world example: I have a messaging system that also has calling built in. Now my system manages the databse and cache parts of the call, but the actual provider could be anything (Twillio, BigBlueButton, WebRTC, etc). Now when a call starts, a queued event listener will setup the call/video room with the service I choose, but the beauty of using contracts come in when making myself a swappable "driver" of sorts. This will come in handy not only for testing (I have a class that implements my contract but does absolutely nothing). Inside my action class, I type hint my VideoDriver contract, and my logic simply needs to call $driver->create() but does not care about what happens in the create. So using laravels service providers, I bind my Concrete implementation of the contract to the contract itself, which tells laravel anytime the container wants to resolve my contract, it will give it the concrete class.

Contract

<?php

namespace App\Contracts;

interface VideoDriver
{
    /**
     * Set the thread we will be working with
     *
     * @param Thread $thread
     * @return $this
     */
    public function setThread(Thread $thread): self;

    /**
     * Set the call we will be working with
     *
     * @param Call|null $call
     * @return $this
     */
    public function setCall(Call $call): self;

    /**
     * Setup the video room for the call/thread
     *
     * @return mixed
     */
    public function create();

    /**
     * Teardown the video room for the call/thread
     *
     * @return mixed
     */
    public function destroy();

    /**
     * Called after create/destroy to know if action worked
     *
     * @return bool
     */
    public function isSuccessful(): bool;

    /**
     * @return string|null
     */
    public function getRoomId(): ?string;

    /**
     * @return string|null
     */
    public function getRoomPin(): ?string;

    /**
     * @return string|null
     */
    public function getRoomSecret(): ?string;

    /**
     * @return string|null
     */
    public function getEndpoint(): ?string;
}

Then in my service provider inside register(): I tell the container anytime It tries to resolve my video driver, give me my janus implementation

    /**
     * Register services and singletons
     *
     * @return void
     */
    public function register()
    {
        $this->app->singleton(
            VideoDriver::class,
            JanusBroker::class
        );
    }

JanusBroker

<?php

use App\Contracts\VideoDriver;
use App\Services\Janus\VideoRoomService;

class JanusBroker implements VideoDriver
{
    /**
     * @var VideoRoomService
     */
    private VideoRoomService $videoRoomService;

    /**
     * @var Thread|null
     */
    private ?Thread $thread = null;

    /**
     * @var Call|null
     */
    private ?Call $call = null;

    /**
     * @var bool
     */
    private bool $isSuccessful = false;

    /**
     * @var string|null
     */
    private ?string $roomId = null;

    /**
     * @var string|null
     */
    private ?string $roomPin = null;

    /**
     * @var string|null
     */
    private ?string $roomSecret = null;

    /**
     * @var string|null
     */
    private ?string $endpoint = null;

    /**
     * JanusBroker constructor.
     *
     * @param VideoRoomService $videoRoomService
     */
    public function __construct(VideoRoomService $videoRoomService)
    {
        $this->videoRoomService = $videoRoomService;
    }

    /**
     * @inheritDoc
     */
    public function setThread(Thread $thread): self
    {
        $this->thread = $thread;

        return $this;
    }

    /**
     * @inheritDoc
     */
    public function setCall(Call $call): self
    {
        $this->call = $call;

        return $this;
    }

    /**
     * @inheritDoc
     */
    public function create(): void
    {
        $this->isSuccessful = false;

        $janus = $this->videoRoomService
            ->create($this->settings());

        if($janus)
        {
            $this->roomId = $janus['room'];
            $this->roomPin = $janus['pin'];
            $this->roomSecret = $janus['secret'];
            $this->isSuccessful = true;
        }
    }

    /**
     * @inheritDoc
     */
    public function destroy(): void
    {
        $this->isSuccessful = false;

        $janus = $this->videoRoomService->destroy(
            $this->call->room_id,
            $this->call->room_secret
        );

        $this->isSuccessful = $janus;
    }

    /**
     * @inheritDoc
     */
    public function getRoomId(): ?string
    {
        return $this->roomId;
    }

    /**
     * @inheritDoc
     */
    public function getRoomPin(): ?string
    {
        return $this->roomPin;
    }

    /**
     * @inheritDoc
     */
    public function getRoomSecret(): ?string
    {
        return $this->roomSecret;
    }

    /**
     * @inheritDoc
     */
    public function getEndpoint(): ?string
    {
        return $this->endpoint;
    }

    /**
     * @inheritDoc
     */
    public function isSuccessful(): bool
    {
        return $this->isSuccessful;
    }

    /**
     * @return array
     */
    private function settings(): array
    {
        return [
            'description' => $this->thread->id,
            'publishers' => $this->publishersCount(),
            'bitrate' => $this->bitrate()
        ];
    }

    /**
     * @return int
     */
    private function publishersCount(): int
    {
        return $this->thread->isGroup()
            ? $this->thread->participants()->count() + 6
            : 4;
    }

    /**
     * @return int
     */
    private function bitrate(): int
    {
        return $this->thread->isGroup()
            ? 600000
            : 1024000;
    }
}

I could make another driver to create video rooms with twillio since all I need back are simple room ID or extra payload data for frontend JS. Now here is a Null version I can swap in for testing when I want features to run but not actually create stuff with my 3rd party services

NullVideoDriver

<?php

use App\Contracts\VideoDriver;

class NullVideoBroker implements VideoDriver
{
    /**
     * @inheritDoc
     */
    public function setThread(Thread $thread): self
    {
        return $this;
    }

    /**
     * @inheritDoc
     */
    public function setCall(Call $call): self
    {
        return $this;
    }

    /**
     * @inheritDoc
     */
    public function create(): void
    {
        //
    }

    /**
     * @inheritDoc
     */
    public function destroy(): void
    {
        //
    }

    /**
     * @inheritDoc
     */
    public function getRoomId(): ?string
    {
        return null;
    }

    /**
     * @inheritDoc
     */
    public function getRoomPin(): ?string
    {
        return null;
    }

    /**
     * @inheritDoc
     */
    public function getRoomSecret(): ?string
    {
        return null;
    }

    /**
     * @inheritDoc
     */
    public function getEndpoint(): ?string
    {
        return null;
    }

    /**
     * @inheritDoc
     */
    public function isSuccessful(): bool
    {
        return true;
    }
}

And finally, the single action class that request a VideoDriver from the container by type hinting it in the constructor. Laravel will give it w.e driver concrete class I bound in the service provider.

Action

<?php

use App\Contracts\VideoDriver;
use Exception;

class CallBrokerSetup extends BaseMessengerAction
{
    /**
     * @var VideoDriver
     */
    private VideoDriver $videoDriver;

    /**
     * CallBrokerSetup constructor.
     *
     * @param VideoDriver $videoDriver
     */
    public function __construct(VideoDriver $videoDriver)
    {
        $this->videoDriver= $videoDriver;
    }

    /**
     * @param mixed ...$parameters
     * @return $this
     * @var Thread $thread $parameters[0]
     * @var Call $call $parameters[1]
     * @throws Exception
     */
    public function execute(...$parameters): self
    {
        $this->setThread($parameters[0])
            ->setCall($parameters[1])
            ->setupCallWithProvider()
            ->setupWasSuccessful()
            ->updateCall();

        return $this;
    }

    /**
     * @return $this
     */
    private function setupCallWithProvider(): self
    {
        $this->videoProvider
            ->setThread($this->getThread())
            ->setCall($this->getCall())
            ->create();

        return $this;
    }

    /**
     * @return $this
     * @throws Exception
     */
    private function setupWasSuccessful(): self
    {
        if( ! $this->videoProvider->isSuccessful())
        {
            throw new Exception('Setup video provider failed.');
        }

        return $this;
    }

    /**
     * Update the call with the information we received from our video provider
     */
    private function updateCall()
    {
        $this->setData($this->getCall()
            ->update([
                'setup_complete' => true,
                'room_id' => $this->videoProvider->getRoomId(),
                'room_pin' => $this->videoProvider->getRoomPin(),
                'room_secret' => $this->videoProvider->getRoomSecret(),
                'endpoint' => $this->videoProvider->getEndpoint()
            ])
        );
    }
}

Sorry if that is a bit to take in. But the action class will work whether I use the Null driver (all returns are null/string or w.e contract requires) or I pass it my janus/twillio or any other custom ones I make. I can even decide to swap out at runtime based on things like if I did multi-tenancy, I may want customer 1 on janus, and customer 2 on twillio. Both clients can use same action class but get different implementations on the fly.

Also, think about how with laravel, in your env/config you simple set drivers for things like Cache:file/redis, database:mysql,postgres etc. You can be safe knowing anywhere you ask for DB or Cache facades/contracts the container will give you the proper implementation. Behind the scenes every cache driver has base stuff like get() has(), but each one implements it differently to to handshake with whatever it was tasked to work with.

Nov
17
1 week ago
Activity icon

Replied to Overriding Core Classes

@mdupor So I found a way to override it, but not sure if the effort is what you are looking for as you still need to edit every migration file. I made a custom helper method where I call in the DB connector schema builder, then inject my custom blueprint into the resolver. Then instead of Schema facade in migrations, call my helper.

MyBlueprint

<?php

namespace App;

use Illuminate\Database\Schema\Blueprint;

class MyBlueprint extends Blueprint
{
    /**
     * Add nullable creation and update timestamps to the table.
     *
     * @param  int  $precision
     * @return void
     */
    public function timestamps($precision = 0)
    {
        $this->timestamp('created_at', $precision)->nullable();

        $this->timestamp('updated_at', $precision)->nullable();

        $this->timestamp('testing_at', $precision)->nullable();
    }
}

Helper in my helpers.php

<?php

use App\MyBlueprint;

if ( ! function_exists('mySchema'))
{
    /**
     * @return Illuminate\Database\Schema\Builder
     */
    function mySchema()
    {
        $schema =  app('db')->connection()->getSchemaBuilder();

        $schema->blueprintResolver(function($table, $callback){
            return new MyBlueprint($table, $callback);
        });

        return $schema;
    }
}

Tested in a migration file

<?php

use App\MyBlueprint;
use Illuminate\Database\Migrations\Migration;

class CreateFriendsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        mySchema()->create('friends', function (MyBlueprint $table) {
            $table->uuid('id')->primary();
            $table->uuidMorphs('owner');
            $table->uuidMorphs('party');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        mySchema()->dropIfExists('friends');
    }
}

***Editing to add that I am also not a fan of Macros, but doing it this way still gets your IDE to understand and code complete, and I can easily GoTo declaration and see the class it extends if I was a new dev wondering what you did.

Activity icon

Replied to Overriding Core Classes

@mdupor Not at my pc to test this, but technically can you not bind any one class to another? So you could still make MyBlueprint extends Blueprint, override the timestamps method. Then in container, bind like so:

$this->app->bind('Illuminate\Database\Schema\Blueprint', function ($app) {
    return $app->make('App\MyBlueprint');
});
Activity icon

Replied to Overriding Core Classes

@mdupor Since I assume you call blueprint only in your migrations, why not just make your own BluePrint class that extends the base Blueprint and overrides the method (since it is public). Then just inject your own blueprint in your migrations. Unless you are trying to find a more "laravel" way.

Activity icon

Replied to Overriding Core Classes

@mdupor Could you not also just override that method by registering a macro using the same method name in your app provider? (Since I see Blueprint is macroable)

Blueprint::macro('timestamps', function ($precision = 0) {  
    // Your timestamps implementation
});
Nov
16
1 week ago
Activity icon

Replied to PHPStorm Marking Closure As An Error

File / Settings / Languages & Frameworks tree / PHP. You should see the PHP language level. Also under PHP Runtime tab, be sure all the Core options are checked. Here is what mine looks like:

https://i.imgur.com/PpwPyHH.png

One last thing to add, my PHPStorm auto sets my php level based on the php in composer.json

"require": {
        "php": "^7.4",
},
Nov
15
1 week ago
Activity icon

Replied to PHPStorm Marking Closure As An Error

@foks Sorry for the late reply. Unfortunately I cannot replicate your issue. The only time I ever get php storm complaining like that is when either php interpreter is not set or vendor files not installed. The only other thing I noticed that I am not used to seeing (never used fortify) is your file is in the Modules workspace and not app, so maybe your workspace is not set to that directory....though that may not be the issue since it seems it understands the laravel part of the code. Sorry!

Activity icon

Replied to PHPStorm Marking Closure As An Error

@foks If you hover over the squigglies on the top of bottom of the docblock /** what does it say? Also, does it say class not defined when you hover over closure? In the settings, do you have the path for your php.exe setup as well?

Nov
14
1 week ago
Activity icon

Replied to PHPStorm Marking Closure As An Error

@foks phpstorm tends to do this with global classes. Try removing the backward slash in the docblock. Also, to remove the other warning underlines, add throws to the docblock since it can throw an auth exception.

<?php

namespace Modules\Fortify\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Auth;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Http\Request;

class FortifyAccess
{
    /**
     * Handle an incoming request.
     *
     * @param  Request  $request
     * @param  Closure  $next
     * @return mixed
     * @throws AuthorizationException
     */
    public function handle(Request $request, Closure $next)
    {
        if(Auth::user()->hasPermission('view_fortify')){
	 	return $next($request);
	}
        abort(401);
    }
}

Also, the fact your helper files are underlined tells me you may have something misconfigured with your phpStorm. One thing I recommend running first is the ide-helper, https://github.com/barryvdh/laravel-ide-helper

php artisan ide-helper:generate

php artisan ide-helper:meta

Activity icon

Awarded Best Reply on How To Silently Execute Controller?

@andyandy First of all, you really should not be trying to call one controllers methods from another. What it sounds like to me is you could use a service or action class for your parser. If you simply make a service class, you can inject it into the method of both your parser controller (if that controller directly responds to http request), and inject in your other controller where you want to run without debugging. To solve the debug issue, if this is something you just want to do temporarily, then add a boolean in your method.

Service

<?php

namespace App\Services;

class ParserService
{
    public function parse($parameters, bool $debug = true)
    {
        if($debug){
             //debugs
        }

	//main code with $parameters
    }

Parser controller

public function index(ParserService $service, $routeParam){
	$service->parse($routeParam)
}

Other misc controller with no debug

public function otherMethod(ParserService $service, $routeParam){
	$service->parse($routeParam, false)
}
Nov
13
1 week ago
Activity icon

Replied to Laravel Caching Problem (blade) / Blade Command

@t0berius Blade views/directives are compiled once, so you should probably return a php string so that the code is executed in the view, and not the compiled string you are getting cached. Try:

public function boot()
{
    Blade::directive('version', function ($expression) {
        return '<?php (new App\Http\Helpers\GitVersionHelper)->getCommit(); ?>';
    });
}

Personally I would just make a helper method in my helper.php file and use app() helper to resolve your GitVersionHelper class, and call helper in blade files where you want it.

helper.php

if ( ! function_exists('git'))
{
    function git()
    {
        return app(App\Http\Helpers\GitVersionHelper::class);
    }
}

Then in your views, just call:

<span> {{ git()->getCommit() }} </span>
Activity icon

Replied to How To Silently Execute Controller?

@andyandy First of all, you really should not be trying to call one controllers methods from another. What it sounds like to me is you could use a service or action class for your parser. If you simply make a service class, you can inject it into the method of both your parser controller (if that controller directly responds to http request), and inject in your other controller where you want to run without debugging. To solve the debug issue, if this is something you just want to do temporarily, then add a boolean in your method.

Service

<?php

namespace App\Services;

class ParserService
{
    public function parse($parameters, bool $debug = true)
    {
        if($debug){
             //debugs
        }

	//main code with $parameters
    }

Parser controller

public function index(ParserService $service, $routeParam){
	$service->parse($routeParam)
}

Other misc controller with no debug

public function otherMethod(ParserService $service, $routeParam){
	$service->parse($routeParam, false)
}
Nov
01
3 weeks ago
Activity icon

Replied to Using Uuid For The Id And Getting It Returned After Create Or Save

@gerritsevilla Ever since laravel merged Ramsey package into their Str::class facade, I have no issue using the uuid->toString method on model creating. I have immediate access to $model->id after it has been saved, or called using create(). Check out my trait I use on my models with UUIDs:

<?php

namespace App\Traits;

use Illuminate\Database\Eloquent\Model;
use Str;

trait Uuids
{
    /**
     * On model creating, set the primary key to UUID
     */
    public static function bootUuids()
    {
        static::creating(function (Model $model) {
            $model->{$model->getKeyName()} = Str::orderedUuid()->toString();
        });
    }
}

I just tested making 2 users, and dumping ID out, and it worked:

        $test = User::create([
            'first' => 'Derpy',
            'last' => 'Herpy',
            'slug' => '12345',
            'active' => 1,
            'email' => '[email protected]',
            'password' => 'password'
        ]);

        dump($test->id);

//"91e85023-4508-4c90-972b-5298e1768702"

        $test2 = new User();
        $test2->first = 'nope';
        $test2->last = 'never';
        $test2->slug = '8888';
        $test2->active = 1;
        $test2->email = '[email protected]';
        $test2->password = '987987987';
        $test2->save();

        dump($test2->id);

//"91e85023-55a7-46e0-801c-8fa9ed9a846a"
Oct
31
3 weeks ago
Activity icon

Replied to I Am Getting Error While Using Chatify Package

@sinnbeck Fair enough, but awesome, when I am ready I will let ya know! I may have it up first as a demo app, as I have never extracted down to a package, but I have abstracted out many classes and interfaces, with many config options, so it should be easy to extract. Just a very beefy project as I baked every option a messenger / video chat app would need into it XD

Activity icon

Replied to I Am Getting Error While Using Chatify Package

@sinnbeck Are you still actively developing your own chat / messenger? Asking since I noticed from your git responses, and I myself am working on one for consumption, that allows multiple models / providers. I would be interested to get your opinion or share ideas.

Oct
12
1 month ago
Activity icon

Awarded Best Reply on Relationships - Private Messaging

@nrginternetdiensten When it comes to messages, one thing I usually do is set it up in 3 main tables: [threads, participants, messages]. Threads are stand alone, participants belong to an owner and thread, and messages belong to thread and owner. Then I just use participants as a pivot to load threads for a given user. (I do prefer morphs since I use messages between different models). My participants has the last_read timestamp for managing unread counts. I also like to give my threads types, that way I can do private, group and other misc types. I like to use soft deletes, especially on participants. That way, if someone leaves a group thread but is re-added, we can show them new unread messages since after they left. Here are how I setup my base tables, and base relation I put in a trait to any model I want to message for loading threads:

Database

        Schema::create('threads', function (Blueprint $table) {
            $table->uuid('id');
            $table->integer('type')->default(1);
            $table->string('subject')->nullable();
            $table->string('image')->nullable();
            $table->timestamps();
            $table->softDeletes();
            $table->primary('id');
        });

        Schema::create('messages', function (Blueprint $table) {
            $table->uuid('id');
            $table->uuid('thread_id');
            $table->uuidMorphs('owner');
            $table->text('body');
            $table->integer('type');
            $table->timestamps();
            $table->softDeletes();
            $table->primary('id');
            $table->index('type');
            $table->foreign('thread_id')
                ->references('id')
                ->on('threads')
                ->onDelete('cascade')
                ->onUpdate('cascade');
        });

        Schema::create('participants', function (Blueprint $table) {
            $table->uuid('id');
            $table->uuid('thread_id');
            $table->uuidMorphs('owner');
            $table->timestamp('last_read')->nullable()->default(null);
            $table->timestamps();
            $table->softDeletes();
            $table->primary('id');
            $table->foreign('thread_id')
                ->references('id')
                ->on('threads')
                ->onDelete('cascade')
                ->onUpdate('cascade');
        });

Load threads relation

    public function threads()
    {
        return $this->belongsToMany(
            Thread::class,
            'participants',
            'owner_id',
            'thread_id'
        )->whereNull('participants.deleted_at')
        ->where('owner_type', get_class($this));
    }

Relations for everything else is easy. Threads have many participants/messages. Participant belong to thread and owner morph, messages belong to thread and owner morph, etc

Oct
10
1 month ago
Activity icon

Replied to API Route Model Binding | Exception Handling

@qwertynik One thing you can do is edit your Exceptions/Handler.php render method. You can choose to return json response or throw new http not found exception with your custom message in the exception. If you take model not found and throw new not found http, by default if going over API, or your request uses accept: application/json, laravel will automatically return json. I prefer to throw my own message, but still use the class/resource name in my message for posterity. Below is an example in my handler where I catch model not found, and throw new http not found, and I use reflection class to get model name, but lowercase and separate words (App\UserDevice becomes user device, App\User becomes user, etc). So instead of No query results for model [App\UserDevice] 123, you will get Unable to locate the user device you requested.

Also, not sure why, but laracast is removing my code and putting in SNIPPET_PLACEHOLDER, so where you see that in my bottom method, it actually is: $0 with a leading space

<?php

namespace App\Exceptions;

use App;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Redirector;
use Illuminate\Support\Str;
use ReflectionClass;
use ReflectionException;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Throwable;

class Handler extends ExceptionHandler
{
    /**
     * A list of the exception types that should not be reported.
     *
     * @var array
     */
    protected $dontReport = [];

    /**
     * @param Throwable $exception
     * @return mixed|void
     * @throws Throwable
     */
    public function report(Throwable $exception)
    {
        parent::report($exception);
    }

    /**
     * Render an exception into an HTTP response.
     *
     * @param Request $request
     * @param Throwable $exception
     * @return Response|JsonResponse|RedirectResponse|Redirector
     * @throws Throwable
     * @noinspection PhpMissingParamTypeInspection
     */
    public function render($request, Throwable $exception)
    {
        if($request->expectsJson())
        {
            if($exception instanceof ModelNotFoundException)
                return new JsonResponse([
                    'message' => "Unable to locate the {$this->prettyModelNotFound($exception)} you requested."
                ], 404);
        }

        if($exception instanceof ModelNotFoundException)
            throw new NotFoundHttpException("Unable to locate the {$this->prettyModelNotFound($exception)} you requested.");

        return parent::render($request, $exception);
    }

    /**
     * @param Throwable $exception
     * @return string
     * @noinspection PhpPossiblePolymorphicInvocationInspection
     */
    private function prettyModelNotFound(Throwable $exception)
    {
        try {
            return Str::lower(
                ltrim(
                    preg_replace(
                        '/[A-Z]/',
                        ' LARACASTS_SNIPPET_PLACEHOLDER',
                        (new ReflectionClass($exception->getModel()))->getShortName()
                    )
                )
            );
        } catch (ReflectionException $e) {
            report($e);
        }
        return 'resource';
    }
}
Activity icon

Replied to Relationships - Private Messaging

@nrginternetdiensten When it comes to messages, one thing I usually do is set it up in 3 main tables: [threads, participants, messages]. Threads are stand alone, participants belong to an owner and thread, and messages belong to thread and owner. Then I just use participants as a pivot to load threads for a given user. (I do prefer morphs since I use messages between different models). My participants has the last_read timestamp for managing unread counts. I also like to give my threads types, that way I can do private, group and other misc types. I like to use soft deletes, especially on participants. That way, if someone leaves a group thread but is re-added, we can show them new unread messages since after they left. Here are how I setup my base tables, and base relation I put in a trait to any model I want to message for loading threads:

Database

        Schema::create('threads', function (Blueprint $table) {
            $table->uuid('id');
            $table->integer('type')->default(1);
            $table->string('subject')->nullable();
            $table->string('image')->nullable();
            $table->timestamps();
            $table->softDeletes();
            $table->primary('id');
        });

        Schema::create('messages', function (Blueprint $table) {
            $table->uuid('id');
            $table->uuid('thread_id');
            $table->uuidMorphs('owner');
            $table->text('body');
            $table->integer('type');
            $table->timestamps();
            $table->softDeletes();
            $table->primary('id');
            $table->index('type');
            $table->foreign('thread_id')
                ->references('id')
                ->on('threads')
                ->onDelete('cascade')
                ->onUpdate('cascade');
        });

        Schema::create('participants', function (Blueprint $table) {
            $table->uuid('id');
            $table->uuid('thread_id');
            $table->uuidMorphs('owner');
            $table->timestamp('last_read')->nullable()->default(null);
            $table->timestamps();
            $table->softDeletes();
            $table->primary('id');
            $table->foreign('thread_id')
                ->references('id')
                ->on('threads')
                ->onDelete('cascade')
                ->onUpdate('cascade');
        });

Load threads relation

    public function threads()
    {
        return $this->belongsToMany(
            Thread::class,
            'participants',
            'owner_id',
            'thread_id'
        )->whereNull('participants.deleted_at')
        ->where('owner_type', get_class($this));
    }

Relations for everything else is easy. Threads have many participants/messages. Participant belong to thread and owner morph, messages belong to thread and owner morph, etc

Aug
18
3 months ago
Activity icon

Replied to How To Post Code In Laracasts

@simonangatia Follow the link at the bottom of every Reply/New Discussion window that pops up. Basically follows githubs style markdown which is also used in README's.

https://docs.github.com/en/github/writing-on-github/creating-and-highlighting-code-blocks

Aug
14
3 months ago
Activity icon

Replied to How To Restrict Users To Do Multiple Login From Different Devices?

@krishna8723 The best (only feasible) way I can think of would be to just use oauth/passport style token login. Tracking sessions per device is not easily done. However, if you go with oauth, tokens are linked to users, so all you have to do is revoke old tokens for a given user if they have more than 2 active tokens. I do this for a desktop app I made where the app accesses my API. But I only wanted one app to be able to be logged in at a time. But same premise can be used on web (only with oauth, like SPA)

Aug
03
3 months ago
Activity icon

Replied to API Route Guest Access.

@phpmick One thing you may want to try, set the guard when using guest. Just like auth:api, try guest:api

Route::namespace('\')->middleware('guest:api')->group(function () {
	
});

Jul
26
3 months ago
Activity icon

Awarded Best Reply on Where Do I Add Custom.css In Webpack?

@aron-spiess If you want it as it's own file, and not in app.css, you can append another .sass()

mix.js("resources/js/app.js", "public/js/app.js")
    .sass("resources/sass/app.scss", "public/css/app.css")
    .sass("resources/sass/tailwind.scss", "public/css/tailwind.css")
    .sourceMaps();

If you want it included within app.css, then open app.scss and add the import to wherever your tailwind scss file is

@import "tailwind";
Jul
25
4 months ago
Activity icon

Replied to Laravel Broadcasting Private Channel “Client Can Not Be Authenticated, Got HTTP Status 500”

Does your event class implement ShouldBroadcast? Also, do you have a queue worker running? By default, broadcast events are queued. To bypass that, you can implement broadcast now, like so

<?php

namespace App\Events;

use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class Ordered implements ShouldBroadcastNow
{

}
Activity icon

Replied to Laravel Broadcasting Private Channel “Client Can Not Be Authenticated, Got HTTP Status 500”

Does the echo server at least show the event being broadcasted?

Seems your event is called Ordered not OrderedEvent, try:

echo.private('order.8')
    .listen('.Ordered', (e) => {
        console.log("DATA RECEIVED");
        console.log(e);
});

Also, I prefer to give my broadcast events my own name instead of relying on namespaces on the frontend, so try adding broadcast as method into your event class, and edit the name in JS accordingly:

Event class

    public function broadcastAs()
    {
        return 'ordered';
    }

JS

echo.private('order.8')
    .listen('.ordered', (e) => {
        console.log("DATA RECEIVED");
        console.log(e);
});
Activity icon

Replied to Telescope In Production To Record Mail And Jobs?

@moiz Each entry has a type attribute, you can can simply check using their EntryType class, like so:

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Gate;
use Laravel\Telescope\EntryType;
use Laravel\Telescope\IncomingEntry;
use Laravel\Telescope\Telescope;
use Laravel\Telescope\TelescopeApplicationServiceProvider;

class TelescopeServiceProvider extends TelescopeApplicationServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        Telescope::night();

        $this->hideSensitiveRequestDetails();

        Telescope::filter(function (IncomingEntry $entry) {
            if ($this->app->isLocal()) {
                return true;
            }

            return $entry->isReportableException() ||
                   $entry->isFailedRequest() ||
                   $entry->isFailedJob() ||
                   $entry->isScheduledTask() ||
                   $entry->type === EntryType::JOB ||
                   $entry->type === EntryType::MAIL ||
                   $entry->hasMonitoredTag();
        });
    }

https://github.com/laravel/telescope/blob/3.x/src/EntryType.php

Activity icon

Replied to Where Do I Add Custom.css In Webpack?

@aron-spiess If you want it as it's own file, and not in app.css, you can append another .sass()

mix.js("resources/js/app.js", "public/js/app.js")
    .sass("resources/sass/app.scss", "public/css/app.css")
    .sass("resources/sass/tailwind.scss", "public/css/tailwind.css")
    .sourceMaps();

If you want it included within app.css, then open app.scss and add the import to wherever your tailwind scss file is

@import "tailwind";
Activity icon

Replied to Laravel Broadcasting Private Channel “Client Can Not Be Authenticated, Got HTTP Status 500”

First, the second error you got was because you hard coded the ID, but expect a a param still.

Broadcast::channel('order.{id}', function ($user, int $id) {
    return true;
});

Second, when you had type hinted User, did you put the USE at the top of your channels file to point to the correct user model?

use App\Models\Auth\User\User;


Broadcast::channel('order.{id}', function (User $user, int $id) {
    // this is for testing purpose as everyone is authenticated to listen to this channel
    return true;
});

If it still tries to pass the base App\User (may be that gates, policies etc auto inject that model), you may need to look into how to rebind your user model globally

**editing to add, I assume your user model is correct under the providers in config/auth.php?

'providers' => [
    'users' => [
        'driver' => 'eloquent',
        'model' => App\Models\Auth\User::class,
    ],
],
Activity icon

Replied to Laravel Broadcasting Private Channel “Client Can Not Be Authenticated, Got HTTP Status 500”

@evacch When you declare your channel, and you type hint User, is there a reason it is pointing to App\Models\Auth\User\User? Is that your main user model? By default, I think laravel always binds the regular App\User to the channel closure. Try removing the type hint for now and dump what $user it is injecting to find out.

Jul
23
4 months ago
Activity icon

Replied to Make Shorter Access Token Laravel Passport

@nithapple They are that long for a reason. It is an encoding of headers, payload and signature. When parsed, your code is:

{
  "aud": "5",
  "jti": "024ace4d06c3b5b0e7e8137d1e5f49b2e66140a6b7cf60686e7409cf918e7d379752f27318a9f4b7",
  "iat": 1595564008,
  "nbf": 1595564008,
  "exp": 1627100008,
  "sub": "1",
  "scopes": []
}

This tells passport what access token ID to compare it to (jti), and other relevant data. Learn more at: https://jwt.io/

Activity icon

Replied to How To Reverse The Notification Class/migration

@webfuelcode If you rename a notification class, you have to restart your worker/queue, as any code changes have to be respawned into the worker memory. Also, a good go to anytime you have class not found issues outside of the queue, is to clear your bootstrap/cache folder and run w.e commands you use for cache (config:cache, routes:cache, etc). Also, check your spelling, usually it is "Notifications" with a capitol, not "notifications" directory.

Activity icon

Awarded Best Reply on How Does Passport's "Consuming Your API With JavaScript" Work ?

@cristimocean So when you use the CreateFreshApiToken, behind the scenes, passport put's it into the request as a token, just like the regular Client or Token models, however, it uses the TransientToken model, parading around with full access. If you want to limit what these can do within your API, one thing I have done is create a middleware that simply checks if the token on the request is transient. If it is, I know the request is coming from web, and I can limit it based on that. As for adding scopes, it is a "virtual" token, so that is not directly possible to my knowledge.

https://github.com/laravel/passport/blob/9.x/src/TransientToken.php

As an example, assuming you put this middleware within an auth group, you can try this:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Laravel\Passport\Token;
use Laravel\Passport\TransientToken;
use Symfony\Component\HttpKernel\Exception\HttpException;

class DenyTransientToken
{
    /**
     * Handle an incoming request.
     *
     * @param  Request  $request
     * @param  Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        /* @var $token Token|TransientToken */

        $token = $request->user()->token();

        if($token && $token->transient())
        {
            throw new HttpException(403, "Unauthorized");
        }

        return $next($request);
    }
}
Jul
22
4 months ago
Activity icon

Replied to How Does Passport's "Consuming Your API With JavaScript" Work ?

@cristimocean So when you use the CreateFreshApiToken, behind the scenes, passport put's it into the request as a token, just like the regular Client or Token models, however, it uses the TransientToken model, parading around with full access. If you want to limit what these can do within your API, one thing I have done is create a middleware that simply checks if the token on the request is transient. If it is, I know the request is coming from web, and I can limit it based on that. As for adding scopes, it is a "virtual" token, so that is not directly possible to my knowledge.

https://github.com/laravel/passport/blob/9.x/src/TransientToken.php

As an example, assuming you put this middleware within an auth group, you can try this:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Laravel\Passport\Token;
use Laravel\Passport\TransientToken;
use Symfony\Component\HttpKernel\Exception\HttpException;

class DenyTransientToken
{
    /**
     * Handle an incoming request.
     *
     * @param  Request  $request
     * @param  Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        /* @var $token Token|TransientToken */

        $token = $request->user()->token();

        if($token && $token->transient())
        {
            throw new HttpException(403, "Unauthorized");
        }

        return $next($request);
    }
}
Activity icon

Replied to POST Method Not Supported Here

If you are using axios, the CSRF token is automatically added to it's headers, assuming you have the default laravel bootstrap.js file. You can also set the CSRF meta attribute in the head section of your html, and in your JS under where axios is imported, you can add:

let token = document.head.querySelector('meta[name="csrf-token"]');
window.Laravel = { csrfToken: token.content };
window.axios = require('axios');
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
Activity icon

Replied to True Or False: Use `\collect()` Over `collect()` - It Is Slightly More Performant.

Personally I never add the preceding slash. My two thoughts on the matter...readability, and all that does is put it in the global namespace, but any of laravel helpers are already connecting and resolving directly to the service container, and helpers are auto loaded by composer. As to the technical side of your question, I have not directly tested "performance" of that.

Activity icon

Replied to POST Method Not Supported Here

Keep in mind resource routes mean the method names themselves are not part of the URL. Rather, /salutations/{salutation} where {salutation} is the ID of the salutation, as laravel can bind the model to the route if you type hint in your controller method. To post delete from a form on the frontend without using javascript, you can add the following to your form:

<form action="/salutations/{{ $salutation->id }}" method="POST">
    @method('DELETE')
</form>

If you are using javascript, such as axios, you can instead call

axios.delete('/salutations/{someID}')

Definitely check out the docs section for resource controllers, they do also list how the URI's are mapped by default https://laravel.com/docs/7.x/controllers#resource-controllers

Activity icon

Awarded Best Reply on POST Method Not Supported Here

@maltekiefer the store method is mapped to posting right to /salutations. Then GET on /salutations/{salutation} would be the show method, etc

Activity icon

Replied to POST Method Not Supported Here

@maltekiefer the store method is mapped to posting right to /salutations. Then GET on /salutations/{salutation} would be the show method, etc

Activity icon

Awarded Best Reply on Accessing BearerToken Details

@dan1234827 Whenever a user is authed on a request using a token, instead of grabbing the bearer token, laravel binds it to the token() on the user for the request. Simply try: $request->user()->token()->revoke() or delete()

class ApiLogout extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | API Logout Controller
    |--------------------------------------------------------------------------
    |
    | This logs out the authenticated user from the api and revokes token
    |
    */

    /**
     * ApiLogout constructor.
     */
    public function __construct()
    {
        $this->middleware('auth:api');
    }

    /**
     * Handle the incoming logout request.
     *
     * @param Request $request
     * @return JsonResponse
     * @throws Exception
     */
    public function __invoke(Request $request)
    {
        /* @var $token Token|TransientToken */

        $token = $request->user()->token();

        if(!$token->transient())
        {
            $token->revoke();
            
            //$token->delete();

            return new JsonResponse([
                'message' => 'Logged out'
            ]);
        }

        throw new HttpException(403, 'Unauthorized to perform that action.');
    }
}
Activity icon

Replied to Accessing BearerToken Details

@dan1234827 Whenever a user is authed on a request using a token, instead of grabbing the bearer token, laravel binds it to the token() on the user for the request. Simply try: $request->user()->token()->revoke() or delete()

class ApiLogout extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | API Logout Controller
    |--------------------------------------------------------------------------
    |
    | This logs out the authenticated user from the api and revokes token
    |
    */

    /**
     * ApiLogout constructor.
     */
    public function __construct()
    {
        $this->middleware('auth:api');
    }

    /**
     * Handle the incoming logout request.
     *
     * @param Request $request
     * @return JsonResponse
     * @throws Exception
     */
    public function __invoke(Request $request)
    {
        /* @var $token Token|TransientToken */

        $token = $request->user()->token();

        if(!$token->transient())
        {
            $token->revoke();
            
            //$token->delete();

            return new JsonResponse([
                'message' => 'Logged out'
            ]);
        }

        throw new HttpException(403, 'Unauthorized to perform that action.');
    }
}
Jul
17
4 months ago
Activity icon

Awarded Best Reply on Unable To Listen To Laravel Echo Private Channel

@codebullet I believe it is because your event is being broadcasted with the full namespace. Unless you configure the namespace in laravel echo, I find it easier to add the broadcast as method on the event to rename what it calls itself. Then be sure to prefix the event name you listen for in echo with a ' . ' dot

PrivateChatEvent

public function broadcastAs()
{
    return 'private-chat-event';
}

Vue

        created() {
            Echo.private(`Chat.${this.friend.session.id}`).listen(
                ".private-chat-event",
                (e) => {
                    console.log(e)

                }
            );
Activity icon

Replied to Unable To Listen To Laravel Echo Private Channel

@codebullet I believe it is because your event is being broadcasted with the full namespace. Unless you configure the namespace in laravel echo, I find it easier to add the broadcast as method on the event to rename what it calls itself. Then be sure to prefix the event name you listen for in echo with a ' . ' dot

PrivateChatEvent

public function broadcastAs()
{
    return 'private-chat-event';
}

Vue

        created() {
            Echo.private(`Chat.${this.friend.session.id}`).listen(
                ".private-chat-event",
                (e) => {
                    console.log(e)

                }
            );
Jul
16
4 months ago
Activity icon

Replied to Adding Custom Guard To My RedirectIfAuthenticated Middleware

"Middleware parameters may be specified when defining the route by separating the middleware name and parameters with a :. Multiple parameters should be delimited by commas", thus try guest:business_user, like so -

Route::middleware(['guest:business_user'])->group(function () {
    Route::view('/business/sign-up', 'business.registration')->name('business.registration');
    Route::view('/business/login', 'business.login')->name('business.login');
});
public function handle($request, Closure $next, $guard = null)
{
    if (Auth::guard($guard)->check())
    {
        if($guard === 'business_user')
            return redirect('/business/dashboard');

        return redirect('/dashboard');
    }

    return $next($request);
}

More info here: https://laravel.com/docs/7.x/middleware#middleware-parameters

Jul
14
4 months ago
Activity icon

Replied to Can't Downgrade Jquery Version

@shami003 If your app works and npm installed, then leave it be lol. I will add that I had your issue when jquery 3.5.0 came out, but since being on jquery 3.5.1, I have had no issues and have not had to downgrade back to 3.4.1

Jul
11
4 months ago
Activity icon

Replied to Can't Downgrade Jquery Version

@shami003 Try clearing your npm cache after removing the node_modules folder, and be sure you edit the numbers again in package.json. Then npm install again

npm cache clean --force
Jul
09
4 months ago
Activity icon

Replied to Can't Downgrade Jquery Version

@shami003 Try removing your node_modules folder, and delete your package-lock.json, then change the 3.5.1 back to 3.4.1 in your package.json, then npm install again.

Activity icon

Started a new Conversation Passport Custom Login For Access Token

Just curious, when it comes to passport and password grants, I only use them for first party apps/SPA, so instead of extending the base controllers, I wanted to be able to run the logins through the regular login process, so that I may throttle request and reduce the required fields down to just username, password, and client_secret. This way I can also un-register the passport routes and use my own API route for login and refresh token.

Has anyone else done anything similar to this? By default, the oauth/token route does not limit attempts or trigger user login event, so this was my solution:

LoginController

class ApiLoginController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | API Login Controller
    |--------------------------------------------------------------------------
    |
    | This controller handles authenticating users for the application's API
    |
    */

    use AuthenticatesUsers;

    /**
     * Get the number of minutes to throttle for.
     *
     * @var int
     */
    protected $decayMinutes = 5;

    /**
     * Get the maximum number of attempts to allow.
     *
     * @var int
     */
    protected $maxAttempts = 5;

    /**
     * ApiLoginController constructor.
     */
    public function __construct()
    {
        $this->middleware('guest')->except('logout');
    }

    /**
     * Handle a login request to the application.
     *
     * @param Request $request
     * @return Response|\Symfony\Component\HttpFoundation\Response|void
     * @throws ValidationException
     * @noinspection PhpVoidFunctionResultUsedInspection
     */
    public function login(Request $request)
    {
        $this->validateLogin($request);

        if ($this->hasTooManyLoginAttempts($request))
        {
            $this->fireLockoutEvent($request);

            return $this->sendLockoutResponse($request);
        }

        if ($this->attemptLogin($request))
            return $this->requestAccessToken($request);

        $this->incrementLoginAttempts($request);

        return $this->sendFailedLoginResponse($request);
    }

    /**
     * Request access token from oauth server
     *
     * @param Request $request
     * @return Response
     */
    private function requestAccessToken(Request $request)
    {
        try{
            $this->addTokenRequest($request);

            $dispatchToTokenServer = $this->tokenServer()->issueToken(
                $this->serverRequest()
            );

            $this->authenticated($request, $this->guard()->user());

            $this->clearLoginAttempts($request);

            return $dispatchToTokenServer;

        }catch (Exception $e) {
            throw new HttpException(422, $e->getMessage());
        }
    }

    /**
     * Add oauth params to request before creating server request instance
     *
     * @param Request $request
     */
    private function addTokenRequest(Request $request)
    {
        $request->request->add([
            'grant_type' => 'password',
            'client_id' => config('passport.password_grant_client.id'),
            'client_secret' => $request->input('client_secret'),
            'username' => $request->input('email'),
            'password' => $request->input('password'),
            'scope' => ''
        ]);
    }

    /**
     * Get the AccessTokenController instance
     *
     * @return Application|AccessTokenController|mixed
     */
    private function tokenServer()
    {
        return app(AccessTokenController::class);
    }

    /**
     * Get the ServerRequestInterface instance
     *
     * @return Application|mixed|ServerRequestInterface
     */
    private function serverRequest()
    {
        return app(ServerRequestInterface::class);
    }

    /**
     * Validate the user login request.
     *
     * @param Request $request
     * @return void
     *
     */
    protected function validateLogin(Request $request)
    {
        $request->validate([
            'email' => 'required|string',
            'password' => 'required|string',
            'client_secret' => 'required|string'
        ]);
    }

    /**
     * Get the needed authorization credentials from the request.
     *
     * @param Request $request
     * @return array
     */
    protected function credentials(Request $request)
    {
        return array_merge($request->only('email', 'password'), ['active' => 1]);
    }

    /**
     * Attempt to log the user into the application.
     *
     * @param Request $request
     * @return bool
     */
    protected function attemptLogin(Request $request)
    {
        return $this->guard()->once($this->credentials($request));
    }

    /**
     * Fire the logged in event
     *
     * @param Request $request
     * @param Authenticatable|User $user
     */
    protected function authenticated(Request $request, User $user)
    {
        event(new NewLogin($user, $request->ip()));
    }
}
Activity icon

Replied to Can't Downgrade Jquery Version

@shami003 Remove the carrot to force it to stay on one version.

"dependencies": {
        "admin-lte": "^3.0.5",
        "jquery": "3.4.1"
    }