Tippin

Member Since 1 Year Ago

TAMPA

Experience Points
35,650
Total
Experience

4,350 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
51
Lessons
Completed
Best Reply Awards
50
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.

  • Community Pillar

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

Level 8
35,650 XP
Jun
10
2 days ago
Activity icon

Replied to Create Route Not Found Error, Resource Route Availble

Rule of thumb: When developing locally, you never cache any framework items. These include config, routes, views, events, and more. You can always run php artisan optimize:clear to clear most of them in one easy command.

Deployment side however, it is common to have the end part of your deployment automate the command php artisan optimize so it creates a fresh cache of configs, routes, and views.

One other side note, if you use queues at all, then any code changes, including routes, means you need to restart your queue worker / service to reflect new code.

Activity icon

Awarded Best Reply on Create Route Not Found Error, Resource Route Availble

That seems ok assuming you are using the older routing standards (newer one imports controller classes directly and ditches namespace on the route definitions)

By chance are you sure your routes are not cached? php artisan route:clear

Edit: If you php artisan route:list do you see that route anywhere? Possibly under a different prefix or something?

Activity icon

Replied to Create Route Not Found Error, Resource Route Availble

That seems ok assuming you are using the older routing standards (newer one imports controller classes directly and ditches namespace on the route definitions)

By chance are you sure your routes are not cached? php artisan route:clear

Edit: If you php artisan route:list do you see that route anywhere? Possibly under a different prefix or something?

Activity icon

Replied to Create Route Not Found Error, Resource Route Availble

@rhand Your route name you call to is admin.reseller-sales.create and you say it is in a route group that is prefixed admin...but did you ALSO name the prefix?

Route::prefix('admin')->name('admin.')->group(function () {
    Route::resource('reseller-sales', 'ResellerSalesController');
}):
Activity icon

Replied to Laravel-Websockets And WebRTC RTCPeerConnection

I do not make videos, sorry. I would say most media servers will require a bit of setup, and if that does not sound like something you want to manage, you can always use a 3rd party provider like Twillio, BigBlueButton, and more. Have you tried looking up other youtube videos for how to install and setup janus?

Currently my buddy keeps a docker image updated and all I have to do is deploy the image, but it requires you know a bit about docker. Example (not up to date but works): https://github.com/ajnozari/janus-gateway

In my demo, I just have a janus docker node setup from within portainer https://www.portainer.io/

Backend wise for how I create and destroy rooms through the janus API, you can find my PHP wrapper here: https://github.com/RTippin/messenger/tree/master/src/Services/Janus

Jun
08
4 days ago
Activity icon

Replied to Trying \Artisan::queue() And Getting ReflectionException

@thebham That class was last in the framework at v5.3

https://github.com/laravel/framework/blob/5.3/src/Illuminate/Foundation/Console/QueuedJob.php

It is now:

https://github.com/laravel/framework/blob/8.x/src/Illuminate/Foundation/Console/QueuedCommand.php

Did you recently upgrade? Perhaps you need to clear the compiled files in your bootstrap/cache directory, mainly services.php and packages.php

Activity icon

Replied to About Chunk Method

Not what I said. Chunk is extremely useful, but not what you use on your frontend. You should never be doing DB queries inside your views, so you only send it the data it needs. You can easily paginate your model and iterate over the collection you send to the view from pagination.

Real world example of chunk: Imagine you wanted to check your database for all users who have not verified their email yet, and send them a reminder email. Well, imagine you did this:

User::whereNull('email_verified_at')->get()->each(fn (User $user) => $user->notify(new RemindVerifyEmail()));

You may load 1 user, or 10 thousand. So to better memory performance, you could instead:

User::whereNull('email_verified_at')->chunk(100, fn (Collection $users) => $this->sendEmails($users));

private function sendEmails(Collection $users) : void
{
    $users->each(fn (User $user) => $user->notify(new RemindVerifyEmail()));
}

Thus you only ever load 100 into memory at a time, and such an operation usually is run from within a command, job, etc.

Activity icon

Replied to About Chunk Method

@asadali007 You do not chunk in blade. Usually you only grab a select number of records, or paginate, and send that data to your view. Chunking is more useful on the backend when you need to iterate over large data sets for some operation, often mass updating records or sending batches into jobs, where you do not want to load all records into memory at once.

