brentxscholl

Member Since 6 Years Ago

North Battleford, Sask

Experience Points
32,190
Total
Experience

2,810 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
388
Lessons
Completed
Best Reply Awards
0
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 7
32,190 XP
Mar
03
3 days ago
Activity icon

Replied to Action [email protected] Not Defined

Try

return redirect()->action([DashboardController::class, 'index'])
Activity icon

Replied to Handling Pre-existing Images When Editing A Model Using Livewire & Filepond

With the above solution for loading the pre-existing files, how would I handle the images when the user saves? I would need to check if they uploaded new images, and save those to to the file system and db, and I would need to set the order of all the images (which are a mix of pre-existing and new) and reflect it in the database.

With the reordering the real catch is this part here

// This allows me to reorder the images, essential resetting the $image variable in livewire component when ever the user reorders the images in filepond
                onreorderfiles(files, origin, target){
                    @this.set('images', null);
                    files.forEach(function(file) {
                        @this.upload('images', file.file);
                    });
                },

I'm not sure how I could handle reordering images that are both pre-existing and newly uploaded to filepond.

@tykus If you have a fully functioning filepond for when a user edits a model with images, I would really appreciate some advice.

Activity icon

Replied to Generate Unique Slugs If The Name Contains Special Characters

You may have luck with this https://github.com/spatie/laravel-sluggable

Its a simple package to utilize.

By default the package will generate unique slugs by appending '-' and a number, to a slug that already exists.

So your "1/2" and "12" will for sure be unique if that is what you are after.

Feb
28
6 days ago
Activity icon

Replied to Livewire Testing Nested Properties

Sorry, that was just a typo in my question. Still having the same issue

Feb
27
1 week ago
Activity icon

Started a new Conversation Livewire Testing Nested Properties

I have a component with nested properties and I'm having a hard time figuring out how to set() and assertHasErrors() when testing the component.

Here is my component:

public $schedules = [
    'start_date'        => null,
    'timeslots'         => [
        0 => [
            'start_time' => null,
            'end_time'   => null,
            'spots'      => 1,
        ],
    ],
];

// Rules

public $rules = [
            'schedules.*.start_date' => 'required',
            'schedules.*.timeslots.*.start_time' => 'required',
            'schedules.*.timeslots.*.end_time' => 'required',
            'schedules.*.timeslots.*.spots' => 'required|numeric|min:1',
];

public function saveSchedule(){
	$this->validate();

	// ......
}

In my test im trying to call saveSchedule() without any properties set, and I want to assert that im getting the errors for the properties

Here is my test:


public function cannot_save_schedule_without_required_inputs() {
            $response = Livewire::Test(ScheduleBuilder::class)
                ->call('saveSchedule');

            $response->assertHasErrors([
                'schedules.*.start_date',
                'schedules.*.timeslots.*.start_time',
                'schedules.*.timeslots.*.end_time',
                'schedules.*.timeslots.*.spots',
            ]);
}

I'm getting this error Component missing error: schedules.*.start_date

How do you handle nested properties when setting and asserting?

Feb
26
1 week ago
Activity icon

Replied to Handling Pre-existing Images When Editing A Model Using Livewire & Filepond

Apologies for the late response (busy week)

Thank you for your clear response!

This works great for displaying the images in Filepond.

How would you go about updating the images on the server side using livewire?

I see you have the $image->id in the source, but how can you access this data in livewire on save?

Thanks again for the help!

Feb
20
2 weeks ago
Activity icon

Started a new Conversation Handling Pre-existing Images When Editing A Model Using Livewire & Filepond

I have a Filepond component that works great for uploading images to a post.

However, I'm struggling with Filepond when needing to edit a post and its pre-exisiting images.

I want to load Filepond with the Post model's pre-existing images. The goal is to allow the user to upload, delete and reorder the images when editing the Post model, then update the database and the file system.

This is what I have so far:

