xtremer360

xtremer360

Full Stack Developer at 321

Member Since 5 Years Ago

Kissimmee, FL

Experience Points
156,385
Total
Experience

3,615 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
1200
Lessons
Completed
Best Reply Awards
9
Best Reply
Awards
  • start-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-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-token Created with Sketch.

    Subscriber

    Earned if you are a paying Laracasts subscriber.

  • lifer-token Created with Sketch.

    Lifer

    Earned if you have a lifetime subscription to Laracasts.

  • lara-evanghelist 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 32
156,385 XP
Jan
20
1 day ago
Activity icon

Commented on Tips For Simplifying Laravel Controllers

What is everyone’s thoughts on doing Route::view() when only returning a view from a route that was it removes the need for a controller?

Jan
15
6 days ago
Activity icon

Replied to PHP CS FIxer

Actually I found out that it was another extentsion that somehow got set to auto sort imports on save.

Activity icon

Replied to PHP CS FIxer

Thanks for your reply. I have it working so that when I use the extension to format the document it works according to the rules I’ve set, however I have the Format on Save option checked in the extension settings and it’s not going by the same rules

Activity icon

Started a new Conversation PHP CS FIxer

I'm trying to get php cs fixer plugin set kup properly for Visual Studio Code. I came across the a .php_cs.laravel.php file that is used for Laravel Shift for fixing common problems with their Laravel projects.

Should I place the .php_cs.laravel.php inside of my project files or place it inside of the .vscode directory as a global file. The reason why I ask is because I want to be able to use the same file for all of my Laravel specific projects.

https://gist.github.com/laravel-shift/cab527923ed2a109dda047b97d53c200

Jan
14
1 week ago
Activity icon

Started a new Conversation Different Formats For Accessor

Currently the code below all works as expected, however, I was curious if anyone notices any possible flaws and what they might suggest doing differently.

I'll go through and explain what each class is doing.

I'm using Spatie's Model View package and put together a class to send through either a new manager or a specific instance. When its passing in a new instance then it will essentially pass in null for the the started_at property since we are creating a new model. If we are passing in a specific instance then we need to call the started_at accessor to see if the manager has any employments and if so then grab the first one if not then it should return null meaning we are editing a manager that was saved but didn't have an employment declared when originally creating the manager. When displaying the started_at property on the manager form I want it to display as a datetime string.

Below I also have a datatable class from using Yajra's laravel-datatables package. When I retrieve all managers with an employment and l am editing the startd_at field so that it can format how the field displays, I am displaying it as a date string without the time.

With having to use the optional helper method in multiple places is there a better way?

<?php

namespace App\ViewModels;

use App\Models\Manager;
use Spatie\ViewModels\ViewModel;

class ManagerViewModel extends ViewModel
{
    /** @var $manager */
    public $manager;

    /**
     * Undocumented function
     *
     * @param App\Models\Manager $manager
     */
    public function __construct(Manager $manager = null)
    {
        $this->manager = $manager ?? new Manager;
        $this->manager->started_at = optional($this->manager->started_at ?? null)->toDateTimeString();
    }
}
<?php

namespace App\DataTables;

use App\Models\Manager;
use App\Filters\ManagerFilters;
use Yajra\DataTables\Services\DataTable;

class ManagersDataTable extends DataTable
{
    /**
     * Build DataTable class.
     *
     * @param mixed $query Results from query() method.
     * @return \Yajra\DataTables\DataTableAbstract
     */
    public function dataTable($query)
    {
        return datatables($query)
            ->editColumn('started_at', function (Manager $manager) {
                return $manager->started_at->toDateString();
            })
    }
}
<?php

namespace App\Models\Concerns;

use App\Models\Employment;

trait CanBeEmployed
{
    /**
     * Get all of the employments of the model.
     *
     * @return \Illuminate\Database\Eloquent\Relations\MorphMany
     */
    public function employments()
    {
        return $this->morphMany(Employment::class, 'employable');
    }

    /**
     * Get the model's first employment date.
     *
     * @return string|null
     */
    public function getStartedAtAttribute()
    {
        return optional($this->employments->first())->started_at;
    }
}

Activity icon

Replied to Yajra Datatables Query Method Being Compatible Error

@nakov I had to install yajra/laravel-datatables-buttons which I wasn't aware of as well.

Activity icon

Replied to Refactoring Controller Update Method

Anyone have any additional suggestions?

Jan
13
1 week ago
Activity icon

Replied to Refactoring Controller Update Method

@jorpedito Can you explain why you think the updateOrCreate method is written wrong?

Activity icon

Started a new Conversation Refactoring Controller Update Method

I'm trying to determine if I can refactor my controller update method so that I can better employ a manager.

ManagersController