Activity icon

Replied to Injecting Request In The Controller's Constructor With Laravel 8 ?

@duddy67 Unless you plan to use request for every single method in the controller, it is usually better to inject it in only the methods you plan to use it. The container will also inject any dependencies you typehint in your controller methods that are called via a route, on top of route params you may have.

class UserController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth');
    }


    public function store(Request $request)
    {
        $request->validate([
                 'name' => 'bail|required|between:5,25|regex:/^[\pL\s\-]+$/u',
                 'email' => 'bail', 'required', 'email'
        ]);
        $request->session()->flash('success', 'The user has been successfully created.');

        // ...
    }
}
Jun
06
6 days ago
Activity icon

Replied to DispatchNow For Events ?

@untymage I do not think there is an easy way to go about it from a queued listener directly. I used a different approach myself, using event subscribers

https://laravel.com/docs/8.x/events#event-subscribers

Instead of having queued listeners, I instead setup the subscriber to listen for events, and within that same class when a method is called to handle an event, I instead rely on a config and dispatch a job inside those methods. Depending on my config (which can be set at runtime during any point before the event would be fired), I dispatch or dispatch sync. Example of what I do in my subscriber (register subscriber first in your event service provider):

Subscriber

class BotSubscriber
{
    /**
     * Register the listeners for the subscriber.
     *
     * @param Dispatcher $events
     * @return void
     */
    public function subscribe(Dispatcher $events): void
    {
        $events->listen(NewMessageEvent::class, [BotSubscriber::class, 'newMessage']);
    }

    /**
     * @param NewMessageEvent $event
     */
    public function newMessage(NewMessageEvent $event): void
    {
        Messenger::getBotSubscriber('queued')
            ? BotActionHandler::dispatch($event)->onQueue('bots')
            : BotActionHandler::dispatchSync($event);
    }
}
May
16
3 weeks ago
Activity icon

Replied to Trying To Access Relationship But Property [services] Does Not Exist On This Collection Instance

$jobs = Job::get(); Is giving you a collection of jobs, not a single job.

You either want to locate a single job (and can eagerload relationship):

$job = Job::with('jobLineItems.services')->find($id);
$job->jobLineItems->services;

With your current method, you would need to iterate over the collection:

$jobs = Job::get();
$jobs->each(function($job) {
    $job->jobLineItems->services;
});

Also usually not wise to ever query using all() / get() without constraints...if you have 50k jobs, well you just loaded 50k job models into memory.

Activity icon

Replied to How To Implement The Internal Chat System In Laravel?

You can checkout this thread where I gave examples of projects you can look at, including my own:

https://laracasts.com/discuss/channels/laravel/suggestion-on-how-to-build-real-time-chat?page=1#reply=698333

I would suggest checking out examples/packages to see how you may want to structure your database. My package does allow multiple models to message one another, but you would have to add in extra policies to allow an admin to monitor all chats. Of course chat/messages does not have to be realtime, but you can still structure your database based on the examples linked above.

May
12
1 month ago
Activity icon

Replied to Telescope Dashboard: Only Show Requests To User

Well if using in production, you will need to edit the service provider it published, and edit the filtered to just return true so it does not only give failed request/jobs etc. See: https://laravel.com/docs/8.x/telescope#filtering

Config wise, look at your telescope config file. Each watcher is enabled by default. You can set ENV keys for those to false except request. See: https://github.com/laravel/telescope/blob/4.x/config/telescope.php#L117

Now not sure I fully understand the depth of your question, but if you are trying to have all watchers going but only let certain users view different sections in the telescope dashboard, that is simply not possible with telescope alone. Firstly, either a watcher is on or off. Gate access wise, their entire API / controllers are protected via one single gate, not per section / watcher. You would have to fork the telescope package and add in custom authorization to each of their controllers if that is the case you want.

May
06
1 month ago
Activity icon

Replied to I'm Trying To Make A Messenger, And I Use Git Hub Project, But I Have A Error "Class 'Redis' Not Found"

I see you found my demo repository :)

Please check the prerequisites : https://github.com/RTippin/messenger-demo#prerequisites