<div
        x-data=""
        x-init="
            // Plugins
            FilePond.registerPlugin(FilePondPluginImagePreview);
            FilePond.registerPlugin(FilePondPluginImageExifOrientation);
            FilePond.registerPlugin(FilePondPluginFileValidateType);
            FilePond.registerPlugin(FilePondPluginFileValidateSize);
            FilePond.registerPlugin(FilePondPluginImageResize);

            // Set options
            FilePond.setOptions({
                allowMultiple: true,
                allowReorder: true,
                itemInsertLocation: 'after',
                server: {
                    process: (fieldName, file, metadata, load, error, progress, abort, transfer, options) => {
                        @this.upload('images', file, load, error, progress)
                    },
                    revert: (filename, load) => {
                        @this.removeUpload('images', filename, load)
                    },
                },
                // This allows me to reorder the images, essential resetting the $image variable in livewire component when ever th euser reorders the images in filepond
                onreorderfiles(files, origin, target){
                    @this.set('images', null);
                    files.forEach(function(file) {
                        @this.upload('images', file.file);
                    });
                },

            });

            // Create Filepond
            const pond = FilePond.create($refs.input, {
                acceptedFileTypes: ['image/png', 'image/jpeg'],
                
                @if(optional($post)->images) // If we are editing a post and if that post has images
                files: [
                    @foreach($post->images as $image)// Loop through each image for the post
                        {
                            // the server file reference
                            source: '{{ Storage::disk('post_images')->url($post->id . '/' . $image->filename.$image->extension) }}', 
                        },
                    @endforeach
                ],
                @endif
            });

            pond.on('addfile', (error, file) => {
                if (error) {
                    console.log('Oh no');
                    return;
                }
            });
        "
    >
        <div wire:ignore wire:key="images">
                <input
                    id="image-upload"
                    type="file"
                    x-ref="input"
                    multiple
                >

                @error('images.*')
                <p wire:key="error_images" class="mt-2 text-sm text-red-600" id="email-error">{{ $message }}</p>
                @enderror
        </div>
    </div>

However this is causing all of the images to re-upload every time the user view the edit page.

There is a lot online on how to upload images using filepond and livewire, but not really much on how to edit.

Is there a better way to manage images, other than reuploading every time the user views the edit page?

Any help with this would greatly be appreciated.

Feb
15
2 weeks ago
Activity icon

Awarded Best Reply on Livewire And FilePond. Change Image Order

Not sure if this is correct, but it seems to work

I added this to FilePond.setOptions()

FilePond.setOptions({
                allowMultiple: true,
                allowReorder: true,
                server: {
                    process: (fieldName, file, metadata, load, error, progress, abort, transfer, options) => {
                        @this.upload('images', file, load, error, progress)
                    },
                    revert: (filename, load) => {
                        @this.removeUpload('images', filename, load)
                    },
                },

                // Added this ----------------------------------------
                onreorderfiles(files, origin, target){
                    @this.set('images', null);
                    files.forEach(function(file) {
                        @this.upload('images', file.file);
                    });
                },
            });

This removes the previous uploaded images and reuploads with the new order.

Feb
14
2 weeks ago
Activity icon

Replied to Livewire And FilePond. Change Image Order

Not sure if this is correct, but it seems to work

I added this to FilePond.setOptions()

FilePond.setOptions({
                allowMultiple: true,
                allowReorder: true,
                server: {
                    process: (fieldName, file, metadata, load, error, progress, abort, transfer, options) => {
                        @this.upload('images', file, load, error, progress)
                    },
                    revert: (filename, load) => {
                        @this.removeUpload('images', filename, load)
                    },
                },

                // Added this ----------------------------------------
                onreorderfiles(files, origin, target){
                    @this.set('images', null);
                    files.forEach(function(file) {
                        @this.upload('images', file.file);
                    });
                },
            });

This removes the previous uploaded images and reuploads with the new order.

Activity icon

Started a new Conversation Livewire And FilePond. Change Image Order

I'm using Livewire and Filepond to allow users to upload images to a gallery.

I need my users to be able to set the order of the images and save that to the database.

Filepond has an option allowReorder: true and a callback that fires when the order has been changed onreorderfiles(files, origin, target)

Here is the basics of my upload component

<div
    x-data="{ 'images': null }"
    x-init="
        FilePond.registerPlugin(FilePondPluginImagePreview);
        FilePond.registerPlugin(FilePondPluginImageExifOrientation);
        FilePond.registerPlugin(FilePondPluginFileValidateType);
        FilePond.registerPlugin(FilePondPluginFileValidateSize);
        FilePond.registerPlugin(FilePondPluginImageResize);

        FilePond.setOptions({
            allowMultiple: true,
            allowReorder: true,
            server: {
                process: (fieldName, file, metadata, load, error, progress, abort, transfer, options) => {
                    @this.upload('images', file, load, error, progress)
                },
                revert: (filename, load) => {
                    @this.removeUpload('images', filename, load)
                },
            },
            onreorderfiles(files, origin, target){
                // **** What do I  put here to update the order of the images in my livewire component? ******
            },
        });

        const pond = FilePond.create($refs.input, {
            acceptedFileTypes: ['image/png', 'image/jpeg'],
            maxFileSize: '7MB',
            allowImageCrop: true,
            allowImageResize: true,
            imageResizeTargetWidth: '1000px',
            imageResizeTargetHeight: '1000px',
        });

        pond.on('addfile', (error, file) => {
            if (error) {
                console.log('Oh no');
                return;
            }
            images = true;
        });
    "