public function update(UpdateRequest $request, Manager $manager)
{
    $manager->update($request->except('started_at'));

    $startedAt = $request->input('started_at');
    $isEmployed = $manager->isEmployed();

    if ($startedAt && $isEmployed && Carbon::parse($startedAt)->lt($manager->currentEmployment->started_at)) {
        $manager->employ($request->input('started_at'));
    }

    return redirect()->route('managers.index');
}

Manager Model

public function employ($startedAt = null)
{
    $startDate = $startedAt ?? now();
        
    $this->employments()->updateOrCreate(['ended_at' => null], ['started_at' => $startDate]);

    return $this->touch();
}

public function canBeEmployed()
{
    if ($this->isEmployed()) {
        return false;
    }

    return true;
}

public function isEmployed()
{
    return $this->currentEmployment()->exists();
}
Jan
11
1 week ago
Activity icon

Replied to Disabling Instance Property Casts

@tykus Thanks for the quick reply. Maybe you can help me understand this because getOriginal() works however when I try it with getAttribute it uses the casting.

Activity icon

Started a new Conversation Disabling Instance Property Casts

Currently, I've been doing some backfilling of back filling of test for my application and started writing some unit tests for my models. I have a test that is failing and I understand why but I'm needing ideas on how to handle it. Originally this test had passed, however, now the status is being cast to an Enum class. So obviously my test won't work. Is there a way to disable temporarily the casting of a model instance property?

If not, what would be a suggestion for renaming the test?

/** @test */
public function a_manager_has_a_status()
{
    $manager = factory(Manager::class)->create(['status' => 'Example Status']);

    $this->assertEquals('Example Status', $manager->status);
}
protected $casts = [
    'status' => ManagerStatus::class,
];
Jan
08
1 week ago
Activity icon

Started a new Conversation Calling Validation Of State Of Model From Request Class

I'm running into a situation where I feel like I need to better handle the if statement inside the invoke method in my EmployController. Currently, after the request is validated it checks to see if the manager can be employed which I think I'm also kind of doing inside of the request inside of the WithoutActiveEmployment custom validation rule.

This is the only time the custom rule is being called in my system and I'm wondering if I need to rename the rule and if I should be adding that if statement inside of the rule class.

<?php

namespace App\Http\Controllers\Managers;

use App\Models\Manager;
use App\Http\Controllers\Controller;
use App\Exceptions\CannotBeEmployedException;
use App\Http\Requests\Managers\EmployRequest;

class EmployController extends Controller
{
    /**
     * Employ a manager.
     *
     * @param  App\Models\Manager  $manager
     * @param  App\Http\Requests\Managers\EmployRequest  $request
     * @return \lluminate\Http\RedirectResponse
     */
    public function __invoke(Manager $manager, EmployRequest $request)
    {
        if (!$request->canBeEmployed()) {
            throw new CannotBeEmployedException();
        }

        $manager->employ($request->input('started_at'));

        return redirect()->route('managers.index');
    }
}
<?php

namespace App\Http\Requests\Managers;

use App\Models\Manager;
use App\Rules\WithoutActiveEmployment;
use Illuminate\Foundation\Http\FormRequest;

class EmployRequest extends FormRequest
{
    ...

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'started_at' => [
                'nullable',
                new WithoutActiveEmployment($this->route('manager'))
            ]
        ];
    }

    /**
     * Determine if the manager can be employed.
     *
     * @return boolean
     */
    public function canBeEmployed()
    {
        $manager = $this->route('manager');

        if ($manager->isEmployed()) {
            return false;
        }

        return true;
    }
}
<?php

namespace App\Rules;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Contracts\Validation\Rule;

class WithoutActiveEmployment implements Rule
{
    /** @var $model */
    protected $model;
    
    /**
     * Undocumented function
     *
     * @param Model $employable
     */
    public function __construct(Model $employable)
    {
        $this->model = $employable;
    }
    
    /**
     * Undocumented function
     *
     * @param [type] $attribute
     * @param [type] $value
     * @return void
     */
    public function passes($attribute, $value = null)
    {
        if ($value === null) {
            return true;
        }
        
        $activeEmployment = $this->model->currentEmployment;

        if (!$activeEmployment || $activeEmployment->started_at->eq($value) || $activeEmployment->started_at->isFuture()) {
            return true;
        }
        
        return false;
    }

    public function message()
    {
        return 'Active employment already exists';
    }
}

Jan
05
2 weeks ago
Activity icon

Replied to Yajra Datatables Query Method Being Compatible Error

Anyone have any suggestions?

Jan
02
2 weeks ago
Activity icon

Replied to Yajra Datatables Query Method Being Compatible Error

I just wonder if there's anyone else who has used this package before and would be able to give additional feedback for my post.

Jan
01
2 weeks ago
Activity icon

Replied to Yajra Datatables Query Method Being Compatible Error

@nakov I ended up trying the above and it works, but I need to make sure that I can customize that table so that's why I was extending it.

Activity icon

Awarded Best Reply on LoginController Does Not Exist

I revisited my RouteServiceProvider and remembered that I had modified the file.

