jrdavidson

Software Engineer at Quicken Loans

Member Since 6 Years Ago

Kissimmee, FL

Experience Points
205,515
Total
Experience

4,485 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
1549
Lessons
Completed
Best Reply Awards
14
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 42
205,515 XP
May
05
4 days ago
Activity icon

Started a new Conversation Ordering By A Relationship

I'm working with Spatie's permissions package and trying to order my users by their role but applying a specific order of those roles by the role name. Currently with my query it its not ordering and I'm curious to know if I'm doing something wrong here.

public function scopeOrderByRole($query)
    {
        return $query->whereHas('roles', function ($query) {
            return $query->orderBy(DB::raw('
                case
                    when roles.name = "super-admin" then 1
                    when roles.name = "company-admin" then 2
                    when roles.name = "maintainer-admin" then 3
                    when roles.name = "user" then 4
                end
            '), 'desc');
        });
    }
May
04
5 days ago
Activity icon

Started a new Conversation Session Data Missing For Test

I'm trying to figure out what I'm doing wrong in my test. Currently my test passes until it hits the assertSessionHas('company_id', null) part of the test. Currently the test is failing due to Session is missing expected key [company_id].

I go through the browser and I see the company_id in the session. Not sure what I"m doing wrong.

/** @test */
    public function a_super_admin_who_impersonates_a_company_admin_can_leave_impersonation()
    {
        $superAdmin = User::factory()->superAdmin()->create();
        $user = User::factory()->companyAdmin()->create();

        $this->actingAs($superAdmin)
            ->post(route('impersonate', $user))
            ->assertSessionHas('company_id', $user->company->id);

        $this->assertAuthenticatedAs($user);

        $this
            ->get(route('leave-impersonation'))
            ->assertRedirect()
            ->assertSessionHas('company_id', null)
            ->assertSessionMissing('impersonate');

        $this->assertAuthenticatedAs($superAdmin);
    }
/**
     * Handle the incoming request.
     *
     * @param  \App\Models\User $user
     * @return \Illuminate\Http\Response
     */
    public function destroy(User $user)
    {
        if (! session()->has('impersonate')) {
            abort(403);
        }

        $impersonator = User::withoutGlobalScope(CompanyScope::class)->find(session('impersonate'));

        auth()->login($impersonator);

        if ($impersonator->hasRole('super-admin')) {
            session()->put('company_id', null);
        }

        session()->forget('impersonate');

        return redirect()->route('user.dashboard');
    }
May
03
6 days ago
Activity icon

Started a new Conversation Dropdown Being Removed From DOM

I’m faced with a problem I can’t understand what’s happening. Currently when the role is changed and meets the correct criteria of the role then it shows the companies dropdown BUT it removes the dropdown of the roles.

<?php

namespace App\Http\Livewire;

use App\Models\Company;
use Livewire\Component;

class AddRoleForUser extends Component
{
    public $selectedRole;
    public $showCompaniesDropdown = false;

    public function updatedSelectedRole($role)
    {
        if (!is_null($role)) {
            $this->showCompaniesDropdown = in_array($role, ['admin', 'maintainer admin', 'user']);
        }
    }

    public function render()
    {
        return view('livewire.add-role-for-user', [
            'roles' => \Spatie\Permission\Models\Role::get()->pluck('name', 'name'),
            'companies' => Company::get()->pluck('name', 'id'),
        ]);
    }
}

<div>
    <div class="mb-8">
        <x-label
            class="text-gray-500"
            for="role"
            value="Role"
        />
        <x-select
            wire:model="selectedRole"
            id="role"
            name="role"
            class="block w-full mt-1"
            :options="$roles"
        />
    </div>
    @if ($showCompaniesDropdown)
        <div class="mb-8">
            <x-label
                class="text-gray-500"
                for="company"
                value="Company"
            />
            <x-select
                id="role"
                name="company"
                class="block w-full mt-1"
                :options="$companies"
            />
        </div>
    @endif
</div>

Apr
29
1 week ago
Activity icon

Replied to Stripe And Cashier New Subscription

@jlrdw Would it be wrong to store the subscription plan in a session.

Activity icon

Started a new Conversation Stripe And Cashier New Subscription

I'm helping build an application with Cashier and Stripe that upon registering the user must put in their personal info like name, address, etc on the first screen. After they submit that form they are redirected to a membership plan page where they must choose their plan they want to sign up for. After submitting that plan form they are redirected to a payment information page, then after a submission of that form redirected to billing information page.

The problem I'm trying to figure out is after they submit which plan I need to create a new subscription but according to the docs you need a payment method to do that.

Apr
22
2 weeks ago
Activity icon

Commented on Clockwork, And The N+1 Problem

@kissartisan After reading that post I agree that yes Debugbar is still a great tool but that has always bothered me with how it injects code into the HTML when I just want to use the tool itself.

Apr
21
2 weeks ago
Activity icon

Commented on Clockwork, And The N+1 Problem

What's the advantage of using this over a solution like Debugbar?

Apr
14
3 weeks ago
Activity icon

Replied to Using HasManyDeep With Model And WithCount

I was suggested to realign some of my database tables and this is what I have now. The problem I have with this is because for each semester has an attached course and has a section but I need a way to show what course is attached to the course section.

Any suggestions?

Semester
- id
- name
...

Course
- id
- name
...

CourseSection
- id
- day
- teacher
- start_time
- end_time
...

CourseSemester
- id
- course_section_id
- semester_Id
- course_id
...

CourseSemesterStudent
- id
- course_section_semester_id
- student_id
Activity icon

Replied to Using HasManyDeep With Model And WithCount

Is this a situation that can be done?

Apr
13
3 weeks ago
Activity icon

Started a new Conversation Using HasManyDeep With Model And WithCount

I enlisted the HasManyDeep package written by Jonas Staudenmeir located here: https://github.com/staudenmeir/eloquent-has-many-deep.I'm retrieving all courses that were taken during a semester. As you can see there is not a has many relationship between semester and course. Instead, I'm using the many-to-many relationship between a semester and a course section, and with the course sections get the one-to-many relationship between the course section and course.

Currently I'm getting the collection of courses for a semester. What I also need to do is get the count of students that have participated in the sections for these courses for the specific semester.

What can add onto my current query so that I can add a total of a nested relationship.

Semester
- id
- name
...
Course
- id
- name
...
CourseSection
- id
- course_id
...
CourseSectionSemester
- id
- course_section_id
- semester_Id
...
CourseSectionSemesterStudent
- id
- course_section_semester_id
- student_id

Semester.php

public function courses()
{
    return $this->hasManyDeep(
        Course::class,
        [CourseSectionSemester::class, CourseSection::class],
        ['semester_id', 'course_id', 'id']
    );
}

Query

$query = $this->semester->courses()->newQuery()
        ->whereHas('sections.semesters', function ($query) {
            $query->withCount('students');
        })
Activity icon

Replied to Deep Relationship Count

I've tried figuring this out this morning and haven't gotten any further. Has anyone used the withCount and had to go many levels deep?

Apr
12
3 weeks ago
Activity icon

Replied to Deep Relationship Count

@michaloravec I'm starting to wonder if any of my relationships aren't right because I can't figure out how to access the students.

Activity icon

Replied to Deep Relationship Count

@michaloravec What I was trying to convey is that I'm wanting the student count for each course in a course section during a semester.

That's a lot to take in. The suggested change wouldn't work because I don't have a student relationship on the semester model. I will provide update my original post with model relationships.

Activity icon

Started a new Conversation Deep Relationship Count

I have a deep count that I'm need to retrieve and would like some help figuring this out if anyone is willing to look at the current code and the database structure and assess what I have so far.

I know the first parameter of the withCount method if passed an array is the relationship but that's where I don't understand I'm not wanting it to be a count of the sections its deeper than that.

Any ideas/suggestions?

Course::query()
    ->whereHas('sections', function (Builder $query) {
        $query->whereHas('semesters', function ($query) {
             $query->where('semester_id', $this->semester->id);
        });
    })
    ->withCount(['testing' => function (Builder $query) {
        $query->whereHas('sections', function (Builder $query) {
            $query->whereHas('semesters', function ($query) {
                $query->where('semester_id', $this->semester->id);
            })->whereHas('students');
        });
    }])
Course
- id
- name
...

CourseSection
- id
- course_id
...

CourseSectionSemester
- id
- course_section_id
- semester_Id
...

CoureSectionSemesterStudent
- id
- course_section_semester_id
- student_Id
...

Course

public function sections()
{
    return $this->hasMany(CourseSection::class);
}

CourseSection

public function semesters()
{
    return $this->belongsToMany(Semester::class);
}

Semester

public function courseSections()
{
        return $this->belongsToMany(CourseSection::class)->using(CourseSectionSemester::class)->withTimestamps();
}

CourseSectionSemester

public function students()
{
    return $this->belongsToMany(User::class, 'course_section_semester_student', 'section_semester_id', 'student_id')->withTimestamps();
}
Activity icon

Replied to Marking Selected Multiple Options With Select Blade Component

@corvs I have a dd() inside of the isSelected method and it's not even being hit.

Activity icon

Started a new Conversation Marking Selected Multiple Options With Select Blade Component

Can someone recommend how I can add the selected attribute for a select element if the instance that I create is a multiple select? So if you notice I am passing in an array of selectedOptions to work with. The isSelected method was taken from a post on Stackoverflow that I don't have working currently.

<x-input.select
    id="courses_listbox"
    name="courses[]"
    class="dual-listbox"
     :options="$courses"
     :selectedOptions="$selectedCourses"
     multiple
/>
@props([
    'options' => [],
    'selectedOptions' => []
])

<select {{ $attributes->merge(['class' => 'form-control']) }}>
    @foreach($options as $value => $label)
        <option value="{{ $value }}" isSelected($value)>{{ $label }}</option>
    @endforeach
</select>
<?php

namespace App\View\Components\Form;

use Illuminate\View\Component;

class Select extends Component
{
    /**
     * Create a new component instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Get the view / contents that represent the component.
     *
     * @return \Illuminate\Contracts\View\View|\Closure|string
     */
    public function render()
    {
        return view('components.inputs.select');
    }

    public function isSelected($option)
    {
        return $option == old($this->name, $this->value) ? 'selected' : '';
    }
}

Apr
11
4 weeks ago
Activity icon

Replied to I Want To Add PR To Laravel Validation Rules

@abdallhsamy I believe the reason Taylor closed your pull request is that it doesn't add additional helpful features for Laravel developers. This is definitely something that if you use in more than one of your projects. Create a package used just for you OR release it to the public so others can use it as well.

Activity icon

Awarded Best Reply on Livewire Component Not Removing Items Correctly

What I ended up doing was adding these two events to the javascript.

addEvent: function (value) {
    @this.call('selectCourse', value);
},
removeEvent: function (value) {
    @this.call('removeCourse', value);
},
window.addEventListener('livewire:load', function() {
    KTDualListbox.init();
});

window.addEventListener('initListBox', function() {
    KTDualListbox.init();
});

I added this to the top of the render method so that every time the component is rerendered it would rerender my course's select element with the plugin.

$this->dispatchBrowserEvent('initListBox');

I also removed the listeners for the component as that was the path that did not give a working solution.

Then I created these two methods that run from the javascript as given above.

public function selectCourse($course)
    {
        $this->selectedCourses[] = $course;
    }

    public function removeCourse($course)
    {
        if ($this->semesterIdToDuplicate != 0) {
            $this->semesterIdToDuplicate = 0;
        }

        $key = array_search($course, $this->selectedCourses);
        if (false !== $key) {
            unset($this->selectedCourses[$key]);
        }
    }
Activity icon

Replied to Livewire Component Not Removing Items Correctly

What I ended up doing was adding these two events to the javascript.

addEvent: function (value) {
    @this.call('selectCourse', value);
},
removeEvent: function (value) {
    @this.call('removeCourse', value);
},
window.addEventListener('livewire:load', function() {
    KTDualListbox.init();
});

window.addEventListener('initListBox', function() {
    KTDualListbox.init();
});

I added this to the top of the render method so that every time the component is rerendered it would rerender my course's select element with the plugin.

$this->dispatchBrowserEvent('initListBox');

I also removed the listeners for the component as that was the path that did not give a working solution.

Then I created these two methods that run from the javascript as given above.

public function selectCourse($course)
    {
        $this->selectedCourses[] = $course;
    }

    public function removeCourse($course)
    {
        if ($this->semesterIdToDuplicate != 0) {
            $this->semesterIdToDuplicate = 0;
        }

        $key = array_search($course, $this->selectedCourses);
        if (false !== $key) {
            unset($this->selectedCourses[$key]);
        }
    }
Apr
10
4 weeks ago
Activity icon

Started a new Conversation Livewire Component Not Removing Items Correctly

I'm trying to figure out two things.

  1. When I have semesterIdToDuplicate set to a value of 0 and I add more than one course to to the selectedCourses array then remove one of them, they all get removed from the selectedCourses array.

  2. If I have the semesterIdToDuplicate set to anything other than 0 and selectedCourses has more than 0 items in its array, once a selectedCourse is removed then I have semesterIdToDuplicate set to 0 which all works but it doesn't actually remove that one item.

Does anyone see why this happens? Not sure with this isn't working.

I have included the Livewire component as well as the blade attached to the component.

<?php

namespace App\Http\Livewire;

use App\Models\Course;
use App\Models\Semester;
use Livewire\Component;

class CreateSemesterCourses extends Component
{
    protected $listeners = ['courseRemoved' => 'countRemainingCourses'];

    /**
     *  @var App\Models\Semester
     */
    public Semester $semester;

    /**
     * List of all courses.
     *
     * @var array
     */
    public $courses;

    /**
     * Semester that will duplicated.
     *
     * @var int
     */
    public $semesterIdToDuplicate;

    /**
     * List of courses of semester to duplicate.
     *
     * @var array
     */
    public $selectedCourses;

    /**
     * Apply properties to the instance.
     *
     * @param  App\Models\Semester $semester
     * @return void
     */
    public function mount(Semester $semester)
    {
        $this->semester = $semester;
        $this->courses = Course::allForDropdown()->toArray();
    }

    /**
     * Display a list of resources.
     *
     * @return \Illuminate\View\View
     */
    public function render()
    {
        return view('livewire.semesters.create-semester-courses', [
            'semesters' => Semester::orderBy('start_date')->pluck('name', 'id')->prepend('Please choose a semester', '0'),
            'semester' => $this->semester,
            'courses' => $this->courses,
        ]);
    }

    /**
     * Updates selected courses of semester to duplicate.
     *
     * @param  int $value
     * @return array
     */
    public function updatedSemesterIdToDuplicate($value)
    {
        if ($value == 0) {
            dd('testing');
            if (count($this->selectedCourses) == 0) {
                return $this->selectedCourses = [];
            }

            $this->dispatchBrowserEvent('livewire:load');
        } else {
            $duplicateSemester = Semester::find($value);

            $courses = $duplicateSemester->courseSections->map(function ($section) {
                return $section->course;
            });

            $uniqueCourses = $courses->unique(function ($course) {
                return $course->name;
            });

            $uniqueCourses->map(function ($course) {
                return [
                'label' => $course->name,
                'value' => $course->id,
            ];
            })->toArray();

            $this->selectedCourses = $uniqueCourses->pluck('id')->toArray();

            $this->dispatchBrowserEvent('livewire:load');
        }
    }

    public function countRemainingCourses()
    {
        if ($this->semesterIdToDuplicate != 0 && count($this->selectedCourses) != 0) {
            $this->semesterIdToDuplicate = 0;
        }
    }
}
<div>
    <x-input.group label="Make Duplicate Of" for="semesterIdToDuplicate" :error="$errors->first('duplicate')">
        <x-input.select
            id="semesterIdToDuplicate"
            wire:model="semesterIdToDuplicate"
            :options="$semesters"
            selectedOption="{{ old('semesterIdToDuplicate', $semester->exists ? $semester->default : '')  }}"
        />
    </x-input.group>

    <x-input.group label="Courses" for="courses_listbox" :error="$errors->first('courses')">
        <x-input.dual-listbox
            id="courses_listbox"
            name="courses[]"
            class="dual-listbox"
            :options="$courses"
            :selectedOptions="$selectedCourses"
            multiple
        />
    </x-input.group>
</div>

@push('scripts')
    <script>
    // Class definition
    var KTDualListbox = function() {
        // Private functions
        var coursesListBox = function () {
            // Dual Listbox
            var _this = document.getElementById('courses_listbox');

            // init dual listbox
            var dualListBox = new DualListbox(_this, {
                addEvent: function (value) {

                },
                removeEvent: function (value) {
                    Livewire.emit('courseRemoved')
                },
                availableTitle: 'Available courses',
                selectedTitle: 'Selected courses',
                addButtonText: 'Add',
                removeButtonText: 'Remove',
                addAllButtonText: 'Add All',
                removeAllButtonText: 'Remove All',
            });
        };

        return {
            // public functions
            init: function() {
                coursesListBox();
            },
        };
    }();

    window.addEventListener('livewire:load', function() {
        KTDualListbox.init();
    });
    </script>
@endpush
Apr
09
1 month ago
Activity icon

Replied to Creating An Assoc. Array Of Next 5 Years

@michaloravec

So I need something like this maybe but there is a syntax error there unless you know a better way?

$years = [];

foreach (range(now()->year, now()->year + 5)) as year) {
    $years[] = [
        'label' => $year,
        'value' => $year
    ];
}
dd($years);
Activity icon

Replied to Creating An Assoc. Array Of Next 5 Years

Oh that makes sense. I need to make each of them an array so that it has a label and value keys.

Activity icon

Replied to Creating An Assoc. Array Of Next 5 Years

It does display as this which looks exactly the way it was supposed to but for some reason my select doesn't like it giving a foreach() argument must be of type array|object, int given.

array:7 [▼
  0 => "Please Choose A Year"
  2021 => 2021
  2022 => 2022
  2023 => 2023
  2024 => 2024
  2025 => 2025
  2026 => 2026
]
<x-input.select id="year" name="year" :options="$years" selectedOption="{{ old('year', $semester->exists ? $semester->year : '')  }}" />
@props([
    'options' => [],
    'selectedOption' => ''
])

<select {{ $attributes->merge(['class' => 'form-control']) }}>
    @foreach($options as $value => $label)
        <option value="{{ $value }}" {{ $selectedOption == $value ? 'selected="selected"' : ''}}>{{ $label }}</option>
    @endforeach
</select>
Activity icon

Replied to Creating An Assoc. Array Of Next 5 Years

Because I have other arrays that are prepared differently and want to make sure I have the arrays prepared correctly for each one.

Activity icon

Replied to Creating An Assoc. Array Of Next 5 Years

My apologies I was looking to have both the keys and values be the same year.

So it should be a final array as such.

array:6 [▼
  0 => "Please Choose A Year"
  2022 => 2022
  2023 => 2023
  2034 => 2024
  2025 => 2025
  2026 => 2026
]
Activity icon

Replied to Creating An Assoc. Array Of Next 5 Years

Yes but I'm using blade components so I need to prepare the right data in the correct manner for this.

Activity icon

Started a new Conversation Creating An Assoc. Array Of Next 5 Years

Looking for suggestions on rewriting this so that the years array looks like this.

@php
$years = [
    \Carbon\Carbon::today()->year,
    \Carbon\Carbon::today()->addYear()->year,
    \Carbon\Carbon::today()->addYears(2)->year,
    \Carbon\Carbon::today()->addYears(3)->year,
    \Carbon\Carbon::today()->addYears(4)->year,
    \Carbon\Carbon::today()->addYears(5)->year,
];
@endphp
@include('semesters.partials.form', [
    'years' => array_merge([0 => 'Please Choose A Year'], array_combine($years, $years))
])
Activity icon

Awarded Best Reply on Livewire On Change Event Not Updating Element

I was able to fix this by removing the wire.model="courses".

Activity icon

Replied to Livewire On Change Event Not Updating Element

I was able to fix this by removing the wire.model="courses".

Activity icon

Replied to Livewire On Change Event Not Updating Element

I was able to get this to work BUT when the livewire component rerenders it loses its javascript of not turning it into a special DualListBox plugin instance since its instantiated in my layout file. What can I do to rerender it with the special plugin instance.

Activity icon

Replied to Livewire On Change Event Not Updating Element

My goal here is to when the page loads display all courses which it does correctly. When the user updates the default property, I need it to get all of the courses attached to the default semester and when it rerenders the component, mark the courses that are inside of the selectedCourses as having selected attribute.

<?php

namespace App\Http\Livewire;

use App\Models\Course;
use App\Models\Semester;
use Livewire\Component;

class CreateSemesterCourses extends Component
{
    public Semester $semester;

    public $courses;

    public $default;

    public $selectedCourses;

    public function mount(Semester $semester)
    {
        $this->semester = $semester;
        $this->courses = Course::allForDropdown()
                            ->prepend(['label' => 'Please choose a course', 'value' => 0])
                            ->toArray();
    }

    /**
     * Display a list of resources.
     *
     * @return \Illuminate\View\View
     */
    public function render()
    {
        return view('livewire.semesters.create-semester-courses', [
            'semesters' => Semester::orderBy('start_date')->pluck('name', 'id'),
            'semester' => $this->semester,
            'courses' => $this->courses,
        ]);
    }

    public function updatedDefault($value)
    {
        $duplicateSemester = Semester::find($value);

        $courses = $duplicateSemester->courseSections->map(function ($section) {
            return $section->course;
        });

        $uniqueCourses = $courses->unique(function ($course) {
            return $course->name;
        });

        $this->selectedCourses = $uniqueCourses->map(function ($course) {
            return [
                'label' => $course->name,
                'value' => $course->id,
            ];
        })->toArray();
    }
}

<x-input.dual-listbox
    id="courses_listbox"
    wire:model="courses"
    name="courses[]"
    class="dual-listbox"
    :options="$courses"
    :selectedOptions="$selectedCourses"
    multiple
/>
@props([
    'options' => [],
    'selectedOptions' => [],
])

<select {{ $attributes->merge(['class' => 'form-control']) }}>
    @foreach ($options as $option)
        <option value="{{ $option['value'] }}" {{ in_array($option['value'], $selectedOptions) ? 'selected="selected"' : '' }}>{{ $option['label'] }}</option>
    @endforeach
</select>
Apr
08
1 month ago
Activity icon

Replied to Livewire On Change Event Not Updating Element

Actually I fixed the problem and just need to figure out why it won't apply the selected attribute to the selectedOptions that are found in the select.

Activity icon

Replied to Livewire On Change Event Not Updating Element

@tykus Its a select element with added functionality on the frontend. The current error says that what is passed to the selectOptions is a collection instead of an array.

n_array(): Argument #2 ($haystack) must be of type array, Illuminate\Support\Collection given (View: /app/resources/views/components/input/dual-listbox.blade.php) (View: /app/resources/views/components/input/dual-listbox.blade.php)
Activity icon

Replied to Livewire On Change Event Not Updating Element

@tykus I'm trying to figure out what between the selectedOptions, wire:model and options I nee to pass in to the dual-list-box component.

Activity icon

Replied to Livewire On Change Event Not Updating Element

@tykus I like that as a better way of handling the situation, however, it still renders the same way when an option is clicked for the first select box.

This is the dual-list-box component. It shows the options but does not show a value or label for the options when it rerenders.

@props([
    'options' => [],
    'selectedOptions' => [],
])

<select {{ $attributes->merge(['class' => 'form-control']) }}>
    @foreach ($options as $option)
        <option value="{{ $option['value'] }}" {{ in_array($option['value'], $selectedOptions) ? 'selected="selected"' : '' }}>{{ $option['label'] }}</option>
    @endforeach
</select>
Activity icon

Started a new Conversation Livewire On Change Event Not Updating Element

I'm trying to figure out why my livewire blade file isn't displaying the list of courses for the changed semester. If I dump the courses as the last line in the changeEvent method I get the right options, but it doesn't render the options in the select element. On initial page load it displays all courses as desired.

<div>
    <x-input.group label="Make Duplicate Of" for="duplicate" :error="$errors->first('duplicate')">
        <x-input.select id="default" wire:click="changeEvent($event.target.value)" name="default" :options="$semesters" selectedOption="{{ old('default', $semester->exists ? $semester->default : '')  }}" />
    </x-input.group>

    <x-input.group label="Courses" for="courses_listbox" :error="$errors->first('courses')">
        <x-input.dual-listbox wire:model="courses" id="courses_listbox" name="courses[]" class="dual-listbox" :options="$courses" :selectedOptions="old('courses', $semester->courses ? $semester->courses : [])" multiple />
    </x-input.group>
</div>
<?php

namespace App\Http\Livewire;

use App\Models\Course;
use App\Models\Semester;
use Livewire\Component;

class CreateSemesterCourses extends Component
{
    public Semester $semester;

    public $courses;

    public function mount(Semester $semester)
    {
        $this->semester = $semester;
        $this->courses = Course::allForDropdown()->prepend(['label' => 'Please choose a course', 'value' => 0]);
    }

    /**
     * Display a list of resources.
     *
     * @return \Illuminate\View\View
     */
    public function render()
    {
        return view('livewire.semesters.create-semester-courses', [
            'semesters' => Semester::orderBy('start_date')->pluck('name', 'id'),
            'semester' => $this->semester,
            'courses' => $this->courses,
        ]);
    }

    public function changeEvent($value)
    {
        $duplicateSemester = Semester::find($value);

        $courses = $duplicateSemester->courseSections->map(function ($section) {
            return $section->course;
        });

        $uniqueCourses = $courses->unique(function ($course) {
            return $course->name;
        });

        $this->courses = $uniqueCourses;
    }
}
Apr
07
1 month ago
Activity icon

Replied to Laravel Blade Component Slot Merging Classes

@martinbean I understand that but my question is how can I only apply extra classes to the card-body div only.

Activity icon

Started a new Conversation Laravel Blade Component Slot Merging Classes

Should I have bodyClasses as an attribrute or a prop as its not required. I would like to make sure that in the div that surrounds the component slot that I want to add additional classes passed to the component.

How should this be handled?

<x-card title="Test Card Title" bodyClasses="whateverClassesHere>
	Whatever code for the slot
</x-card>
@props(['bodyClasses' => ''])

<!--begin::Card-->
<div class="card card-custom">
    <!--begin::Header-->
    <div class="card-header">
        <div class="card-title">
            <h3 class="card-label">{{ $title }}</h3>
        </div>
        <div class="card-toolbar">
            {{ $toolbar }}
        </div>
    </div>
    <!--end::Header-->
    <!--begin::Body-->
    <div {{ $attributes->merge(['class' => 'card-body ' .$bodyClasses]) }}>
        {{ $slot }}
    </div>
    <!--end::Body-->
</div>
<!--end::Card-->
Apr
06
1 month ago
Activity icon

Started a new Conversation Using Attributes Of A Model If Passed Into Factory

I'm trying to figure out how I can handle the situation that when I pass in a semester model then it will use its start and end dates but if I don't provide one then it will generate a new factory and use its dates.

Is this possible?

public function definition()
    {
        $courseSection = CourseSection::factory()->create();
        $semester = Semester::factory()->create();

        return [
            'course_section_id' => $courseSection->id,
            'semester_id' => $semester->id,
            'start_date' => Carbon::parse($semester->start_date)->is($courseSection->day) ?
                Carbon::parse($semester->start_date) :
                Carbon::parse($semester->start_date)->next($courseSection->day),
            'end_date' => Carbon::parse($semester->end_date)->is($courseSection->day) ?
                Carbon::parse($semester->end_date) :
                Carbon::parse($semester->end_date)->previous($courseSection->day),
        ];
    }
Activity icon

Started a new Conversation Querying Non Directly Associated Models

I'm looking for the right query for this situation. I need to get all the different courses that are scheduled for a particular semester. This is a little challenging for me since coures aren't directly associated with a semester. I recently had to change my database structure so I'm having to now update this query so that I can correctly retrieve these different cources.

ALSO: Is there where a hasManyThrough would come into play for connecting semesters and courses?

Old Query

$query = Course::query()
            ->whereHas('semesters', function (Builder $query) {
                $query->where('semester_id', $this->semester->id);
            })
            ->join('course_semester', 'course_semester.course_id', '=', 'courses.id');
Schema::create('course_section_semester', function (Blueprint $table) {
    $table->id();
    $table->foreignId('course_section_id')->constrained();
    $table->foreignId('semester_id')->constrained();
    $table->date('start_date');
    $table->date('end_date');
    $table->timestamps();
});

Schema::create('course_sections', function (Blueprint $table) {
    $table->id();
    $table->foreignId('course_id')->constrained();
    ...
    $table->timestamps();
});

Semester.php

public function courseSections()
{
    return $this->belongsToMany(CourseSection::class)->using(CourseSectionSeemster::class);
}

CourseSection.php

public function course()
{
    return $this->belongsTo(Course::class);
}
Apr
05
1 month ago
Activity icon

Replied to Default Model Structure

@bugsysha I redid my database table structures because the tables certain data was being stored in was wrong. I now have the following datatabe tables. The problem I am having with rewriting this is now with updating the migrations I have a foreign key that is too long.

Is there a better way I can name these tables so that I can have a shorter foreign key.

SQLSTATE[42000]: Syntax error or access violation: 1059 Identifier name 'course_section_semester_student_course_section_semester_id_foreign' is too long (SQL: alter table course_section_semester_student add constraint course_section_semester_student_course_section_semester_id_foreign foreign key (course_section_semester_id) references course_section_semester (id))

Schema::create('course_section_semester_student', function (Blueprint $table) {
            $table->id();
            $table->foreignId('course_section_semester_id')->constrained('course_section_semester');
            $table->foreignId('student_id')->constrained('users');
            $table->timestamps();
        });
courses
    id
   name
   slug
   ...

semsters
    id 
   name (eg. Fall 2021)
   slug
   ...

course_section_semester
   id
   course_section_id
   semster_id
   start_date
   end_date
   ...

course_section
   course_Id
   teacher_id
   day
   start_time
   end_time 
   ...

course_section_semster_student
    course_section_semester_id
    student_id
Activity icon

Replied to Default Model Structure

@bugsysha I'm wondering where the mix up for me is with understanding this, because what I believe I need to do is rethink the db structure because a semester as of right now only has the name and slug and start dates for real data. I need to setup default course_sections with but those are attached to the id of the course_semester pivot table.

<?php

namespace App\Models;

class DefaultSpringSemester extends Semester
{
    protected const ID_OF_THE_DEFAULT_SEMESTER = 1;

    protected function __construct()
    {
        parent::__construct(func_get_args());
    }

    protected $attributes = [
        'attribute' => 1, // and so on for all attributes
    ];

    protected $with = [
        'coursesSemsters',
    ];

    public function courseSemesters()
    {
        return $this->belongsToMany(CourseSemester::class)
            ->whereIn('semster_id', [static::ID_OF_THE_DEFAULT_SEMESTER]);
    }

    public static function mirror($acceptDynamicAttributes): Semester
    {
        $defaultSpringSemester = CourseSemester::find(static::ID_OF_THE_DEFAULT_SEMESTER);
        $newSpringSemesterCourses = $defaultSpringSemester->replicate();
        $newSpringSemesterCourses->fill($acceptDynamicAttributes);
        $newSpringSemesterCourses->push();

        return $newSpringSemesterCourses;
    }
}
Activity icon

Replied to Default Model Structure

@bugsysha The problem here will be needing to duplicate not only the values of the pivot table course_semester but also the course_section table.

Activity icon

Replied to Default Model Structure

@bugsysha I'm wondering how I could do it inside the code because yes I agree it would be faster and easier but not sure how this would be implemented. Are you able to provide a small example?

Activity icon

Started a new Conversation Default Model Structure

I have a page that an admin can create a new school semester with a name and dates for when it starts and ends. What I'm trying to decide is how I should I create a course schedule for that semester. I realize there could be many different suggetions here because of different ways of handling this situation.

Method One I could have a model that is called DefaultSemesterCourseSchedule that represents a pivot model that belongs to a Semester Type (Spring, Summer, Fall) model and belongs to a Course model. Then I can just copy all of the matches for that type of model and duplicate them in the course_semester pivot table. As you can see I don't currently have a semester type so that would be something I would need to add.

Does anyone have any other ideas on how I could implement this feature?

Table Structure

semsters
    id 
   name (eg. Fall 2021)
   slug
   start_date
   end_date
   ...

course_semster
   id
   course_id
   semster_id
   ...

course_section
   course_semester_Id
   teacher_id
   start_date
   end_date
   ...
Apr
03
1 month ago
Activity icon

Replied to Unique Rule After Validation

How can I make sure that the individual fields themselves validate successfully before it hits the concatenated validated?

Apr
02
1 month ago
Activity icon

Replied to Unique Rule After Validation

I don’t understand what you are saying. I have a column in the database called (name). After term and year are validated I want to concat them together and make sure that the concatenated string doesn’t match a column value for (name).

Activity icon

Replied to Unique Rule After Validation

I think you did. I need to figure out that as long both the term and year fields pass then con are are both their values and then do database query to make sure that the concatenated string doesn’t match another column in the database.

Activity icon

Started a new Conversation Unique Rule After Validation

I am currently trying to validate two fields in my form that one is a string and the other is a number. I can get both of these to pass, however, the next validation I need to take place is to check to make sure the two fields concatenated together doesn't already exist in a database table. I have included the rules below

My first thought is to do a after validation hook and query the db to see if the model exists with that concatenated name but didn't know if there was a better way of handling this situation.

public function rules()
{
    return [
        'term' => ['required', 'string', Rule::in(['Spring', 'Summer', 'Fall'])],
        'year' => ['required', 'numeric', 'digits:4'],
    ];
}
Activity icon

Replied to Accessing A Pivot Table Column ID For Ohter Model Factory

@bugsysha I definitely took your advice and made the seeder simpler and easier for modification in case requirements change. The one thing I noticed after the refactoring is that the dates for the course in a semester seem to get passed around throughout the code. How can I fix that?

<?php

namespace Database\Seeders;

use App\Models\Course;
use App\Models\CourseSection;
use App\Models\CourseSemester;
use App\Models\Semester;
use App\Models\Teacher;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Seeder;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Str;

class SemestersTableSeeder extends Seeder
{
    use WithFaker;

    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $this->setUpFaker();

        $this->generateSemesters();
    }

    /**
     * Generate semesters needed for seeder.
     *
     * @return void
     */
    protected function generateSemesters()
    {
        foreach ($this->generateSemesterNames() as $semesterName) {
            $courseDates = $this->generateCourseDates($semesterName);

            $semester = Semester::factory()->create(['name' => $semesterName]);
            $courses = Course::inRandomOrder()->take(5)->get();

            $this->createCourseRequirements($semester, $courses, $courseDates['startDate'], $courseDates['endDate']);
        }
    }

    /**
     * Create semester names.
     *
     * @return array
     */
    protected function generateSemesterNames()
    {
        $seasons = ['Spring', 'Summer', 'Fall'];
        $years = [date('Y'), date('Y', strtotime('-1 year')), date('Y', strtotime('-2 years'))];
        $semesterNames = [];

        foreach ($years as $year) {
            foreach ($seasons as $season) {
                $semesterNames[] = "{$season} {$year}";
            }
        }

        return $semesterNames;
    }

    /**
     * Creates dates for each course during the semester.
     *
     * @param  string $semesterName
     * @return array
     */
    protected function generateCourseDates($semesterName)
    {
        $dates = [];

        if (Str::of($semesterName)->startsWith('Spring')) {
            $dates['startDate'] = Carbon::parse('first day of February '.Str::of($semesterName)->after('Spring '));
            $dates['endDate'] = Carbon::parse('first day of June '.Str::of($semesterName)->after('Spring '));
        } elseif (Str::of($semesterName)->startsWith('Summer')) {
            $dates['startDate'] = Carbon::parse('first day of June '.Str::of($semesterName)->after('Summer '));
            $dates['endDate'] = Carbon::parse('first day of September '.Str::of($semesterName)->after('Summer '));
        } elseif (Str::of($semesterName)->startsWith('Fall')) {
            $dates['startDate'] = Carbon::parse('first day of September '.Str::of($semesterName)->after('Fall '));
            $yearString = (string) Str::of($semesterName)->after('Fall ');
            $yearInt = (int) $yearString + 1;
            $dates['endDate'] = Carbon::parse('first day of January '.(string) $yearInt);
        }

        return $dates;
    }

    /**
     * Create course requirements during a semester.
     *
     * @param  App\Models\Semester $semester
     * @param  App\Models\Course $course
     * @param  string $startDate
     * @param  string $endDate
     * @return void
     */
    protected function createCourseRequirement($semester, $course, $startDate, $endDate)
    {
        $courseSemester = $this->createCourseSemester($semester, $course, $startDate, $endDate);

        $this->createCourseSection($courseSemester);
    }

    /**
     * Create coure requirements for each course in a semester.
     *
     * @param  App\Models\Semester $semester
     * @param  \Illuminate\Database\Eloquent\Collection $courses
     * @return void
     */
    protected function createCourseRequirements(Semester $semester, Collection $courses, $startDate, $endDate)
    {
        foreach ($courses as $course) {
            $this->createCourseRequirement($semester, $course, $startDate, $endDate);
        }
    }

    /**
     * Create a course section for a course in a semester.
     *
     * @param  App\Models\CourseSemester $courseSemester
     * @return void
     */
    protected function createCourseSection(CourseSemester $courseSemester)
    {
        CourseSection::factory()->create([
            'course_semester_id' => $courseSemester->id,
            'teacher_id' => Teacher::inRandomOrder()->first()->id,
            'start_time' => $startTime = Carbon::parse($this->faker->time('H:00')),
            'end_time' => $startTime->copy()->addHour(),
        ]);
    }

    /**
     * Create a course semester.
     *
     * @param  App\Models\Semester $semester
     * @param  App\Models\Course $course
     * @param  string $startDate
     * @param  string $endDate
     * @return App\Models\CourseSemester
     */
    protected function createCourseSemester($semester, $course, $startDate, $endDate)
    {
        return CourseSemester::factory()->create([
            'semester_id' => $semester->id,
            'course_id' => $course->id,
            'start_date' => $startDate,
            'end_date' => $endDate,
        ]);
    }
}