>
    <div wire:ignore wire:key="images">
        <div x-show="images == null" class="ex-builder-no-images">
            <i class="fas fa-image"></i>
            <p>There are no images for this experience.
                <br>Upload some below. <br><small>(MAX 10 Images)</small></p>
        </div>
        <div class="form-group text-center">
            <input
                id="image-upload"
                type="file"
                x-ref="input"
                multiple
            >
            @error('images.*')
            <p wire:key="error_images" class="mt-2 text-sm text-red-600" id="email-error">{{ $message }}</p>
            @enderror
        </div>
    </div>
</div>

I'm also showing a preview of the first image in the gallery (this is the gallery's featured image) like this <img src="{{ $images ? $images[0]->temporaryUrl() : '/images/placeholder.jpg' }}"> I'm expecting this image to update after the user drags a new image to be the first.

How can I update the image order in the public $images = []; found in my livewire componenet using the onreoderfiles() callback?

Thanks!

Jan
18
1 month ago
Activity icon

Replied to Performance Anxiety: 1 Big Table Or 2 Smaller Tables?

Thanks for your input! I really appreciate it.

If anyone else has some input on the matter I would appreciate it as well!

Jan
17
1 month ago
Activity icon

Replied to Form Method Error

Try replacing your <a> with a <button> like this

<button type="button" onclick="return confirm({{ __('auth.are_you_sure') }});" onclick="event.preventDefault();
                                document.getElementById('delete-account-form').submit();" class="btn btn-red">
Activity icon

Started a new Conversation Performance Anxiety: 1 Big Table Or 2 Smaller Tables?

I keep on encountering this performance anxiety when building out the database structure of my projects. I'm hoping to get an outside opinion on the matter.

Which approach would you say is better when building a large scale project?

Option A. 1 large table with many columns, or

Option B. Break data up into 2 small tables with few columns, but linked with ids.

Here is an example:

Say you are building a project that showcases things to do in an area. We will call these Activities. You have an index page that list all the Activities as cards/thumbnails. Simple data that is just the Activity Title and the Activity Image.

When you view the single Activity page, there are ~20 more columns worth of data that you want to show about the activity. ie. Description, how physically demanding it is, it's location, is it indoor or outdoor, is it family friendly. etc.

Lets also say there are many places throughout the site where you would see the simple cards for the activity (title and image only). but only one time you would need all the details (when viewing the single activity page).

Which is better?:

Option A (single table)

Activity Table
-----------------------------------------------------------------------
id
title
image_id
status
description
physical_level
environment
family_friendly
location_id
start_date
end_date
start_time

Option B (multiple tables)

Activity Table
-----------------------------------------------------------------------
id
title
image_id
status

Activity Details Table
-----------------------------------------------------------------------
id
activity_id
description
physical_level
environment
family_friendly
location_id
start_date
end_date
start_time
end_time

Does it take more cpu to join tables or more to select columns in tables?

What is better for searching, if say we were wanting to search for activities based on environment field?

What is better to query with? Option A: Activity::select(['id', 'title', 'image_id'])->all() for querying activities on index page and Activity::find($id) for querying activity for single/show page.

Option B: Activity::all() for querying activities on index page and Activity::with(['activityDetails']) for querying activity for single/show page.

I appreciate any advice

Jan
12
1 month ago
Activity icon

Started a new Conversation Avoid "Trying To Get Property Of Non-object" Error In Conditional Statement

I have a simple conditional in my livewire component

 @if($client->id == $c->id)
    // some code
@else
    // some code
@endif

The catch is sometimes $client will be null. Is there a simple way to perform this conditional for both situations where $client contains a Client Object and where $client is null. Right now I of course get an error that is "Trying to get property 'id' of non-object" when $client is null