protected function mapWebRoutes()
    {
        Route::middleware('web')
             ->group(base_path('routes/web.php'));
            //->namespace($this->namespace)
    }

So inside of my web.php file I had to do this.

Route::namespace('App\Http\Controllers')->group(function () {
    Auth::routes();
});
Activity icon

Replied to LoginController Does Not Exist

I revisited my RouteServiceProvider and remembered that I had modified the file.

protected function mapWebRoutes()
    {
        Route::middleware('web')
             ->group(base_path('routes/web.php'));
            //->namespace($this->namespace)
    }

So inside of my web.php file I had to do this.

Route::namespace('App\Http\Controllers')->group(function () {
    Auth::routes();
});
Activity icon

Replied to LoginController Does Not Exist

@nakov I have not moved it. It is inside of the app\Http\Controllers\Auth directory.

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;

class LoginController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | Login Controller
    |--------------------------------------------------------------------------
    |
    | This controller handles authenticating users for the application and
    | redirecting them to your home screen. The controller uses a trait
    | to conveniently provide its functionality to your applications.
    |
    */

    use AuthenticatesUsers;

    /**
     * Where to redirect users after login.
     *
     * @var string
     */
    protected $redirectTo = '/dashboard';

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('guest')->except('logout');
    }
}
Activity icon

Started a new Conversation LoginController Does Not Exist

I'm still working on a 5.8 application and just noticed today that when I run php artisan route:list command I get an error

ReflectionException  : Class Auth\LoginController does not exist

I can't understand why because in my web.php routers file I have the simple command of Auth::routes() . I've ran composer dump auto-load and no errors. I have removed my vendor directory entirely and reran composer install and still get the same error. I have also ran php artisan cache:clear with the same problem.

Any suggestions?

Dec
29
3 weeks ago
Activity icon

Replied to Yajra Datatables Query Method Being Compatible Error

Has anyone else been through this before?

Dec
24
4 weeks ago
Activity icon

Replied to Yajra Datatables Query Method Being Compatible Error

@nakov Yeah I'm trying to figure out when I need to call the datatables and query methods on the child Datatables class from the controller.

Activity icon

Replied to Yajra Datatables Query Method Being Compatible Error

Still the same. I think it's because I don't have the eloquent method in the UsersDataTable class and its calling the parent class method.

Activity icon

Replied to Yajra Datatables Query Method Being Compatible Error

Yes, it is. So should I be calling the eloquent method in my controller?

Activity icon

Replied to Yajra Datatables Query Method Being Compatible Error

@nakov This is the controller code.

public function index(Request $request, UsersDataTable $dataTable, UsersFilters $requestFilter)
    {
        $this->authorize('viewList', Manager::class);

        if ($request->ajax()) {
            $query = User::query();
            $requestFilter->apply($query);

            return $dataTable->eloquent($query)->toJson();
        }

        return view('users.index');
    }
Activity icon

Replied to Yajra Datatables Query Method Being Compatible Error

I've removed it and still get the same error as not being compatible with its parent method. I've added a dd() at the top of the query method and at no point does my tests ever hit that method so I don't understand how it could give that error.

Activity icon

Replied to Yajra Datatables Query Method Being Compatible Error

@nakov I appreciate your help on this however I'm not understanding where the Services directory is coming from since one does not exist.

Activity icon

Replied to Yajra Datatables Query Method Being Compatible Error

@nakov

I don't have that class installed in the package files. This is the package that is installed.

"yajra/laravel-datatables-oracle": "~9.0"
Activity icon

Started a new Conversation Yajra Datatables Query Method Being Compatible Error

If anyone has used the Yajra Datatables package, I am getting this error.

ReflectionException: Class App\DataTables\UsersDataTable does not exist

Caused by
ErrorException: Declaration of App\DataTables\UsersDataTable::query(): Illuminate\Database\Query\Builder should be compatible with Yajra\DataTables\DataTables::query($builder)

From what I see both query methods are returning the same object.

<?php

namespace App\DataTables;

use App\Models\User;
use App\Filters\UserFilters;
use Yajra\DataTables\DataTables;

class UsersDataTable extends DataTables
{
    /** @var userFilters */
    private $userFilters;

    /**
     * UsersDataTable constructor.
     *
     * @param UserFilters $userFilters
     */
    public function __construct(UserFilters $userFilters)
    {
        $this->userFilters = $userFilters;
    }

    /**
     * Build DataTable class.
     *
     * @param mixed $query Results from query() method.
     * @return \Yajra\DataTables\DataTableAbstract
     */
    public function dataTable($query): \Yajra\DataTables\DataTableAbstract
    {
        return datatables($query)
            ->editColumn('started_at', function (User $user) {
                return $user->currentEmployment->started_at->format('Y-m-d H:s');
            })
            ->filterColumn('id', function ($query, $keyword) {
                $query->where($query->qualifyColumn('id'), $keyword);
            })
            ->filterColumn('name', function ($query, $keyword) {
                $sql = "CONCAT(user.first_name, ' ', user.last_name)  like ?";
                $query->whereRaw($sql, ["%{$keyword}%"]);
            })
            ->addColumn('action', 'users.partials.action-cell');
    }

