RogerManich's avatar

RogerManich wrote a reply+100 XP

6d ago

Finally I found a possible solution that avoid flickr and no warnings errors on debug console.

RogerManich's avatar

RogerManich started a new conversation+100 XP

6d ago

Hi,

I am in learning process and I started a new project to practice a bit. My first goal is having language support to my App using vue starter kit.

The backend part is acomplished and the frontend almost acomplished there is a refresh issue. When I refresh the page I see the original labels and then the translated ones. This is weird for me. But first I want to review what I did in case I did somenthing wrong. Once I create standard project with Larave 13 + inertia + vue3 + authorization enabled:

  1. populate language files
php artisan lang:publish
  1. create en.json in lang folder with my labels.
  2. translate al language files to my supported languages (somthing I'll do at the end. For the moment. Just create a few keys tot test it.)
  3. Add new field in users to store desired languge (in fact it is a json field named preferences with multiple options.)
  4. Create a new middleware SetLocal to get current language in Laravel
  1. Register middleware in bootstrap app.php
<?php

use App\Http\Middleware\HandleAppearance;
use App\Http\Middleware\HandleInertiaRequests;
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
use Illuminate\Http\Middleware\AddLinkHeadersForPreloadedAssets;
use App\Http\Middleware\SetLocale;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
    )
    ->withMiddleware(function (Middleware $middleware): void {
        $middleware->encryptCookies(except: ['appearance', 'sidebar_state']);

        $middleware->web(append: [
            HandleAppearance::class,
            SetLocale::class, /* THIS */
            HandleInertiaRequests::class,
            AddLinkHeadersForPreloadedAssets::class,
        ]);
    })
    ->withExceptions(function (Exceptions $exceptions): void {
        //
    })->create();
  1. add in shere method in HandleInertiaRequests two data to be shered with frontend. current language and available language (for future language selector not covered here.).
public function share(Request $request): array
{
    return [
        ...parent::share($request),
        'auth' => [
            'user' => $request->user(),
        ],
        'locale' => fn () => app()->getLocale(),
        'available_locales' => fn () => config('app.available_locales'),
    ];
}
  1. Install laravel-vue-i18n
  2. Add in vite.config.js
//at the beginning of the file.
import i18n from 'laravel-vue-i18n/vite';

//in plugins section
i18n(),

  1. In app ts
//at the beginning of file
import { createApp, h } from 'vue';
import { i18nVue } from 'laravel-vue-i18n';

//Inside the createInertiaApp

setup({ el, App, props, plugin }) {
        const app = createApp({ render: () => h(App, props) })
            .use(plugin)
            .use(i18nVue, {
                lang: (props.initialPage.props.locale as string) ?? 'en',
                fallbackLang: 'en',
                resolve: async (lang: string) => {
                    const langs = import.meta.glob('../../lang/*.json');
                    return await langs[`../../lang/${lang}.json`]();
                },
            });
             // Only mount in the browser. On SSR `el` is undefined and mounting
        // would try to access `window`.
        if (typeof window !== 'undefined' && el) {
            app.mount(el);
        }

        return app;
    },
  1. Now we can use this to translate

in php

__('hello world!');

In vue3

{{ $t('hello world') }}

And now my question:

It works fine. But when I refresh the page I see the original label "hello world" and then the translated text "Hola món". Is there something wrong? Maybe my vue part is not quite fine and I forget something or I doing something too late?

thank you

RogerManich's avatar

RogerManich liked a comment+100 XP

6d ago

@Ottenim I google the question and I check documentation.

What you said is right but I want to display i in different languages. (Current app Language). For this case we can use:

php artisan lang:publish

To populate language files. Then make copies for each language you want to support. en, fr, sk, ca, es, nl, etc.

Finally, you can use it in your backend with __('hello world'). It also accept placeholders. If you use Livewire it also works fine. For vue3 I am investigating a bit. Acomplished but I need to polish some things. Ah, don't forget to add a middleware SetLocale to obtain your current language based on your criteria and precedence (session => user => browser => config => hardcoded default.

RogerManich's avatar

RogerManich wrote a comment+100 XP

6d ago

@Ottenim I google the question and I check documentation.

What you said is right but I want to display i in different languages. (Current app Language). For this case we can use:

php artisan lang:publish

To populate language files. Then make copies for each language you want to support. en, fr, sk, ca, es, nl, etc.

Finally, you can use it in your backend with __('hello world'). It also accept placeholders. If you use Livewire it also works fine. For vue3 I am investigating a bit. Acomplished but I need to polish some things. Ah, don't forget to add a middleware SetLocale to obtain your current language based on your criteria and precedence (session => user => browser => config => hardcoded default.

RogerManich's avatar

RogerManich wrote a reply+100 XP

1w ago