By default, my demo package is setup to use socketio / laravel echo server / and PHP redis for REDIS, which you will have to install that module for your php here: https://github.com/phpredis/phpredis/blob/develop/INSTALL.markdown

You may also just install the base package itself into an existing laravel app and configure all aspects accordingly (demo is the most basic setup that I use to show it off)

https://github.com/RTippin/messenger

May
03
1 month ago
Activity icon

Awarded Best Reply on ErrorException : Unparenthesized `a ? B : C ? D : E` Is Deprecated

You are using a package that has not been touched since 2017. Assuming you recently upgraded to php 7.4 or 8, the multi ternary needs to now be wrapped in parentheses. See :

https://github.com/themsaid/laravel-langman/blob/master/src/Commands/FindCommand.php#L113

https://github.com/themsaid/laravel-langman/issues/96

https://wiki.php.net/rfc/ternary_associativity

Activity icon

Replied to ErrorException : Unparenthesized `a ? B : C ? D : E` Is Deprecated

You are using a package that has not been touched since 2017. Assuming you recently upgraded to php 7.4 or 8, the multi ternary needs to now be wrapped in parentheses. See :

https://github.com/themsaid/laravel-langman/blob/master/src/Commands/FindCommand.php#L113

https://github.com/themsaid/laravel-langman/issues/96

https://wiki.php.net/rfc/ternary_associativity

Apr
09
2 months ago
Activity icon

Awarded Best Reply on Mocking A Class With New'ed Up Class Inline

With your current code, that controller depends on that dependency, which is not the best design. You would have to test the activate class directly and not the full http test.

Could you not instead inject the activate user into the constructor, but leave the userID out, instead using a setter.

<?php

namespace App\Http;

use App\Exceptions\AccountIsAlreadyActiveException;
use App\Exceptions\CannotActivateUserException;
use Exception;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Http\Response;
use Helper\ActivateUser;

/**
 * Class ActivateUser
 *
 * @package App\Http
 */
class ActivateUser
{
    private ActivateUser $activate;

    /**
     * ActivateUser constructor.
     *
     * @param ActivateUser $activate
     */
    public function __construct(ActivateUser $activate)
    {
        $this->activate = $activate;
    }

    /**
     * @param string $userId
     *
     * @return string
     * @throws \App\Exceptions\AccountIsAlreadyActiveException
     */
    public function activate(string $userId): string
    {
        try {
            // pass a request to external api to activate the account.
            return $this->activate->activate($userId);

        } catch (GuzzleException | Exception $exception) {

            if($exception->getCode() == Response::HTTP_FORBIDDEN) {
                throw new AccountIsAlreadyActiveException($exception->getMessage());
            }
        }
    }
}

Then either in your HTTP test add a mock for the activate user, or when testing the class directly. Also, any reason it is not an invokable controller, since it has one method?

Apr
03
2 months ago
Activity icon

Awarded Best Reply on Laravel Horizon Configuration Options

@nahomt A good place would be to checkout the original source. You can find their main supervisor and all of the options they inject here : https://github.com/laravel/horizon/blob/5.x/src/SupervisorOptions.php

From there if you have further questions, I would go through their issues searching for terms you may not understand, as many will have answered responses.

Apr
02
2 months ago
Activity icon

Replied to Laravel Horizon Configuration Options

@nahomt A good place would be to checkout the original source. You can find their main supervisor and all of the options they inject here : https://github.com/laravel/horizon/blob/5.x/src/SupervisorOptions.php

From there if you have further questions, I would go through their issues searching for terms you may not understand, as many will have answered responses.

Mar
30
2 months ago
Activity icon

Replied to Seconds To Humantime

@rafaeladi You never replied back, did you solve this issue? Seems you did looking at your recent post.

Mar
28
2 months ago
Activity icon

Replied to Laravel Echo For Multiple Channels?

@thinkerytim Why not just make a single private channel per user, user.{userId}, add all events it may listen for on your frontend, such as your CalendarEventCreated.

On your backend, when you emit that event for a given calendar, broadcast to the users private channel whose calendar it is for, and emitting valuable data like the calendar model, or some way your frontend can differentiate between different calendar IDs.