    /**
     * Get query source of dataTable.
     *
     * @return \Illuminate\Database\Query\Builder
     */
    public function query(): \Illuminate\Database\Query\Builder
    {
        $query = User::with('employment');

        $this->userFilters->apply($query);

        return $query;
    }
}
Dec
18
1 month ago
Activity icon

Replied to Spatie BladeX Componentized Logic

Is this something that anyone has used before?

Dec
17
1 month ago
Activity icon

Started a new Conversation Spatie BladeX Componentized Logic

I've started using the Spatie package Bade X found here. https://github.com/spatie/laravel-blade-x

I have added it to my AppServiceProvider with this snippet.

public function boot()
{
    BladeX::component('components.*');
}

This is my date-field component. If you notice inside of the value attribute of the input element it has a value that is situational to the form that it is on. What can I do so that I can pull that logic out so that the value is determined out of the component.

<field-label :for="$name" :label="$label ?? ''" />

<div class="kt-input-icon kt-input-icon--right">
    <input 
        type="text" 
        class="form-control @error($name) is-invalid @enderror"
        name="{{ $name }}" 
        placeholder="Enter {{ $label }}"
        value="{{ old($name, optional($employee->employment->started_at ?? null)->toDateTimeString()) }}"
        data-datetimepicker 
        data-input
    >
    <span class="kt-input-icon__icon kt-input-icon__icon--right">
        <span><i class="flaticon-calendar-with-a-clock-time-tools"></i></span>
    </span>
    @error($name)
        <form-error name="{{ $name }}" />
    @enderror
</div>
Dec
12
1 month ago
Activity icon

Replied to Decisions To Be Made For Simple Naming Semantics

@bugsysha I had updated my previous response before you replied. If you can give your opinion it would be greately appreciated.

Activity icon

Replied to Decisions To Be Made For Simple Naming Semantics

@bugsysha Well basically with most of the controllers I write, if it's not part of the BASIC 7 actions of a model then I tend to make invokable controllers for them. For example, I also have these controllers. Should I change the name of the controller to HealController?

EmployeeController
InjureController
PlayersController
RecoveryFromInjuryController
ReinstateController
RestoreController
RetireController
SuspendController
UnretireController
Activity icon

Replied to Decisions To Be Made For Simple Naming Semantics

@bugsysha Do you think RecoverFromInjury{Controller/Request} are good names for those classes?

Dec
10
1 month ago
Activity icon

Started a new Conversation Decisions To Be Made For Simple Naming Semantics

If someone has a player that has a state of injured in their system but wants to mark them as recovered/healed what sounds better out of those two words. At one point I had RecoverController but changed it to RecoverFromInjuryController. Not sure Recover sounds right.

I have differences where I use recovered and others where I use healed.

Does anyone have any suggestions on what would be better used for naming my controller, request class, and methods involving this split naming classes and methods.

<?php

namespace App\Http\Controllers\Players;

use App\Models\Player;
use App\Http\Controllers\Controller;
use App\Exceptions\CannotBeMarkedAsHealedException;
use App\Http\Requests\Players\RecoverFromInjuryRequest;

class RecoverFromInjuryController extends Controller
{
    /**
     * Recover a manager.
     *
     * @param  \App\Models\Player  $manager
     * @param  App\Http\Requests\Players\RecoverFromInjuryRequest  $request
     * @return \lluminate\Http\RedirectResponse
     */
    public function __invoke(Player $manager, RecoverFromInjuryRequest $request)
    {
        if (!$request->canBeMarkedAsHealed()) {
            throw new CannotBeMarkedAsHealedException();
        }

        $player->markAsHealed();

        return redirect()->route('players.index');
    }
}
<?php

namespace App\Http\Requests\Players;

use App\Models\Player;
use Illuminate\Foundation\Http\FormRequest;

class RecoverFromInjuryRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return $this->user()->can('markAsHealed', Player::class);
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [];
    }

    /**
     * Determine if the player can be marked as healed.
     *
     * @return boolean
     */
    public function canBeMarkedAsHealed()
    {
        if (!$this->route('player')->isInjured()) {
            return false;
        }

        return true;
    }
}
<?php

namespace App\Policies;

use App\Models\User;
use Illuminate\Auth\Access\HandlesAuthorization;

class PlayerPolicy
{
    use HandlesAuthorization;

    /**
     * Determine whether the user can recover a player.
     *
     * @param  App\Models\User  $user
     * @return bool
     */
    public function markAsHealed(User $user)
    {
        return $user->isSuperAdministrator() || $user->isAdministrator();
    }
}
Nov
29
1 month ago
Activity icon

