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 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 wrote a comment+100 XP
2mos ago
Again, no wire:key on repeated elements!
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 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 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 liked a comment+100 XP
2mos ago
Worst tutorial that I ever follow...
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 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 wrote a comment+100 XP
2mos ago
No wire:key='{{ $product->id }} ???
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 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 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 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 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 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.
{"id":9,"product_id":3,"featured":0,"path":"media\/example20.png","created_at":"2024-02-27T12:40:09.000000Z","updated_at":"2024-02-27T12:40:09.000000Z"}
To render it it you would need to use $product->image->path
PeteBatin liked a comment+100 XP
2mos ago
@alikmanukian@gmail.com probably it was the screencast magic
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 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 wrote a reply+100 XP
3mos 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 wrote a comment+100 XP
3mos ago
For anyone considering this series, I'd recommend https://laracasts.com/series/livewire-3-from-scratch instead
PeteBatin wrote a comment+100 XP
3mos 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 liked a comment+100 XP
3mos 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 wrote a comment+100 XP
3mos 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 wrote a comment+100 XP
3mos 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 wrote a comment+100 XP
3mos 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 liked a comment+100 XP
3mos ago
@joshcirre helps leverage the relationships, i really like that approach
PeteBatin wrote a comment+100 XP
3mos 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 liked a comment+100 XP
3mos ago
In laravel 11.x, casts define as a function: link to doc
protected function casts(): array
{
return [
'is_admin' => 'boolean',
];
}
PeteBatin wrote a comment+100 XP
3mos ago
Thanks for this series. Made it really easy to digest.
PeteBatin wrote a comment+100 XP
3mos ago
Great episode, thank you.
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 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 liked a comment+100 XP
5mos ago
@PeteBatin thank you for your comments.