Как я могу правильно обобщить входные данные формы в Laravel Volt?

Я имею опыт разработки React и WordPress и пытаюсь разобраться в компонентах Livewire с помощью Laravel Volt. Моя дилемма заключается в том, что я пытаюсь обобщить больше компонентов формы, но сталкиваюсь с трудностями при сохранении синхронизации состояния.

Вот мой компонент формы:

<?php

use App\Models\MyModel;

use Illuminate\Database\Eloquent\Collection;
use Livewire\Attributes\Validate;
use Livewire\Volt\Component;

new class extends Component {

    #[Validate('required|string|max:256')]
    public string $description;

    public ?MyModel $editing = null;

    public function submit(): void
    {
        $validated = $this->validate();
        $this->dispatch('my-model-form-submitted', $validated);
        $this->description = '';
    }

    public function mount(): void
    {
        if (isset($editing)) {
            $this->editing = $editing;
            $this->description = $this->editing->description;
        } else {
            $this->description = '';
        }
    }
};

?>

<form wire:submit.prevent = "submit">
    <livewire:form-input :label = "__('Description')" id = "description" wire:model = "description"
        placeholder = "{{ __('Describe the thing') }}" :error = "$errors->get('description')" />
    <livewire:form-input :label = "__('Description a second time')" id = "description2" wire:model = "description"
        placeholder = "{{ __('Ideally in sync with the same value as the first input') }}" :error = "$errors->get('description')" />
    <div>
        {{ $editing }}
        <x-primary-button>{{ $editing ? __('Update') : __('Save') }}</x-primary-button>
    </div>
</form>

Вот компонентviews/livewire/form-input.blade.php (в основном ввод с меткой и сообщением об ошибке):

<?php

use Livewire\Attributes\Modelable;

new class extends \Livewire\Volt\Component {
    public string $id;
    public string $label;

    #[Modelable]
    public string $value = '';

    public string $placeholder;
    public array $error;

    public function mount(string $id, string $label, string $placeholder, array $error = []): void
    {
        $this->id = $id;
        $this->label = $label;

        $this->placeholder = $placeholder;
        $this->error = $error;
    }
};

?>

<x-form-group>
    <x-input-label for = "{{ $id }}">{{ $label }}</x-input-label>
    <x-input-text type = "{{ $type ?? 'text' }}" id = "{{ $id }}" wire:model = "value"
        placeholder = "{{ $placeholder }}" />
    <x-input-error :messages = "$error" />
</x-form-group>

а вот представления/компоненты/input-text.blade.php (только элемент ввода):

<input
    {{ $attributes->merge(['class' => ' class = "block w-full px-4 py-2 border-gray-300 text-slate-900 dark:text-white focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50 rounded-md shadow-sm"']) }}>

Я чувствую, что упускаю ключевую деталь, поскольку два ввода в форме не синхронизируются, загрузка модели для редактирования не устанавливает значение входных данных, а отправка формы только отключает ее, не отправляя событие или сброс значения описания.