Basically no matter the calendar, backend should broadcast the event to the same private user channel. Frontend wise, each event you listen for is almost like a router, where you can see calendar ID and know what to do next (maybe ID not loaded in view yet, lets load it, or perhaps calendar is in view, lets update it).

Mar
22
2 months ago
Activity icon

Replied to Protect API Calls

Sanctum or passport would both be a good fit. If you do not need to worry about authenticating 3rd parties, then use sanctum. I am not sure I understand what you are currently doing, but it sounds all types of wrong.

https://laravel.com/docs/8.x/sanctum

https://laravel.com/docs/8.x/passport

Activity icon

Replied to Suggestion On How To Build Real Time Chat?

@nickywan123

Thanks, so the messenger that you're working is open source right?

Yes, it is open source. Fork it, use it, do as you please with it.

Would you recommend it as stable for the current version it's released?

It is stable in that it works and I have it being used on multiple projects, and have over 1k passing tests. However, it is pre-release, so I may add new features or version breaking changes rather often until I reach v1.

Of course you do not have to use my or anyone's package, but simply use them as references / guides to build your own!

Mar
21
2 months ago
Activity icon

Replied to Suggestion On How To Build Real Time Chat?

Alternative to pusher would be to install your own socket.io, or packages such as:

Chat packages or references:

Messenger I am working on: https://github.com/RTippin/messenger

You can basically choose to go the livewire approach if you do not need instant realtime and do not mind polling, or use any websocket implementation and get your feet wet in the https://laravel.com/docs/8.x/broadcasting

Realtime or not, I prefer my base database setup of threads participants and messages tables, as it makes it rather easy to store what you need and relate messages to a thread whether private or group, while being able to broadcast to any participants within a thread without worrying about who a single message is being sent to (I like to think of a message as alerting all participants in a thread, not directly to a single user)

Mar
16
2 months ago
Activity icon

Replied to Seconds To Humantime

Well before you send the data to your view from your controller, you can transform a collection and replace values. Then you send the new collection to your view so all you need to do is loop through them in your view. Checkout: https://laravel.com/docs/8.x/collections#method-transform

Activity icon

Replied to Seconds To Humantime

Well, if you want to go the helper route (not what I would do, but may work for you), check this out: https://laravel-news.com/creating-helpers

Then you can call your humanTime(), but give it a parameter. What you posted above was a method that does not accept any value, so not sure how you intend to feed it data.

Activity icon

Replied to Seconds To Humantime

Seems like you are going about this in the wrong way. Your humanTime() method as far as I can tell does not even return anything. Second, unless you make that a global helper, you can't just access humanTime() in blade. You should really be transforming your collection in the controller, modify the times there, and send the formatted data back to your view.

Activity icon

Replied to Seconds To Humantime

Can you please share more of your code? Not giving me much to go off of here. My initial response with carbon works just fine, I tested it myself.

Activity icon

Replied to Seconds To Humantime

Whatever makes life easiest for you and reads best. No issue with using that in a single method in the controller. If you use that carbon method in multiple methods within one controller, then sure, you can make a private method in the controller to save yourself repeating the carbon code.

Activity icon

Replied to Seconds To Humantime

use use Carbon\CarbonInterval;

$seconds = 6700;
$time = CarbonInterval::seconds($seconds)->cascade()->forHumans();
dump($time); //1 hour 51 minutes 40 seconds
Mar
07
3 months ago
Activity icon

Awarded Best Reply on How To Create API Login Attempts

@nakov Only issue with using limiter as middleware for the logins means failed or not, it counts towards the limit, where you may only want to increment attempts on fail.

@jvbalcita So what I ended up doing was basically copying what the base login controller (OG/UI) did using the rate limiter into a trait to use in my api login (though I use passport).

Trait

<?php

namespace App\Http\Controllers\Auth\Concerns;

use Illuminate\Auth\Events\Lockout;
use Illuminate\Cache\RateLimiter;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Lang;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;

trait ThrottlesAttempts
{
    /**
     * Determine if the user has too many failed login attempts.
     *
     * @param Request $request
     * @return bool
     */
    protected function hasTooManyAttempts(Request $request): bool
    {
        return $this->limiter()->tooManyAttempts(
            $this->throttleKey($request), $this->maxAttempts()
        );
    }