It what I did but it didn't work it. Looks like I need to do something like this:

Route::get('/lab', function () {
       return back()->with('flux-toast', [
        'text' => 'hellou',
        'variant' => 'success',
    ]);   
})->name('lab')->middleware('auth');

Which it is pretty much the same as session()->flash. Maybe there is something easier we can do. But as @imranbru suggest, not bad solution using this approach.

For the moment, with both works fine. Only one is displayed.

RogerManich's avatar

RogerManich wrote a reply+100 XP

1w ago

thank you, I will

RogerManich's avatar

RogerManich started a new conversation+100 XP

1w ago

Hi,

After I watched the last Laravel course I wanted to try to build something with Laravel + LiveWire. My first goal was expanding the user preferences to accept language and color scheme. It works but in my first design I wanted to use a route + controller to update the user preferences instead of doing it insde the component settings. It worked but I realized that flux::toast doesn't work in this scenario. I've seen a post where explaining that now is supported out of the box. Well, inside the component works fine.

After googling a bit and some IA help I found out that I require to use session to store the message and add some listener in my layout. Now it works but I wonder if I did something wrong and I am reinventing the wheel or the starterkit missing this piece of code.

thank you

a Route example:

Route::post('/lab', function () {
    session()->flash('flux-toast', [
        'text'    => 'Record saved successfully!',
        'variant' => 'success',
    ]);

    return redirect()->back();
})->name('lab')->middleware('auth');

and in my layout after

@persist('toast')
    <flux:toast position="top right" />
@endpersist
@if(session()->has('flux-toast'))
    @php $toast = session('flux-toast'); @endphp
    <script>
        function showToast() {
            Flux.toast({
                text: '{{ $toast['text'] }}',
                variant: '{{ $toast['variant'] ?? 'success' }}',
            });
        }

        if (document.readyState === 'complete') {
            showToast();
        } else {
            document.addEventListener('DOMContentLoaded', showToast, { once: true });
        }
        document.addEventListener('livewire:navigated', showToast, { once: true });
    </script>
@endif
RogerManich's avatar

RogerManich liked a comment+100 XP

2w ago

@RogerManich Yes, I noticed this after a while. Thanks Roger

RogerManich's avatar

RogerManich wrote a comment+100 XP

4w ago

@Go3shom the if is correct but did you fix it in the when clausule?

require to be $status instead of $request->status

$ideas = $user
        ->ideas()
        ->when($status, fn($query, $status) => $query->where('status', $status))
        ->get();
RogerManich's avatar

RogerManich liked a comment+100 XP

4w ago

@wordxpression If I understand what you mean right, you may get the All button count by calling the count method on $statusCounts like so:

<span class="text-xs pl-3">{{ $statusCounts->count() }}</span>
RogerManich's avatar

RogerManich liked a comment+100 XP

4w ago

As much as I like to practice array mapping and manipulation, countBy() helps to clean the logic up a bit:

// Get counts in the controller
'counts' => $request->user()->ideas()->get()->countBy('status');

// Get counts in view, including those with no records
{{ $counts[$ideaStatus->value] ?? 0 }}
RogerManich's avatar

RogerManich wrote a comment+100 XP

1mo ago

@RogerManich a better version

@props([
    'status' => ""
])

@php
    use App\IdeaStatus;

    $classes = 'inline-block rounded-full border px-2 py-1 text-xs font-medium';

    $classes .= match($status) {
            IdeaStatus::PENDING->value => ' bg-yellow-500/10 text-yellow-500 border-yellow-500/20',
            IdeaStatus::IN_PROGRESS->value => ' bg-blue-500/10 text-blue-500 border-blue-500/20',
            IdeaStatus::COMPLETED->value => ' bg-green-500/10 text-green-500 border-green-500/20',
            default => ' bg-red-500/10 text-red-500 border-red-500/20'
    };


@endphp

<span {{ $attributes(['class' => $classes]) }}>
        {{ $slot }}    
</span>
RogerManich's avatar

RogerManich wrote a comment+100 XP

1mo ago

I wonder if it is better use this code. Use a switch instead of several if statements. Use the IdeaStatus enum we created in previous lessons to have consistency. Adding a red color for unknown status (improvably but possible). It is what I do in real life but not sure if Laravel has any considerations to use strings or it is just a lesson and Jeffrey make easier to use strings to not add to much stuff.

@props([
    'status' => null
])

@php
    use App\IdeaStatus;

    $classes = 'inline-block rounded-full border px-2 py-1 text-xs font-medium';

    switch($status) {
        case IdeaStatus::PENDING->value:
            $classes .=' bg-yellow-500/10 text-yellow-500 border-yellow-500/20';
        break;
        case IdeaStatus::IN_PROGRESS->value:
            $classes .=' bg-blue-500/10 text-blue-500 border-blue-500/20';
        break;
        case IdeaStatus::COMPLETED->value:
            $classes .=' bg-green-500/10 text-green-500 border-green-500/20';
        break;
        default:
            $classes .=' bg-red-500/10 text-red-500 border-red-500/20';
    }    