Обновлять: Я разобрался с дилеммой синхронизации двух входов. Теперь я вижу, что состояние обновляется на сервере только при выполнении действия. https://livewire.laravel.com/docs/wire-model но я все еще озадачен загрузкой для редактирования и отсутствием значений во время отправки.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
0
227
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Во-первых, давайте посмотрим на вашу функцию монтирования

 public function mount(): void
    {
        if (isset($editing)) {

Мы проверяем, установлена ​​ли переменная $editing, но никогда не пытаемся ее установить. Вы можете сделать это, указав, что это параметр, который мы принимаем в функции монтирования.

Ниже приведена фиксированная версия. Я переименовал MyModel в модель Post, чтобы это имело больше смысла.

public function mount(?Post $post = null): void
    {
        if (isset($post)) {
            $this->post = $post;

Метод mount не является конструктором класса, но, по сути, он ведет себя именно так. Это может быть концепция, с которой вы знакомы по реакции.

Это еще не полное решение.

Дальнейшие улучшения

Теперь, чтобы закончить это, мы собираемся делать что-то «путем Laravel», а также некоторые проблемы, связанные с безопасностью, о которых нам следует знать, и лучший способ сделать что-то для повышения производительности.

    #[Validate('required|string|min:1|max:256')]
    public string $description;

    public Post $post;

    public function submit(): void
    {
        $validated = $this->validate();
        /** 
        * You likely just gave me psuedo but we should actually create a 
        * model here usually */
        $this->dispatch('my-post-form-submitted', $validated);
        $this->description = '';
    }

    public function mount(?Post $post = null): void
    {
        if (isset($post)) {
            $this->post = $post;
            $this->description = $this->post->description;
        }
    }

Раньше наша функция монтирования присваивала переменной описания значение пустой строки. Поскольку он был инициализирован, он всегда проходил «обязательное» правило проверки.

Мы также можем установить для Post значение null в методе монтирования. Используя ?Post $post = null, мы указали, что параметр $post должен быть экземпляром класса Post. Мы также присвоили ему значение по умолчанию, равное нулю, которое будет использоваться, если при рендеринге компонента не было передано ни одного сообщения.

Чтобы удвоить уверенность в том, что пользователь ввел что-то в качестве описания, было установлено минимальное правило проверки, указав не менее 1 символа.

Функция монтирования имеет типизированный параметр $post. Если в этой форме есть маршрут и это полностраничный компонент, это будет сделано именно так. Если эта форма является всего лишь дочерним компонентом и имеет родительский компонент, вам следует изменить ее, чтобы она принимала целое число, и загрузить связанную модель со строкой, аналогичной этой, внутри метода монтирования.

$this->post = Post::findOrFail($id);

У меня нет полных подробностей реализации, а есть только то, что было предоставлено, но имеющийся у меня контекст создает впечатление, что родительский компонент имеет копию модели Post и используется вертикально.

В большинстве случаев это делать не имеет смысла. Если родительскому элементу нужен экземпляр Post, отмените вложение этого компонента и просто поместите функциональность в его родительский элемент. Передача моделей вертикально через вложенные компоненты довольно затруднительна.

Проблемы безопасности

Livewire будет включать любые общедоступные свойства в запросы для отслеживания состояния. В некоторых случаях это может быть опасно, поскольку пользователь может изменить значения свойств с помощью модификатора общего доступа.

Например, если пользователь редактирует сообщение, а он должен редактировать только сообщения, принадлежащие ему, он может манипулировать свойством postId, если вы сохранили его в общедоступном свойстве, для редактирования сообщения, которое ему не принадлежит.

К счастью, Livewire умен и блокирует для нас свойство ID на моделях. Но помните об этом в будущем и взгляните на Проблемы безопасности собственности

Обработка отправки формы

Внутри вашей формы вы, похоже, излучаете свойство $description, которое предполагает, что оно передается вертикально между компонентами.

Это действительно неэффективно и опасно, поскольку все это делается на стороне клиента, и пользователь может манипулировать свойствами и их значениями.

Если вам нужно передать этот параметр вертикально, потому что он хочет разделить проблемы, я понимаю. В этом случае вы можете использовать Livewire Forms, поскольку они не имеют представления и просто содержат логику проверки и отправки формы.

Состояние и живое обновление

Вы можете настроить состояние так, чтобы оно практически проверялось, как только пользователь вводит ключ внутри одного из входов, который имеет привязку к свойству. Существует множество различных вариантов, но я рекомендую использовать wire:model.onblur , поскольку он будет запускать запрос только тогда, когда ввод теряет фокус, что гарантирует, что наше приложение не будет слишком громким и не отправит больше данных, чем нам нужно.

И последнее замечание, но я не буду вдаваться в подробности. Входные компоненты не обязательно должны быть компонентами Livewire, и вы можете просто использовать Компоненты Blade для того, чего вы сейчас пытаетесь добиться от них. Livewire просто не соответствует вашим текущим требованиям.

Большое спасибо за подробное объяснение. Есть ли какие-нибудь хорошие общие ресурсы для Volt и Livewire помимо документации Laravel? Я все еще пытаюсь разобраться в том, «что происходит на сервере» и «что происходит на клиенте».

m_i_rite 09.04.2024 02:08

Лично я не использую Volt именно по этой причине. Я использую Livewire без Volt, так что у меня есть один файл, который является блейд-файлом/IE, который может видеть клиент, и класс компонента Livewire, который представляет собой логику на стороне сервера.

Dylan Marriott 09.04.2024 17:17

Другие вопросы по теме