valentin_vranic's avatar

valentin_vranic started a new conversation+100 XP

2mos ago

Probably it's supposed to be a blog post, but I find it well to place it here too.

So my first, real "wtf" moment after so many "wow"s regarding of capabilities of AI agents, and the development with them.

So long story short. Together with my teammate , we started working on a dashboard for our customers, with many things in plan from our PM, and superiors, but nothing was clearly defined in the beginning, rather as we moved forward new tasks arose. We used AI for development clearly, but in kind of Developer Driven mode, putting together our stuffs, using agents to help our process.

After 3 weeks, we came to present our first phase achievement. After presentation one of our colleagues, who is not particularly a tech-dev guy, mostly a project manager came up with his dashboard, which he put together totally with claude code, also in 3 weeks. Nobody knows about that. And we were amazed too, how much things he put in, with totally user friendly approach. Kind of like almost production ready dashboard, even added couple of special complex functionalities which were amazing. So the CEO was amazed too, that a non dev guy was able to put this together.

Yes, it's a bit buggy, and have couple of security issues. It combines couple of different languagess/frameworks (python, nextjs, go...), for me not so familiar ones. But the boss was amazed. And I had some really mixed feelings about it, mostly like my work is not good enough, not fast enough, although I did everything as I wanted. We spoke to him about our approach using AI for development, and for later issues, when real problems will arise, with scalability and fixing issues in general. But probably soon, that will be managed by ai too. But summa summarum we switched to this project, and will continue to develop it. IDK what will be the end of this project, and will it break in the future, but currently here we are.

I'm not waiting for help, or any guidance, only wanted to share my thoughts. Please feel free to share yours too.

Thanks all,

Val

valentin_vranic's avatar

valentin_vranic wrote a reply+100 XP

2mos ago