@endphp

<span {{ $attributes(['class' => $classes]) }}>
        {{ $slot }}    
</span>
RogerManich's avatar

RogerManich wrote a comment+100 XP

1mo ago

@senxor it's a matter of trying and check if it works. Or do you asking if it is a good practice?

RogerManich's avatar

RogerManich wrote a comment+100 XP

1mo ago

@Siggles I guess you can evaluate type an assign old depend on the type

value="{{ $type === 'password' ? '' : old($name) }}"

or using @IF or @unless directives to include old value.

RogerManich's avatar

RogerManich liked a comment+100 XP

1mo ago

I’m using https://heroicons.com/, and it has worked well for me. I just copy the icon, create the Blade view, and add the width and height attributes set to 20, but that’s optional. Thank you

RogerManich's avatar

RogerManich wrote a comment+100 XP

1mo ago

@XavierHsiao it is explained in next episodes.

RogerManich's avatar

RogerManich liked a comment+100 XP

1mo ago

Seems that Jeffery did not mention displaying flash data. We just need to add it from seesion as below:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Idea</title>

    @vite(['resources/css/app.css'])
</head>

<body class="bg-background text-foreground">
    <x-layout.nav />

    {{-- Flash Data --}}
    @if (session('success'))
        <div class="fixed bottom-4 right-4 bg-primary text-primary-foreground px-6 py-3 rounded-xl shadow-lg">
            {{ session('success') }}</div>
    @endif

    <main class="max-w-7xl mx-auto px-6 pb-10">
        {{ $slot }}
    </main>
</body>

</html>
RogerManich's avatar

RogerManich wrote a comment+100 XP

1mo ago

@Alext1926 we use the DB each time we use Auth::login or Auth::destroy, Auth::attempt, etc. You are using a builtin Laravel classes that make this tasks out of the box. If you open your database you'll see the registered users and sessions.

Maybe did I misunderstand your question?

RogerManich's avatar

RogerManich wrote a comment+100 XP

1mo ago

Hi, I have a little question: When we logout, the session record remains in the database without the user_id. Is this a security measure to avoid reusing session id or we should destroy it?

RogerManich's avatar

RogerManich wrote a comment+100 XP

1mo ago

@hendriaprianto99 well, maybe you have something in mind.

RogerManich's avatar

RogerManich wrote a comment+100 XP

1mo ago

Just a question @Jefrey: In real life when you work with git, you only maintain one branch? Main / develop branch? Main / Develop and one branch per feature you work?

thanks

RogerManich's avatar

RogerManich wrote a comment+100 XP

1mo ago

@nosthas you added WithNames.

What I see this rector.php modify some original file in Laravel. Not sure if it is good practice do that.

RogerManich's avatar

RogerManich wrote a comment+100 XP

2mos ago

@crscnc if you plan increase complexity there are a few great course in here: Laravel API masterclass, Modular Laravel and others. My concern is about time to dedicate to a technology: Blade looks like great but when you plan to do things close to app maybe vue3 is better. But not entirely sure. Maybe you dedicate efforts to vue3 and an experienced developers tell you that now the trend is CanavisReact 4 (fake name) because it handle better some things that vue3 doesn't. As an example: I usually use MariaDB for all kind of projects. It is a bit work to configure MariaDB, maybe a Linux, Apache or nginx, etc. @jeffreyway suggest in a course that SQLite should be enough for most Laravel projects. I tried it and looks like a good advice. So, I expect the opinion who was there in the battle. You know. :-)

Thank you

RogerManich's avatar

RogerManich wrote a comment+100 XP

2mos ago

@crscnc The point is about choosing the right technology among all that Laravel offers. As an example: Before starting to follow Jeffrey I use to make my little projects with MariaDB. Jeffrey suggest in his Laravel in 30 days course that sqlite is good enough for little / medium projects. Good advice. I test it and it is ok. So, if I have to learn Blade or vue3 I want to know if at the end is better to use Vue or Blade is ok. Vue looks like better in terms of I can use it in other places, for instance. Just want to leverage the experience of who were there before.

RogerManich's avatar

RogerManich wrote a comment+100 XP

2mos ago

@jawaid interface is something you define independent of a class. If an interface define get, set, erase methods all the classes that implements that interface must define that methods. A class can accept multiple interfaces.

When you use an abstract class is more specifically to think with a classes that you want to instruct how you want to be defined. It can includes implementation (I think it. not sure). It is like a sketch of your class in terms of methods, and specific implementations.

More less.

RogerManich's avatar