Replied to Looking For A Better Assertion

@bobbybouwmann I know I've extended this post out, however, I'm trying to figure out I can feature test the employ method with having the check if the manager is employed. I'm starting to wonder if that's a good place for it.

<?php

namespace Tests\Feature\Admin\Manager;

use Carbon\Carbon;
use Tests\TestCase;
use App\Models\Manager;
use Illuminate\Foundation\Testing\RefreshDatabase;

/**
 * @group managers
 * @group admins
 * @group roster
 */
class CreateManagerSuccessConditionsTest extends TestCase
{
    use RefreshDatabase;

    /**
     * Valid parameters for request.
     *
     * @param  array $overrides
     * @return array
     */
    private function validParams($overrides = [])
    {
        return array_replace([
            'first_name' => 'John',
            'last_name' => 'Smith',
            'started_at' => now()->toDateTimeString(),
        ], $overrides);
    }

    /** @test */
    public function an_administrator_can_view_the_form_for_creating_a_manager()
    {
        $this->actAs('administrator');

        $response = $this->createRequest('manager');

        $response->assertViewIs('managers.create');
        $response->assertViewHas('manager', new Manager);
    }

    /** @test */
    public function an_administrator_can_create_a_manager()
    {
        $now = now();
        Carbon::setTestNow($now);

        $this->actAs('administrator');

        $response = $this->storeRequest('manager', $this->validParams());

        $response->assertRedirect(route('managers.index'));
        tap(Manager::first(), function ($manager) use ($now) {
            $this->assertEquals('John', $manager->first_name);
            $this->assertEquals('Smith', $manager->last_name);
        });
    }

    /** @test */
    public function an_administrator_can_employ_a_manager_during_creation()
    {
        $now = now();
        Carbon::setTestNow($now);

        $this->actAs('administrator');

        $this->storeRequest('manager', $this->validParams(['started_at' => $now->toDateTimeString()]));

        tap(Manager::first(), function ($manager) use ($now) {
            $this->assertDatabaseHas('employments', [
                'employable_id' => $manager->id,
                'employable_type' => get_class($manager),
                'started_at' => $now->toDateTimeString()
            ]);
        });
    }

    /** @test */
    public function an_administrator_can_create_a_manager_without_employing()
    {
        $now = now();
        Carbon::setTestNow($now);

        $this->actAs('administrator');

        $this->storeRequest('manager', $this->validParams(['started_at' => null]));

        tap(Manager::first(), function ($manager) use ($now) {
            $this->assertDatabaseMissing('employments', [
                'employable_id' => $manager->id,
                'employable_type' => get_class($manager),
                'started_at' => $now->toDateTimeString()
            ]);
        });
    }
}

<?php

namespace App\Http\Controllers\Managers;

use App\Models\Manager;
use App\Http\Controllers\Controller;
use App\Http\Requests\StoreManagerRequest;

class ManagersController extends Controller
{
    /**
     * Create a new manager.
     *
     * @param  \App\Http\Requests\StoreManagerRequest  $request
     * @return \Illuminate\Http\RedirectResponse
     */
    public function store(StoreManagerRequest $request)
    {
        $manager = Manager::create($request->except('started_at'));

        if ($request->filled('started_at')) {
            $manager->employ($request->input('started_at'));
        }

        return redirect()->route('managers.index');
    }
}

app/Models/Concerns/CanBeEmployed.php

<?php

namespace App\Models\Concerns;

use App\Models\Employment;
use App\Exceptions\CannotBeEmployedException;


trait CanBeEmployed
{
    /**
     * Get all of the employments of the model.
     *
     * @return \Illuminate\Database\Eloquent\Relations\MorphMany
     */
    public function employments()
    {
        return $this->morphMany(Employment::class, 'employable');
    }

    /**
     * Employ a model.
     *
     * @param  Carbon|string $startedAt
     * @return bool
     */
    public function employ($startedAt = null)
    {
        if ($this->checkIsEmployed()) {
            throw new CannotBeEmployedException;
        }

        $startDate = $startedAt ?? now();
        $this->employments()->updateOrCreate(['ended_at' => null], ['started_at' => $startDate]);

        return $this->touch();
    }
}

Nov
25
1 month ago
Activity icon

Replied to Looking For A Better Assertion

@bobbybouwmann So you would agree with me doing the following, or is there somethign else that could even be more helpful.

/** @test */
    public function a_super_administrator_can_employ_a_manager_during_creation()
    {
        $now = now();
        Carbon::setTestNow($now);

        $this->actAs('super-administrator');

        $this->storeRequest('manager', $this->validParams(['started_at' => $now->toDateTimeString()]));

        tap(Manager::first(), function ($manager) use ($now) {
            $this->assertDatabaseHas('employments', ['employable_id' => $manager->id, 'employable_type' => get_class($manager), 'started_at' => $now->toDateTimeString()]);
        });
    }

    /** @test */
    public function a_super_administrator_can_create_a_manager_without_employing()
    {
        $now = now();
        Carbon::setTestNow($now);

        $this->actAs('super-administrator');

        $this->storeRequest('manager', $this->validParams(['started_at' => null]));

        tap(Manager::first(), function ($manager) use ($now) {
            $this->assertDatabaseMissing('employments', ['employable_id' => $manager->id, 'employable_type' => get_class($manager), 'started_at' => $now->toDateTimeString()]);
        });
    }