    /**
     * Increment the login attempts for the user.
     *
     * @param Request $request
     * @return void
     */
    protected function incrementAttempts(Request $request): void
    {
        $this->limiter()->hit(
            $this->throttleKey($request), $this->decayMinutes() * 60
        );
    }

    /**
     * Redirect the user after determining they are locked out.
     *
     * @param Request $request
     * @return void
     * @throws ValidationException
     */
    protected function sendLockoutResponse(Request $request): void
    {
        $seconds = $this->limiter()->availableIn(
            $this->throttleKey($request)
        );

        throw ValidationException::withMessages([
            $this->throttleKeyName() => [Lang::get('auth.throttle', [
                'seconds' => $seconds,
                'minutes' => ceil($seconds / 60),
            ])],
        ])->status(Response::HTTP_TOO_MANY_REQUESTS);
    }

    /**
     * Clear the login locks for the given user credentials.
     *
     * @param Request $request
     * @return void
     */
    protected function clearAttempts(Request $request): void
    {
        $this->limiter()->clear($this->throttleKey($request));
    }

    /**
     * Fire an event when a lockout occurs.
     *
     * @param Request $request
     * @return void
     */
    protected function fireLockoutEvent(Request $request): void
    {
        event(new Lockout($request));
    }

    /**
     * Get the throttle key for the given request.
     *
     * @param Request $request
     * @return string
     */
    protected function throttleKey(Request $request): string
    {
        return Str::lower($request->input($this->throttleKeyName())).'|'.$request->ip();
    }

    /**
     * Get the rate limiter instance.
     *
     * @return RateLimiter
     */
    protected function limiter(): RateLimiter
    {
        return app(RateLimiter::class);
    }

    /**
     * Get the maximum number of attempts to allow.
     *
     * @return int
     */
    public function maxAttempts(): int
    {
        return property_exists($this, 'maxAttempts')
            ? $this->maxAttempts
            : 5;
    }

    /**
     * Get the number of minutes to throttle for.
     *
     * @return int
     */
    public function decayMinutes(): int
    {
        return property_exists($this, 'decayMinutes')
            ? $this->decayMinutes
            : 1;
    }

    /**
     * Get the key used to throttle request
     *
     * @return string
     */
    public function throttleKeyName(): string
    {
        return property_exists($this, 'throttleKeyName')
            ? $this->throttleKeyName
            : 'email';
    }
}

Controller

use ThrottlesAttempts;


class ApiLogin extends Controller
{
    /**
     * Handle a login request to the application.
     */
    public function login(Request $request)
    {
        if($this->hasTooManyAttempts($request))
        {
            return $this->sendLockoutResponse($request);
        }

        if (!Auth::attempt($credentials)) {
            $this->incrementAttempts($request);

            return response()->json([
                'status_code' => 401,
                'message' => 'Unauthorized'
            ]);
        }
        //auth attempt good

        $this->clearAttempts($request);

        //w.e else you do
    }
Activity icon

Replied to How To Create API Login Attempts

@nakov Only issue with using limiter as middleware for the logins means failed or not, it counts towards the limit, where you may only want to increment attempts on fail.

@jvbalcita So what I ended up doing was basically copying what the base login controller (OG/UI) did using the rate limiter into a trait to use in my api login (though I use passport).

Trait

<?php

namespace App\Http\Controllers\Auth\Concerns;

use Illuminate\Auth\Events\Lockout;
use Illuminate\Cache\RateLimiter;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Lang;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;

trait ThrottlesAttempts
{
    /**
     * Determine if the user has too many failed login attempts.
     *
     * @param Request $request
     * @return bool
     */
    protected function hasTooManyAttempts(Request $request): bool
    {
        return $this->limiter()->tooManyAttempts(
            $this->throttleKey($request), $this->maxAttempts()
        );
    }

    /**
     * Increment the login attempts for the user.
     *
     * @param Request $request
     * @return void
     */
    protected function incrementAttempts(Request $request): void
    {
        $this->limiter()->hit(
            $this->throttleKey($request), $this->decayMinutes() * 60
        );
    }

