PeteBatin's avatar

PeteBatin wrote a comment+100 XP

2mos ago

@richin Stripe's amazing! It's been a game changer in terms of developing for payment gateways. I imagine the majority of the bad TP reviews are because they've done something bad and Stripe has put holds on their accounts.

We have so many customers using Stripe for their stores, not a single one of them has reported any bad experiences to us.

PeteBatin's avatar

PeteBatin liked a comment+100 XP

2mos ago

For anyone using Laravel 11, where the RouteServiceProvider.php is no longer in the app/Providers/ directory, you simply have to change the home config var in the config/fortify.php file.

PeteBatin's avatar

PeteBatin wrote a comment+100 XP

2mos ago

Again, no wire:key on repeated elements!

PeteBatin's avatar

PeteBatin liked a comment+100 XP

2mos ago

@lomelisan Thought so too! There's one bug though that I can't seem to be able to fix: when you do this, the cart link in the navigation nav bar seems to lose its 'focus' classes, although the URL hasn't changed.

PeteBatin's avatar

PeteBatin liked a comment+100 XP

2mos ago

@Nabiu that's having an eye for detail!

This issue arises because Livewire re-renders the entire component view whenever there's a change, such as the count property in this case. However, during this re-render, the request()->routeIs('cart') value is not present, resulting in the navigation-cart.php nav-link's active value being false. To solve this, we can maintain the previous active value during the re-render.

On your navigation-cart.blade, change request()->routeIs('cart') to $this->isActive, so you get:

<x-nav-link href="{{ route('cart') }}" :active="$this->isActive">
    {{ __('Your cart ') }} ({{ $this->count }})
</x-nav-link>

Next go to your NavigationCart.php and add:

public $isActive = false;

public function mount()
{
    $this->isActive = request()->routeIs('cart');
}

By doing this, the active value is going to be calculated just the first time the component is rendered.

So next count updates will no longer trigger a recalculation of the active value. Instead, it will retrieve the value directly from the isActive property, ensuring that your nav-link maintains its previous active status.

There's probably a cleanest way to do this, as I do not find this very scalable, but this and having a child component just for the count are the only approaches I came up with so far.

PeteBatin's avatar

PeteBatin wrote a comment+100 XP

2mos ago

@HimanhsuN the wire:click action is increment.

increment() method is then defined in Cart.php