Activity icon

Replied to Looking For A Better Assertion

@bobbybouwmann I do cover testing that exception in other tests because that employ method can be accessed in an actual employController which is an invokable controller. With the store method the manager can't already be hired so it will never pass the checkIsEmployed if statement.

Nov
24
1 month ago
Activity icon

Started a new Conversation Looking For A Better Assertion

What I'm debating is assertions in the last two test methods. Currently, I have it trying to retrieve the currentEmployment but I don't have anything that specifically says currentEmployment involved in the employ method.

Does anyone have any better ideas on how I should be testing against for making sure that the employment was created correctly? I've also debated on whether or not to use the assertDatabaseHas but not sure if that's the best solution either.

This is a feature level and does in fact pass however I don't think it depicts exactly what the edge case test is describing.

<?php

namespace Tests\Feature\SuperAdmin\Managers;

use Tests\TestCase;
use App\Models\Manager;
use Illuminate\Foundation\Testing\RefreshDatabase;

/**
 * @group managers
 * @group superadmins
 * @group roster
 */
class CreateManagerSuccessConditionsTest extends TestCase
{
    use RefreshDatabase;

    /**
     * Valid parameters for request.
     *
     * @param  array $overrides
     * @return array
     */
    private function validParams($overrides = [])
    {
        return array_replace([
            'first_name' => 'John',
            'last_name' => 'Smith',
            'started_at' => now()->toDateTimeString(),
        ], $overrides);
    }

    /** @test */
    public function a_super_administrator_can_view_the_form_for_creating_a_manager()
    {
        $this->actAs('super-administrator');

        $response = $this->createRequest('manager');

        $response->assertViewIs('managers.create');
        $response->assertViewHas('manager', new Manager);
    }

    /** @test */
    public function a_super_administrator_can_create_a_manager()
    {
        $this->actAs('super-administrator');

        $response = $this->storeRequest('manager', $this->validParams());

        $response->assertRedirect(route('managers.index'));
        tap(Manager::first(), function ($manager) {
            $this->assertEquals('John', $manager->first_name);
            $this->assertEquals('Smith', $manager->last_name);
        });
    }

    /** @test */
    public function a_super_administrator_can_employ_a_manager_during_creation()
    {
        $this->actAs('super-administrator');

        $this->storeRequest('manager', $this->validParams(['started_at' => now()->toDateTimeString()]));

        tap(Manager::first(), function ($manager) {
            $this->assertEquals(now()->toDateTimeString(), $manager->currentEmployment->started_at);
        });
    }

    /** @test */
    public function a_super_administrator_can_create_a_manager_without_employing()
    {
        $this->actAs('super-administrator');

        $this->storeRequest('manager', $this->validParams(['started_at' => null]));

        tap(Manager::first(), function ($manager) {
            $this->assertEquals(null, $manager->currentEmployment);
        });
    }
}
/**
     * Create a new manager.
     *
     * @param  \App\Http\Requests\StoreManagerRequest  $request
     * @return \Illuminate\Http\RedirectResponse
     */
    public function store(StoreManagerRequest $request)
    {
        $manager = Manager::create($request->except('started_at'));

        if ($request->filled('started_at')) {
            $manager->employ($request->input('started_at'));
        }

        return redirect()->route('managers.index');
    }
/**
     * Employ a model.
     *
     * @param  Carbon|string $startedAt
     * @return bool
     */
    public function employ($startedAt = null)
    {
        if ($this->checkIsEmployed()) {
            throw new CannotBeEmployedException;
        }

        $startDate = $startedAt ?? now();
        $this->employments()->updateOrCreate(['ended_at' => null], ['started_at' => $startDate]);

        return $this->touch();
    }
Oct
18
3 months ago
Activity icon

Commented on Widget Workshop

Also to add if you have to assign private properties on a class and don't want the Widget to pass along the constructor for the viewData you can add this check inside of the foreach of the buildViewData method.

if ($method->isConstructor()) {
   continue;
}
Oct
10
3 months ago
Activity icon

Started a new Conversation Blog Post And Project Sharing Attachments And Categories

I'm attempting to map out my personal blog site with the right migrations and models. I have posts that each have either one or multiple categories and attachments which can be an image or a video. I also have projects that can either have one or multiple categories as well and one or multiple attachments attached to the project.

My question is my description above with how a project and a blog post can both have multiple attachments and categories assigned to them the correct way to set up my migrations.