    /**
     * Redirect the user after determining they are locked out.
     *
     * @param Request $request
     * @return void
     * @throws ValidationException
     */
    protected function sendLockoutResponse(Request $request): void
    {
        $seconds = $this->limiter()->availableIn(
            $this->throttleKey($request)
        );

        throw ValidationException::withMessages([
            $this->throttleKeyName() => [Lang::get('auth.throttle', [
                'seconds' => $seconds,
                'minutes' => ceil($seconds / 60),
            ])],
        ])->status(Response::HTTP_TOO_MANY_REQUESTS);
    }

    /**
     * Clear the login locks for the given user credentials.
     *
     * @param Request $request
     * @return void
     */
    protected function clearAttempts(Request $request): void
    {
        $this->limiter()->clear($this->throttleKey($request));
    }

    /**
     * Fire an event when a lockout occurs.
     *
     * @param Request $request
     * @return void
     */
    protected function fireLockoutEvent(Request $request): void
    {
        event(new Lockout($request));
    }

    /**
     * Get the throttle key for the given request.
     *
     * @param Request $request
     * @return string
     */
    protected function throttleKey(Request $request): string
    {
        return Str::lower($request->input($this->throttleKeyName())).'|'.$request->ip();
    }

    /**
     * Get the rate limiter instance.
     *
     * @return RateLimiter
     */
    protected function limiter(): RateLimiter
    {
        return app(RateLimiter::class);
    }

    /**
     * Get the maximum number of attempts to allow.
     *
     * @return int
     */
    public function maxAttempts(): int
    {
        return property_exists($this, 'maxAttempts')
            ? $this->maxAttempts
            : 5;
    }

    /**
     * Get the number of minutes to throttle for.
     *
     * @return int
     */
    public function decayMinutes(): int
    {
        return property_exists($this, 'decayMinutes')
            ? $this->decayMinutes
            : 1;
    }

    /**
     * Get the key used to throttle request
     *
     * @return string
     */
    public function throttleKeyName(): string
    {
        return property_exists($this, 'throttleKeyName')
            ? $this->throttleKeyName
            : 'email';
    }
}

Controller

use ThrottlesAttempts;


class ApiLogin extends Controller
{
    /**
     * Handle a login request to the application.
     */
    public function login(Request $request)
    {
        if($this->hasTooManyAttempts($request))
        {
            return $this->sendLockoutResponse($request);
        }

        if (!Auth::attempt($credentials)) {
            $this->incrementAttempts($request);

            return response()->json([
                'status_code' => 401,
                'message' => 'Unauthorized'
            ]);
        }
        //auth attempt good

        $this->clearAttempts($request);

        //w.e else you do
    }
Mar
06
3 months ago
Activity icon

Replied to Chatify Not Installing

@darkros93 Check the issues and pull request, someone else seems to have had the same issue and it is due to pusher-php version. Until the maintainer releases his next version, you would have to fork the package, update composer to allow pusher 4 (they are on 5 now), then install your forked repo into your app instead.

https://github.com/munafio/chatify/pull/74

On a side note, I would not consider it production ready code. If you take a look at the source, all messages are sent over one private channel. It is up to the client side to show a message or not, but anyone watching websocket in console can see any messages sent to anyone within your app.

https://github.com/munafio/chatify/blob/master/src/Http/Controllers/MessagesController.php#L160

Mar
04
3 months ago
Activity icon

Replied to How Do You UNIT Test Your Controller?

Testing controllers to me is more feature/integration. Thus I do my http test to check validation, authorization and responses. I keep my controllers slim however, so any events or actions my controllers use are tested on their own. My "controller" test basically look more like these:

    /** @test */
    public function user_can_send_image_message()
    {
        $this->expectsEvents([
            NewMessageBroadcast::class,
            NewMessageEvent::class,
        ]);

        $this->actingAs($this->tippin);

        $this->postJson(route('api.messenger.threads.images.store', [
            'thread' => $this->private->id,
        ]), [
            'image' => UploadedFile::fake()->image('picture.jpg'),
            'temporary_id' => '123-456-789',
        ])
            ->assertSuccessful()
            ->assertJson([
                'thread_id' => $this->private->id,
                'temporary_id' => '123-456-789',
                'type' => 1,
                'type_verbose' => 'IMAGE_MESSAGE',
                'owner' => [
                    'provider_id' => $this->tippin->getKey(),
                    'provider_alias' => 'user',
                    'name' => 'Richard Tippin',
                ],
            ]);
    }