RogerManich wrote a comment+100 XP

2mos ago

I knew this as polimorphism that is used in other languages. When I realized I can use interface to achieve that I was so glad. But I didn't know the concept of contract which is great too. Thanks for this masterclass.

RogerManich's avatar

RogerManich liked a comment+100 XP

2mos ago

Even as a long-time PHP developer I find this series incredibly helpful and approachable! Really great job, Jeffrey!

RogerManich's avatar

RogerManich liked a comment+100 XP

2mos ago

And in the controller if we are using authorize method with one parameter, we are using gate:

Gate::authorize(parameter1);

// ex.
Gate::authorize(gateName);

If we are using authorize method with 2 parameters, we are using policies:

Gate::authorize(parameter1, parameter2);

// ex.
Gate::authorize(methodName, modelOrClassInstance);
RogerManich's avatar

RogerManich wrote a comment+100 XP

2mos ago

@akaydin I think if you plan having undetermined amount of admins and don't want to make anything complex, you can replicate what Jeffrey suggest: A field named role and define different roles such as user, advanced user, operator, admin, superadmin, etc. According to your needs.

if you require anything more sophisticated you can create a permissions table, role table and pivot table. Then you can associate that role to a user. Each permission can correspond to a Gate. And inside the gate you have to check if you have that particular permission.

RogerManich's avatar

RogerManich wrote a comment+100 XP

2mos ago

On login, in case of bad credentials we can use a special name to show general errors

return back()->withErrors([
            'general' => 'The provided credentials do not match our records.',
        ]);
    }

and then in our view:

<SNIP>  
  <x-forms.error name="general" />
</fieldset>
<SNIP>
RogerManich's avatar

RogerManich wrote a comment+100 XP

2mos ago

@jake83 I thought the same. I test it in my project and update is required to update the data which is what I expect.

RogerManich's avatar

RogerManich wrote a comment+100 XP

2mos ago

@jeffry if we want to display the messages in a different language is there a way to achieve that?

RogerManich's avatar

RogerManich wrote a comment+100 XP

2mos ago

thanks for the trick about pushing a button and fire a different form. I didn't remeber that. :-)

RogerManich's avatar

RogerManich liked a comment+100 XP

2mos ago

@koulritesh98 While developing, you added some new tables or columns to existing tables, after you deployed to production. You add them by writing new migrations. Then, when you update your production site, you also update your table by running "php artisan migrate". It will ask you "are you sure, this is prod?", you answer yes, and the prod DB is updated. It will run only the newly added migrations, not the old ones. How, might you ask? It keeps a list of migrations that have been already run in the DB table called "migrations". Open it and see for yourself.

Of course, it goes without saying: always double check what your migrations are doing and always made a DB backup before updating.

RogerManich's avatar

RogerManich liked a comment+100 XP

2mos ago

@jeffreyway in every video, there's a moment cracks me up. This time, the super explanation for the 419 page expired.. typing fast enough ahahah.

RogerManich's avatar

RogerManich wrote a comment+100 XP

2mos ago

@subhrodeb888 I think he meant that when you define a get route is to fetch data and ultimatelly display / return something. It is not a good practice to do something different there like delete something. If you plan to delete something you need to define a route for this. Rest define a way to do this.

RogerManich's avatar

RogerManich wrote a comment+100 XP

2mos ago

I like this new course: You combine the video and you communication capability with some text-based exampled to help us to put in motion. Great!

RogerManich's avatar

RogerManich wrote a comment+100 XP

2mos ago

As we can work with Blade, Vue or React what do you recommend to use in Laravel @jeffreyway? Blade is enough or is limited and Vue is much powerful? I have a bit confusion how to use Vue in a project with Laravel (the Vue3 course is not clear enough in this part). But finally I see it and I wonder what is the best? Or when to choose one or another based on your experience.

RogerManich's avatar

RogerManich wrote a comment+100 XP

2mos ago

@timgavin Yes and No. From my point of view, places like Laracast are escencial because the course and the teacher is like the man that show the right path. Show you the best practices. AI without knowlede and context is often dangerous. To solve a problem through an AI you need to know what are the right questions. You need to know the capabilities of the technology you choose. And here is where Laracast is valuable. Once you draw the map thanks to the course is when you can start to use AI to expand your knowledge or to help you to build something. Or you can use to clarify something is not entirely clear in the course. But without this essencial context AI is like a car without keys.

RogerManich's avatar

RogerManich wrote a comment+100 XP

3mos ago

What I miss in this setup is a 30 seconds to indicate what extensions required to work on VS Code. Php Storm is not free. Only 30 days which is not much.

Also it could be nice some references to Linux. Not everything is apple.

At the end, it is a couple of lines to have an operational setup.

Anyway, you contents are pretty amazing!

thank you Roger