Schema::create('posts', function (Blueprint $table) {
    $table->bigIncrements('id');
    $table->string('title');
    ...
    $table->timestamps();
});

Schema::create('attachments', function (Blueprint $table) {
    $table->bigIncrements('id');
    $table->morphs('attachable');
    $table->string('path');
    $table->timestamps();
});

Schema::create('projects', function (Blueprint $table) {
    $table->bigIncrements('id');
    $table->string('name');
    $table->timestamps();
});

Schema::create('categories', function (Blueprint $table) {
    $table->bigIncrements('id');
    $table->morphs('categorable');
    $table->string('name');
    $table->timestamps();
});
Oct
05
3 months ago
Activity icon

Replied to Laravel Mutator Not Working Correctly

@falloutboi Remember it will NEVER hit that if statement when you are returning the first_name property always.

Sep
25
3 months ago
Activity icon

Started a new Conversation Custom Relationship Returning Collection Instead Of Single Model

I created a custom relationship to handle situations for a polymorphic many to many relationship. My problem is if I have a model that has this trait attached and I want to grab the currentGroup they are attached to if they are it then returns a collection instead of a single model instance. I attempted to add ->first() to the end of the QB inside of the current method of the relationship class but it still returns the collection. What am I doing wrong here?

<?php

namespace App\Models\Concerns;

use App\Models\Member;
use App\Models\Group;

trait CanBeGroupMember
{
    /**
     * Get the group history the member has belonged to.
     *
     * @return App\Eloquent\Relationships\LeaveableMorphToMany
     */
    public function groupHistory()
    {
        return $this->leaveableMorphToMany(Group::class, 'member')->using(Member::class);
    }

    /**
     * Get the current group the member belongs to.
     *
     * @return App\Eloquent\Relationships\LeaveableMorphToMany
     */
    public function currentGroup()
    {
        return $this->groupHistory()->where('status', 'active')->current();
    }

    /**
     * Get the previous groups the member has belonged to.
     *
     * @return App\Eloquent\Relationships\LeaveableMorphToMany
     */
    public function previousGroups()
    {
        return $this->groupHistory()->detached();
    }
}
<?php

namespace App\Eloquent\Concerns;

use Illuminate\Support\Arr;
use Illuminate\Database\Eloquent\Relations\Pivot;

trait IsLeaveableBelongsToMany
{
    /**
     * The cached copy of the currently attached pivot models.
     *
     * @var Collection
     */
    private $currentlyAttached;

    public function detach($ids = null, $touch = true)
    {
        $query = $this->newPivotQuery();
        // If associated IDs were passed to the method we will only delete those
        // associations, otherwise all of the association ties will be broken.
        // We'll return the numbers of affected rows when we do the deletes.
        if (! is_null($ids)) {
            $ids = $this->parseIds($ids);
            if (empty($ids)) {
                return 0;
            }
            $query->whereIn($this->relatedPivotKey, (array) $ids);
        }

        $results = $query->update(['left_at' => now()]);
        if ($touch) {
            $this->touchIfTouching();
        }
        return $results;
    }

    /**
     * Sync the intermediate tables with a list of IDs or collection of models.
     *
     * @param  \Illuminate\Support\Collection|\Illuminate\Database\Eloquent\Model|array  $ids
     * @param  bool   $detaching
     * @return array
     */

    public function sync($ids, $detaching = true)
    {
        $changes = [
            'attached' => [], 'detached' => [], 'updated' => [],
        ];

        // First we need to attach any of the associated models that are not currently
        // in this joining table. We'll spin through the given IDs, checking to see
        // if they exist in the array of current ones, and if not we will insert.
        $current = $this->getCurrentlyAttachedPivots()
                        ->pluck($this->relatedPivotKey)->all();

        $detach = array_diff($current, array_keys(
            $records = $this->formatRecordsList($this->parseIds($ids))
        ));

        // Next, we will take the differences of the currents and given IDs and detach
        // all of the entities that exist in the "current" array but are not in the
        // array of the new IDs given to the method which will complete the sync.
        if ($detaching && count($detach) > 0) {
            $this->detach($detach);

            $changes['detached'] = $this->castKeys($detach);
        }

        // Now we are finally ready to attach the new records. Note that we'll disable
        // touching until after the entire operation is complete so we don't fire a
        // ton of touch operations until we are totally done syncing the records.
        $changes = array_merge(
            $changes,
            $this->attachNew($records, $current, false)
        );

        // Once we have finished attaching or detaching the records, we will see if we
        // have done any attaching or detaching, and if we have we will touch these
        // relationships if they are configured to touch on any database updates.
        if (count($changes['attached']) ||
            count($changes['updated'])) {
            $this->touchIfTouching();
        }

        return $changes;
    }