    /**
     * @test
     * @dataProvider imageValidation
     * @param $imageValue
     */
    public function send_image_message_validates_image_file($imageValue)
    {
        $this->actingAs($this->tippin);

        $this->postJson(route('api.messenger.threads.images.store', [
            'thread' => $this->private->id,
        ]), [
            'image' => $imageValue,
            'temporary_id' => '123-456-789',
        ])
            ->assertStatus(422)
            ->assertJsonValidationErrors('image');
    }

    public function imageValidation(): array
    {
        return [
            'Image cannot be empty' => [''],
            'Image cannot be integer' => [5],
            'Image cannot be null' => [null],
            'Image cannot be an array' => [[1, 2]],
            'Image cannot be a movie' => [UploadedFile::fake()->create('movie.mov', 500, 'video/quicktime')],
            'Image must be under 5mb' => [UploadedFile::fake()->create('image.jpg', 6000, 'image/jpeg')],
            'Image cannot be a pdf' => [UploadedFile::fake()->create('test.pdf', 500, 'application/pdf')],
        ];
    }
Activity icon

Awarded Best Reply on Can We Remove Default Service Providers From Laravel?

You can remove providers you do not need yes, but also be careful, something like cache you may not think you use directly, but parts of the application might.

Activity icon

Replied to Can We Remove Default Service Providers From Laravel?

You can remove providers you do not need yes, but also be careful, something like cache you may not think you use directly, but parts of the application might.

Feb
16
3 months ago
Activity icon

Replied to Mocking A Class With New'ed Up Class Inline

With your current code, that controller depends on that dependency, which is not the best design. You would have to test the activate class directly and not the full http test.

Could you not instead inject the activate user into the constructor, but leave the userID out, instead using a setter.

<?php

namespace App\Http;

use App\Exceptions\AccountIsAlreadyActiveException;
use App\Exceptions\CannotActivateUserException;
use Exception;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Http\Response;
use Helper\ActivateUser;

/**
 * Class ActivateUser
 *
 * @package App\Http
 */
class ActivateUser
{
    private ActivateUser $activate;

    /**
     * ActivateUser constructor.
     *
     * @param ActivateUser $activate
     */
    public function __construct(ActivateUser $activate)
    {
        $this->activate = $activate;
    }

    /**
     * @param string $userId
     *
     * @return string
     * @throws \App\Exceptions\AccountIsAlreadyActiveException
     */
    public function activate(string $userId): string
    {
        try {
            // pass a request to external api to activate the account.
            return $this->activate->activate($userId);

        } catch (GuzzleException | Exception $exception) {

            if($exception->getCode() == Response::HTTP_FORBIDDEN) {
                throw new AccountIsAlreadyActiveException($exception->getMessage());
            }
        }
    }
}

Then either in your HTTP test add a mock for the activate user, or when testing the class directly. Also, any reason it is not an invokable controller, since it has one method?

Feb
14
3 months ago
Activity icon

Replied to Limiting Eager Loaded Results

I use this package in my project and it works great! (Though some slow query warnings if you start using on tables with millions of rows)

Feb
11
4 months ago
Activity icon

Replied to I Cannot Start Horizon

Can you be sure you stop horizon, and clear your cache? Odd for sure

php artisan cache:clear

php artisan horizon:terminate // If using on server

Then restart horizon.

Activity icon

Replied to I Cannot Start Horizon

@blakeyman Can you double check your horizon configs under environments/defaults?

https://laravel.com/docs/8.x/horizon#environments

I think you may have a null / undefined supervisor options. Default setup looks like:

'environments' => [
    'production' => [
        'supervisor-1' => [
            'maxProcesses' => 10,
            'balanceMaxShift' => 1,
            'balanceCooldown' => 3,
        ],
    ],

    'local' => [
        'supervisor-1' => [
            'maxProcesses' => 3,
        ],
    ],
],
Activity icon

Replied to How To Access Route Model Binding In A Request Class?

@martinzeltin