in that method it uses ->increment('quantity) which is an Eloquent method, 'quantity' being the column name that you want to increment.

PeteBatin's avatar

PeteBatin liked a comment+100 XP

2mos ago

Worst tutorial that I ever follow...

PeteBatin's avatar

PeteBatin liked a comment+100 XP

2mos ago

@Matrich Thank you. There are really a lot of mistakes and bad practices in this course.

PeteBatin's avatar

PeteBatin liked a comment+100 XP

2mos ago

Livewire has a .fill modifier for the wire:model directive, that will automatically set the value of that property to the value of whatever the selected option of the select input is.

<select wire:model.fill="variant">
    <!-- Variant options -->
</select>
PeteBatin's avatar

PeteBatin wrote a comment+100 XP

2mos ago

No wire:key='{{ $product->id }} ???

PeteBatin's avatar

PeteBatin wrote a comment+100 XP

2mos ago

7 chapters in and the bad practices get worse! Does anyone at Laracast quality check these videos?

PeteBatin's avatar

PeteBatin liked a comment+100 XP

2mos ago

Instead of trying to find some images and put them into a folder before $product->image->path in the store-front.blade.php file I changed my image factory to this from what was originally written

'path' => $this->faker->unique()->imageUrl(),

sped things up a bit.

PeteBatin's avatar

PeteBatin wrote a comment+100 XP

2mos ago

@wblondel so far I can tell there are many problems introduced by this series. So many bad practices. Luckily I'm only here for more Livewire content and have Laravel down already.

PeteBatin's avatar

PeteBatin liked a comment+100 XP

2mos ago

In this video we introduced a N+1 problem. For each product, a database request is made to load the featured image. To solve the problem, we must change the database request in app/Livewire/StoreFront.php to:

return Product::with('image')->get();
PeteBatin's avatar

PeteBatin liked a comment+100 XP

2mos ago

I didn't understand why $product->image substitutes image path? You just used relation, but you didn't define anywhere toString for image model, which would make it possible to substitute image path.

PeteBatin's avatar

PeteBatin liked a comment+100 XP

2mos ago

@alikmanukian@gmail.com

It doesn't as far as I can see, for me it returns the object.

{&quot;id&quot;:9,&quot;product_id&quot;:3,&quot;featured&quot;:0,&quot;path&quot;:&quot;media\/example20.png&quot;,&quot;created_at&quot;:&quot;2024-02-27T12:40:09.000000Z&quot;,&quot;updated_at&quot;:&quot;2024-02-27T12:40:09.000000Z&quot;}

To render it it you would need to use $product->image->path

PeteBatin's avatar

PeteBatin liked a comment+100 XP

2mos ago

@alikmanukian@gmail.com probably it was the screencast magic

PeteBatin's avatar

PeteBatin started a new conversation+100 XP

2mos ago

Has anyone else noticed a sudden increase in warnings in the Problems tab of VS Code from the Intelephense Extension? Does anyone know if they've reduced the feature set for the freemium version and maybe that's why it's doing it?

It happened around last Thursday (12th Feb) where the most basic things are being falsely flagged up.

I also noticed that PHP Namespace Resolver had some updates recently which coincidently had an update on the 12th (first time in 3 years) but as a test I downgraded back to the the version from 3 years ago and the warnings below still appear.

Example: Working on a migration file I get the following errors

Undefined type 'Illuminate\Database\Migrations\Migration'. Undefined type 'Illuminate\Support\Facades\Schema'. Undefined type 'Illuminate\Database\Schema\Blueprint'. Undefined type 'Illuminate\Support\Facades\Schema'.

Or for a Model: Undefined type 'Illuminate\Database\Eloquent\Model'. Undefined type 'Illuminate\Database\Eloquent\Factories\HasFactory'.

PeteBatin's avatar

PeteBatin wrote a comment+100 XP

2mos ago

Sorry to say it, but so far these migrations are pretty awful. The carts migration for example, not even indicating that session_id is a foreign key... just as well I'm here for the Livewire parts.

Normally I'd say I'll update this as I go through the other chapters to see if it's been revisited but judging by the other comments I'm thinking it hasn't. I'm hoping this isn't going to turn into a bad practice tutorial.

PeteBatin's avatar

PeteBatin wrote a reply+100 XP

2mos ago

Sorry, only just seen your comment! Keep going through the course (if you haven't completed it already), I've added updated comments with code where necessary.

If you get stuck on something give me a nudge and I'll try to help out.

PeteBatin's avatar

PeteBatin wrote a comment+100 XP

2mos ago

For anyone considering this series, I'd recommend https://laracasts.com/series/livewire-3-from-scratch instead

PeteBatin's avatar

PeteBatin wrote a comment+100 XP

2mos ago

Nah..... I'm tapping out of this course.

All that JS inline is not the right way to be doing things, I'm sure some of the things that follow on are useful but there's a lot of bad habit teaching in many of the chapters so far and not enough best practice teaching.

PeteBatin's avatar

PeteBatin liked a comment+100 XP

2mos ago

Hello and thank you so much for this series, I am enjoying a lot building this application.

Even if this series is done and was published a while ago, maybe it worth a short posting the only feedback I have so far.


Maybe for any other video content, it would be interesting to disable this tailwind extension that hides classes.

It makes it a bit harder to follow through (at least for me).

I am building the app while watching, and I have to constantly pause the video and go back to try understanding what had been written and/or to just locate myself in the code.

Disabling the extension would make it easier to follow, especially given the GitHub code linked to this lesson is slightly different.

PeteBatin's avatar

PeteBatin wrote a comment+100 XP

2mos ago

A Seeder/Factory would have been good to implement at this stage.

Dude! Your style/video editing is too chaotic, we went from finalising the h3 to this

<h3 class="font-serif mb-8">Ongoing Listening Parties</h3>

And then all of a sudden saying, "maybe we don't want the text centered here" and it looking like this...

<h3 class="mb-8 font-serif text-xl font-bold text-center">Ongoing Listening Parties</h3>

Also why are we styling a div to look like a card when we've already used the x-card component and could just re-use that?

Hopefully there's a refactoring part to this course, the dashboard's becoming a bit of a mess.

Suggestion: I know this was published Sept 2024 so your style might have changed since then, but please have your style/template sorted before you hit record. All this back and forth changing styles because you've changed your mind ("maybe we'll have this.....no actually we'll have this....no I still don't like it, maybe this") makes it really difficult to keep up and follow along. We're here for code and not design.

Update: Made it to the end of this chapter, decided I'm not going to follow any more styling, the amount of edits/re-edits are insane. Wire framing will do me just fine.

PeteBatin's avatar

PeteBatin wrote a comment+100 XP

2mos ago

Request/Beg for future courses/episodes. The collapsing class attributes in your IDE makes it really hard to easily copy them. I'm having to pause/play lots so they can be entered in my dev.

PeteBatin's avatar

PeteBatin wrote a comment+100 XP

2mos ago

Future tip: The part where you say after saving that the migration had to be changed to this... (placing nullable before constrained)....should have been cut in before attempting to save the first Episode.

I paused the video when you successfully created an Episode and I didn't and then spent a lot of time going back over chapters making sure I hadn't missed anything, in the end Claude solved it for me.

For anyone else having problems, nullable() needs to be before constrained() not at the end.

public function up(): void
    {
        Schema::create('episodes', function (Blueprint $table) {
            $table->id();
            $table->foreignId('podcast_id')->nullable()->constrained()->cascadeOnDelete();
            $table->string('title')->nullable();
            $table->string('media_url');
            $table->timestamps();
        });
    }
PeteBatin's avatar

PeteBatin liked a comment+100 XP

2mos ago

@joshcirre helps leverage the relationships, i really like that approach

PeteBatin's avatar

PeteBatin wrote a comment+100 XP

2mos ago

If you're like me and you didn't upload a png file then you may have to make your method look a little like this.

    public function downloadPhoto()
    {
        $extension = pathinfo($this->form->photo_path, PATHINFO_EXTENSION);

        return response()->download(
            Storage::disk('public')->path($this->form->photo_path),
            "article.{$extension}"
        );

        //return response()->streamDownload(function () {}, "article.{$extension}");
    }
PeteBatin's avatar

PeteBatin liked a comment+100 XP

2mos ago

In laravel 11.x, casts define as a function: link to doc

protected function casts(): array
{
    return [
        'is_admin' => 'boolean',
    ];
}
PeteBatin's avatar

PeteBatin wrote a comment+100 XP

3mos ago

Thanks for this series. Made it really easy to digest.

PeteBatin's avatar

PeteBatin wrote a comment+100 XP

3mos ago

Great episode, thank you.

PeteBatin's avatar

PeteBatin wrote a comment+100 XP

3mos ago

Just one comment for the sake of my OCD....

In the last controller update UserTeamController update(), a variable name update was missed.

You have it as

        foreach($validated['teams'] as $userId => $data){
            if(isset($data['assigned'])){
                $syncData[$userId] = ['role' => $data['role']];
            }
        }

Although the end result is the same and it's just variable naming, for code accuracy/readability, it should be:

        foreach($validated['teams'] as $teamId => $data){
            if(isset($data['assigned'])){
                $syncData[$teamId] = ['role' => $data['role']];
            }
        }
PeteBatin's avatar

PeteBatin wrote a comment+100 XP

3mos ago

@hardflip welcome to the club! My biggest criticism of Laravel is it's documentation. Sometimes the older versions of the documentation contain better information than the new versions.

The API documentation lists everything but isn't too great at explaining https://api.laravel.com/docs/12.x/

PeteBatin's avatar

PeteBatin liked a comment+100 XP

5mos ago

@PeteBatin thank you for your comments.