    /**
     * Get the pivot models that are currently attached.
     *
     * @return \Illuminate\Support\Collection
     */
    protected function getCurrentlyAttachedPivots()
    {
        return $this->currentlyAttached ?: $this->newPivotQuery()->whereNull('left_at')->get()->map(function ($record) {
            $class = $this->using ? $this->using : Pivot::class;

            return (new $class)->setRawAttributes((array) $record, true);
        });
    }

    protected function baseAttachRecord($id, $timed)
    {
        return Arr::add(
            parent::baseAttachRecord($id, $timed),
            'joined_at',
            now()
        );
    }

    public function current()
    {
        $this->wherePivot('left_at', null);

        return $this;
    }

    public function detached()
    {
        $this->wherePivot('left_at', '!=', null); //Laravel translates this to `IS NOT NULL`

        return $this;
    }

}

Sep
23
3 months ago
Activity icon

Replied to Unit Testing A Model

@martinbean

So do you mean I should remove the following from the model?

if (!$this->is_employed) || $this->is_retired) {
    throw new CannotBeRetiredException;
}
Activity icon

Started a new Conversation Unit Testing A Model

I'm trying to unit test my models and currently have a method that will retire a player from the system. I'm trying to find out if I should have my checks on the status of the player in the policy or in the model because it changes how I approach my unit testing for the player.

What suggestions or ideas do people have?

Policy

/**
     * Determine whether the user can retire a player.
     *
     * @param  App\Models\User  $user
     * @param  App\Models\Player  $player
     * @return bool
     */
    public function retire(User $user, Player $player)
    {
        if (!$player->is_employed || $player->is_retired) {
            return false;
        }

        return $user->isSuperAdministrator() || $user->isAdministrator();
    }

Model

/**
     * Retire a model.
     *
     * @return \App\Models\Retirement
     */
    public function retire()
    {
        if (!$this->is_employed) || $this->is_retired) {
            throw new CannotBeRetiredException;
        }

        $this->retirements()->create(['started_at' => now()]);
        $this->touch();
    }
Aug
22
4 months ago
Activity icon

Replied to Refactoring To Datatable Classes

@jlrdw No worries on the misunderstanding. Some of the references for the package have sites that I think are temporarily down because I can't access any of them.

Is there anyone that has used this package and created their own classes that extend the package datatables class and modified the class so that they can handle all of the logic in one place.

Aug
21
5 months ago
Activity icon

Replied to Refactoring To Datatable Classes

@jlrdw I've updated with my full controller method.

Activity icon

Replied to Refactoring To Datatable Classes

How would I apply a scope for this?

Activity icon

Started a new Conversation Refactoring To Datatable Classes

I'm trying to figure out how I can refactor this little bit of controller code to individual classes that can be used instead. The package I am using is Yajra Laravel Datatables package.

/**
     * View a list of users.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\DataTables\UsersDataTable  $table
     * @param  \App\Filters\UserFilters  $requestFilter
     * @return \Illuminate\View\View
     */
    public function index(Request $request, UsersDataTable $table, UserFilters $requestFilter)
    {
        $this->authorize('viewList', User::class);

        if ($request->ajax()) {
            $query = User::with('employment');
            $requestFilter->apply($query);

            return $table->eloquent($query)
                ->addColumn('action', 'users.partials.action-cell')
                ->filterColumn('name', function ($query, $keyword) {
                    $sql = "CONCAT(users.first_name, ' ', users.last_name)  like ?";
                    $query->whereRaw($sql, ["%{$keyword}%"]);
                })
                ->filterColumn('id', function ($query, $keyword) {
                    $query->where($query->qualifyColumn('id'), $keyword);
                })
                ->toJson();
        }

        return view('users.index');
    }
Aug
16
5 months ago
Activity icon

Started a new Conversation Yajra Datatables

I'm using the following package to better display a rendered table of users for my project. The problem is what I would like to do is extract the logic inside of the ajax check to a new Datatable class that extends the package's default Datatable class. The methods that I'm looking at for the class doesn't exactly line up with what I'm doing.

https://github.com/yajra/laravel-datatables

https://yajrabox.com/docs/laravel-datatables/master/editor-tutorial

public function index(IndexUserRequest $request, DataTables $table, UserFilters $requestFilter)
    {
        $this->authorize('viewList', User::class);

        if ($request->ajax()) {
            $query = User::with('employment');
            $requestFilter->apply($query);

            return $table->eloquent($query)
                ->addColumn('action', 'users.partials.action-cell')
                ->filterColumn('id', function ($query, $keyword) {
                    $query->where($query->qualifyColumn('id'), $keyword);
                })
                ->toJson();
        }

        return view('users.index');
    }
Aug
13
5 months ago
Activity icon

Replied to Filter Statuses Array

I ended up going with this in the view.

@foreach (\App\Enums\PlayerStatus::toArray() as $key => $value)
    <option value="{{ $value }}">
        {{ trans('enums.' . \App\Enums\PlayerStatus::class . '.' . constant("\App\Enums\PlayerStatus::$key")) }}
    </option>
@endforeach