So, finally, I was able to come up with a working solution. Hopefully someone facing some same kind of issues will find it helpful.

  private function checkSSEServer(McpServer $server, array $headers): array
    {
        try {
            $response = Http::timeout(10)
                ->withHeaders($headers)
                ->get($server->url);

            $body = $response->body();
            $endpoint = $this->extractSseEndpoint($body, $server->url);

            $sessionId = $this->extractSessionId($endpoint);
            $requestHeaders = $sessionId ? array_merge($headers, ['Mcp-Session-Id' => $sessionId]) : $headers;

            return $this->requestToolsList($endpoint, $requestHeaders);
}

So, it's not handling when it's unsuccessful, only to show what is my workflow for it. McpServer is only my model consisting some props like name, url, etc...

valentin_vranic's avatar

valentin_vranic started a new conversation+100 XP

2mos ago

Hi all!

I'm facing an issue for a while. Firstly it was the lack of understanding of MCP-s, secondly the understanding of capabilities of Laravel and MCP-s.

So as I know, the MCP-s are not kind of REST endpoint(s) as I thought in the beginning, but an SSE (server-sent-events). Which is a new for me.

So my starting approach was to just send a tools-list method to the url, but later realised that it does need an open session connection to the MCP itself and then can only happen the query.

So my question is, is there any solutions to this in laravel? A lightweight approach for a quick MCP client which only lists the tools of a certain MCP server? I'm building a workflow app, where one of the features would be that users can add/pick MCP servers and list their tools to visually see them.

Thanks in advance, Val

valentin_vranic's avatar

valentin_vranic liked a comment+100 XP

2mos ago

Hi @silveira, I've read about a similar issue in another post when upgrading to Livewire 4 and Filament. They fixed it by deleting the node_modules directory and installed the nodes packages again. I suggest giving it a try.

valentin_vranic's avatar

valentin_vranic wrote a reply+100 XP

2mos ago

Do you have a public property defined with the name resourceTypes above int he code? Ensure that only the #[Computed] is present, thus the public property will override it.

valentin_vranic's avatar

valentin_vranic liked a comment+100 XP

3mos ago

Providing some essential code would help a lot.

@valentin_vranic This.

valentin_vranic's avatar

valentin_vranic wrote a reply+100 XP

3mos ago

Firstly the issue title and your real question I think is a bit misleading, thus I don't see the real relation between them (at first look).

IMO I would pass the object if it't not so heavy, and a simple model, and use #[Locked] on it in child, to prevent any malicious data manipulation between queries. And as a mandatory step, when looping the over parent property of child components, passing the :key on it to keep track of them.

IDK what the pivot datas consists and what losing them actually means. That's correct that the action is isolated for a component. But I'm not sure that refreshing the parent makes it efficient.

Providing some essential code would help a lot.

valentin_vranic's avatar

valentin_vranic wrote a reply+100 XP

4mos ago

For that purpose you can change the

public string const HOME = '/'; in app/Providers/RouteServiceProvider.php

EDIT:

My bad, the code above is for laravel 11x.

Here's the docs for 12, which could help: https://laravel.com/docs/12.x/authentication#redirecting-authenticated-users

valentin_vranic's avatar

valentin_vranic liked a comment+100 XP

4mos ago

Why you can't just set write credentials same as read? In worst case you get error of wrong privileges, but you don't plan to execute write queries on that database anyway, so no harm there.

valentin_vranic's avatar

valentin_vranic wrote a reply+100 XP

4mos ago

Hm. Firstly, it has to be an array.

If empty array then: Undefined array key "host".

Or in third case, getting this error: Database hosts array is empty.

This is kind of strange a bit to me. And have a feeling that I'm missing something.

valentin_vranic's avatar

valentin_vranic started a new conversation+100 XP

4mos ago

I have an application, where I connect to multiple db-s. I have In 8 connections 3 where read & write credentials are separately defined, and the rest where only the read were defined and write was left empty.

This worked under laravel 11. After I've upgraded to version 12 I'm getting

SQLSTATE[HY000] [2002] No such file or directory for those connections where the write is left empty like above.

My question is what happened in the upgrade? Does anyone had some similar issues?

And yeah, why don't I write it into single dimension without read, write in this second scenario, even if it works like that? Because I wanted to keep the structure.

Probably I will if there's no other solution.

NOTE: maybe it's not in the upgrade, but on system I use it. On live test server (debian 12) everything seems okay yet. But in my local env, macos under Herd, it got broken.

Thanks in advance,

Val

valentin_vranic's avatar

valentin_vranic wrote a reply+100 XP

5mos ago

Place here please the content of dynamic-component class and view too. And the x-layouts.wizard content.

valentin_vranic's avatar

valentin_vranic wrote a reply+100 XP

5mos ago

Hi. First thing I noticed, and probably will fix the issue too. You don't need the wire:key="questionnaire-step-{{ $step }}" in the parent div. wire:key is mostly used in loops to track the elements inside.

The second is for the livewire components call. Use :key instead of wire:key for them, thus that is the recommended approach. Like <livewire:questionnaires.step1 :key="'q-step1'" />

And the third would be, the $refresh on your nextStep method. Because you modify the step property, it will automatically re-render the view, and if there's no any other use case to force the whole component to $refresh then don't do it.

Hope this helps, Val

valentin_vranic's avatar

valentin_vranic wrote a reply+100 XP

5mos ago

Hey. I came up with an idea/solution. You can like it or hate it, but this is what I can give you :D

Using, livewire 3 and alpineJs/vanillaJs solutions.

The view:

x-user-tile (in views/components)

@props(['user', 'bg'])

<div wire:key="{{ $user->id }}"
     style="background: {{ $bg }};
            border-radius: 10px;
            display: flex;
            align-items: center;
            justify-content: center;
            font-weight: 600;
            color: #1f2937;">
    {{ $user->name }}
</div>

I'm using the laravel pagination, combined with livewire use WithPagination, WithoutUrlPagination; With this approach, I only append to the parent, preventing the growth of property, and querying the whole dataset using only the limit.

p.s. with livewire 4, there is/will be a solution for this: https://livewire.laravel.com/docs/4.x/islands#append-and-prepend-modes

valentin_vranic's avatar

valentin_vranic liked a comment+100 XP

5mos ago

After Episode 7 everything was confused. It would be better to continue how you started by creating Payooner, Wire and Wise providers and it would be great you demonstrate how would you add a new functionality to the providers. Also I was expecting that you will provide how to divide PaymentInterface by multiple parts (RefundableInterface, CapturedPaymentInterface)

Say that Payooner has an option to capture a payment and then confirm it, but Wire transfer there is only refundable option available

class Payooner implements RefundableInterface, CapturedPaymentInterface class Wire implements RefundableInterface

valentin_vranic's avatar

valentin_vranic liked a comment+100 XP

5mos ago

@automica I second that. I do not get the benefit from this yet and a concrete example in the test (without the interface and with the interface) would help.

valentin_vranic's avatar

valentin_vranic wrote a reply+100 XP

5mos ago

Well, I'm using PHPStorm, with barryvdh/laravel-ide-helper package. But the experience is somewhere similar you described.

My experience is that, when the view's name is rendered from the convention of class name, it is more reactive on referencing the properties, methods used in view.

The other way, sometimes when it's a bit different named view, it simply doesn't recognize anything.

It would a be a pleasure to have some other insights from others too.

valentin_vranic's avatar

valentin_vranic wrote a reply+100 XP

5mos ago

Hey. Idk what could cause you an issue, bcs I've tried with your provided code, and the transition seems to me that takes effect on the first attempt after loading the page.

Please provide the versions of your stack. Laravel, livewire

valentin_vranic's avatar

valentin_vranic wrote a reply+100 XP

5mos ago

So couple of things.

Firstly provide the class content too, especially where saveSelectedCustomer happens.

It's not a good practice to combine name and wire:model attributes, especially with lw stick with the latter.

Where forms are present, like here, I like to set wire:submit="saveSelectedCustomer" and set the submit button type to submit, and remove the wire:click from it too, thus this will lock, disable the form while it submits it.

There's no attribute like wire:blur rather a modifier like wire:model.blur which updates the property when clicked away from the input itself: https://livewire.laravel.com/docs/3.x/wire-model#updating-on-blur-event

Lastly, don't make unnecessary mess in the forum posting the same question more than once.

valentin_vranic's avatar

valentin_vranic wrote a reply+100 XP

5mos ago

Not aware of the cause, I had some similar approaches earlier in my codebase. And everywhere where I dispatch from js the [] were needed when passing params, so I tried and it worked.

But I agree, it's a bit strange behavior...

valentin_vranic's avatar

valentin_vranic was awarded Best Answer+1000 XP

5mos ago

Oh, okay. I think I figured it out.

Put the payload into [].

<button
        wire:click="$dispatchTo(target, eventToEmit, [payload])"
        class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-1.5 rounded text-sm"
>
    Confirm
</button>
valentin_vranic's avatar

valentin_vranic wrote a reply+100 XP

5mos ago

Provide some code, or be more descriptive about your issue.

FYI: livewire properties are not reactive by default. You can set wire:model.live to make them interactive (go to backend and update the property value) when an input changes

valentin_vranic's avatar

valentin_vranic wrote a reply+100 XP

5mos ago

Oh, okay. I think I figured it out.

Put the payload into [].

<button
        wire:click="$dispatchTo(target, eventToEmit, [payload])"
        class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-1.5 rounded text-sm"
>
    Confirm
</button>
valentin_vranic's avatar

valentin_vranic wrote a reply+100 XP

5mos ago

Hi. Well it's supposed to work as you described. I'm only not aware of this part

<livewire:currlm-select-block::currlm-select-block-setting it's not a valid syntax with ::, rather if it's nested file in file structure, then concatenate it with . Like: <livewire:currlm-select-block.currlm-select-block-setting

valentin_vranic's avatar

valentin_vranic wrote a reply+100 XP

5mos ago

I would suggest to follow the example provided by LarryAI, with adding wire:submit="createComment", thus it will disable all the input fields, and the submit button while making the roundtrip from frontend and backend, making it more secure, and preventing submiting a form multiple times.

valentin_vranic's avatar

valentin_vranic wrote a reply+100 XP

5mos ago

Hey. I'm not so familiar with flux behaviors and components. However I don't recommend to render unnecessary view for each row, rather define one on bottom of parent page, something like let's say:

<x-dialog wire:show="clickedPerson">
    <x-dialog.panel panelWidth="w-50">
        @if($clickedPerson)
            @include('livewire.person', ['person' => $clickedPerson])
        @endif
    </x-dialog.panel>
</x-dialog>

This is my custom livewire panel case. So in each row to have a button, with wire:click="loadPerson($id)" which will trigger a method, and that will load the person by id.

Something like this, so in this case, it will be dependent on the provided $id rather than the loaded view.

valentin_vranic's avatar

valentin_vranic wrote a reply+100 XP

5mos ago

I don't see where you listen for the global event itself, on for confirm method.

What if:

adding #[On('open-modal')] above public function confirm($eventToEmit = null, $payload = [])?

And it could be used like you mentioned in the beginning with wire:click="$dispatchTo('ConfirmationModal', 'confirm', {{$payload}})"

Am I missing something?