    public function authorize()
    {
          return $this->route()->parameter('organization')->id === $this->user()->organization_id
    }

Or create a policy and authorize as the first action in the method.

edit: @michaloravec beat me

Feb
10
4 months ago
Activity icon

Awarded Best Reply on What's Optimal - Laravel Websockets

I may suggest taking a route I did with messaging. You could have many users following each stock. So first, you can have each user subscribe to their own private channel using their ID, such as user.stocks.{userID}

Then when each stock is updated / triggers event on your backend, you can loop through all users following a stock, and send the collection of users to a formatter, that will send the array of private channels to that event. Note pusher driver and others limit 100 channels at a time, so chunking at 100 works. So maybe you have a single broadcast event, like StockUpdated, meaning the frontend only needs to listen for a single event. The data you send inside the event can contain the relevant info as to what stock it pertains to.

As an example when formatting channels, say you get the collection of all users following a single stock. Loop through and transform them into private channel format, example matching the channel I listed above:

public function generateChannel(User $User){
	return "private-user.stocks.{$user->getKey()}";
}

Then chunk your new collection to 100, and on the each, send your broadcast() out. Just be sure to inject the channels yourself into the event.

    public function broadcastOn()
    {
        return $this->channels;
    }
Feb
09
4 months ago
Activity icon

Awarded Best Reply on Laravel Custom Rules

Within an array:

'password' => ['required', 'confirmed', new CustomPasswordRule],
Activity icon

Replied to Laravel Custom Rules

Within an array:

'password' => ['required', 'confirmed', new CustomPasswordRule],
Activity icon

Replied to What's Optimal - Laravel Websockets

Would that mean if I have for example 101 users listening to stock price, would that require me to send 2 events with a batch of 100 channels in the first and 1 in the second?

Yes, as an example, broadcast(new StockUpdated($channels, $data)) would be run twice, first with array of 100 channels, and again with array of one channel.

With that said, if I want realtime data from stocks that aren't in my holdings/watchlist, would it make sense to have maybe something like a presence channel, to subscribe/unsubscribe to the stocks I'm currently viewing from the client?

I would think this is an acceptable approach. I imagine it being like scrolling through a facebook feed. As post come into view, it "attaches" to them and lets you see realtime someone writing a comment or otherwise. Though not sure how many at once you may want to subscribe to.

As far as how I format / chunk / broadcast stuff between presence and private channels, you can have a look at my broadcast class for reference: BroadcastBroker

Activity icon

Replied to What's Optimal - Laravel Websockets

I may suggest taking a route I did with messaging. You could have many users following each stock. So first, you can have each user subscribe to their own private channel using their ID, such as user.stocks.{userID}

Then when each stock is updated / triggers event on your backend, you can loop through all users following a stock, and send the collection of users to a formatter, that will send the array of private channels to that event. Note pusher driver and others limit 100 channels at a time, so chunking at 100 works. So maybe you have a single broadcast event, like StockUpdated, meaning the frontend only needs to listen for a single event. The data you send inside the event can contain the relevant info as to what stock it pertains to.

As an example when formatting channels, say you get the collection of all users following a single stock. Loop through and transform them into private channel format, example matching the channel I listed above:

public function generateChannel(User $User){
	return "private-user.stocks.{$user->getKey()}";
}

Then chunk your new collection to 100, and on the each, send your broadcast() out. Just be sure to inject the channels yourself into the event.

    public function broadcastOn()
    {
        return $this->channels;
    }
Feb
07
4 months ago
Activity icon

Replied to How To Make A Test For Image File?

I will add that upload tests work well not only for testing validation (http tests), but I like testing that my custom file service will stick a given file in the correct directory, along with renaming the file in the process.

But to your main point, I agree you still need to test "for real" to truly know your code does what it should when it comes to uploads.

Feb
05
4 months ago
Activity icon

Replied to Running Cashier's Unit Tests

I am not 100% on this, but I think depending on your composers 'minimum stability' among other settings may decide whether it pulls in full src, or "optimized as defined by author".

I do know I made my own package following laravels own package configs as a guide. My package does indeed ignore tests folder when I just require it in my laravel app. (I am still semi new to how all of this works myself)