The only solution I can think of would be to write a conditional before. Like this:

@if($client)
    @if($client->id == $c->id)
        // some code
    @else
        // some code
    @endif
@endif

Is there a better way to do this? With blade or a helper function?

Thanks!

Dec
12
2 months ago
Activity icon

Commented on Installation And Usage

If you are trying to do this without a logged in user (say it's for a registration form) you need to pass the intent as a new User object

$user = new User;

return view('your-view", [
	'intent => $user->createSetupIntent()
]);
Nov
30
3 months ago
Activity icon

Awarded Best Reply on Error: Class 'Dotenv\Environment\DotenvFactory' Not Found When Running Phpunit Test

Turns out I had phpunit installed globally.

composer global remove phpunit/phpunit

did the trick.

Activity icon

Replied to Error: Class 'Dotenv\Environment\DotenvFactory' Not Found When Running Phpunit Test

Turns out I had phpunit installed globally.

composer global remove phpunit/phpunit

did the trick.

Activity icon

Started a new Conversation Error: Class 'Dotenv\Environment\DotenvFactory' Not Found When Running Phpunit Test

I have a fresh install of Laravel 8.

When I run phpunit I get an error.

Tests\Feature\ExampleTest::testBasicTest
Error: Class 'Dotenv\Environment\DotenvFactory' not found

I have tried running composer dump-autoload, and I've removed the vendor directory and ran composer update no luck.

Has anyone encountered this problem or know a possible fix?

Nov
06
4 months ago
Activity icon

Started a new Conversation Use Laravel Livewire With Laravel Fortify For Login

I'm wanting to use Laravel Fortify and Livewire to create a very simple login form. I do not want to use Jetstream as it has more features that I do not need vs features I do need.

I'm using livewire throughout my app, and would like to use it for my login page to provide real time instant validation.

The problem I am encountering is I am unable to submit the form with values if I'm using wire:model on inputs.

I also can not use auth()->attempt() because it is being hijacked by Fortify.(At least, I think it is. All know is when I use it, it returns false)

How can I use livewire with fortify? I need to send the data from the livewire component to POST /login.

Here is my current set up:

FortifyServiceProvider.php

public function boot()
    {
        Fortify::createUsersUsing(CreateNewUser::class);
        Fortify::updateUserProfileInformationUsing(UpdateUserProfileInformation::class);
        Fortify::updateUserPasswordsUsing(UpdateUserPassword::class);
        Fortify::resetUserPasswordsUsing(ResetUserPassword::class);

        // Custom Fortify Views =============================

        // Login Page
        Fortify::loginView(function () {
            return view('auth.login');
        });
   }

My auth/login.blade.php (simply calls the livewire components with the proper layout template)

<x-layouts.auth>
    @livewire('auth.login')
</x-layouts.auth>

The livewire component livewire/auth/login.blade.php:

<form wire:submit.prevent="login" action="#" method="POST">
    <div>
        <label for="email">Email address</label>
        <input wire:model="email" id="email" type="email" required autofocus>
        @error('email'){{ $message }}@enderror
    </div>

    <div>
        <label for="password">Password</label>
        <input wire:model.lazy="password" id="password" type="password" required>
        @error('password'){{ $message }}@enderror
    </div>

    <div>
        <input wire:model.lazy="remember" id="remember_me" type="checkbox">
        <label for="remember_me">Remember me</label>

        <a href="#">Forgot your password?</a>
    </div>

    <div>
        <button type="submit">Sign in</button>
    </div>
</form>

and my Http/Livewire/Auth/Login.php file for the livewire component:

class Login extends Component
{
    public $email = '';
    public $password = '';
    public $remember = false;

    protected $rules = [
        'email' => 'required|email|exists:users,email',
        'password' => 'required',
    ];

    /**
     * Shows Real time validation for email field
     */
    public function updatedEmail() {
        $this->validate(['email' => 'email|exists:users,email']);
    }

    /**
     * Logs user in when form is submitted
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Support\MessageBag
     */
    public function login()
    {
        // ******* Need to submit the form to Fortify here?? ******
    }

    /**
     * Renders the view
     * @return mixed
     */
    public function render()
    {
        return view('livewire.auth.login')
            ->layout('layouts.auth');
    }
}
Sep
16
5 months ago
Activity icon

Commented on Contact Form With Validation

Very cool! I think I like this more than vue. Is there anything to worry about due to Livewire sending so many network requests?