Laravel编辑浅层嵌套资源 [英] Laravel edit shallow nested resource

查看:49
本文介绍了Laravel编辑浅层嵌套资源的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用

假设我们要编辑 tiagoperes.eu stackoverflow.com .我要进入修改视图

更改相应的字段,然后单击保存"按钮.这是结果

如您所见,记录未更新.

检查控制器的update()中的 $ request-> all()

以及网络"标签中的表单数据

并将数据发布到

  http://localhost/app/public/emaildomains/7 

与浅层嵌套中的URI相匹配.


在edit.blade.php中,我具有以下表单来处理更新

 < form method ="post"操作=" {{route('emaildomains.update',['emaildomain'=> $ email_domain-> id])}}'"autocomplete ="off">;@csrf@method('put')< h6 class =标题较小的文本静音mb-4"> {{__('电子邮件域信息')}}</h6>< div class ="pl-lg-4">< div class =" form-group {{$ errors-> has('organization_id')?'has-danger':''}}'>< label class ="form-control-label"for ="input-organization_id"> {{__('Organization')}}}</label><选择名称="organization_id";id ="input-organization"class =" form-control {{$ errors-> has('organization_id')?'is-invalid':``}}''';placeholder =''{{__('Organization')}}''';必需>@foreach($ organizations为$ organization)< option value ="{{$ organization-> id}}"{{$ organization-> id == old('organization_id',$ email_domain-> organization-> id)吗?'selected':''}}> {{$ organization-> name}}</option>@endforeach</select>@include('alerts.feedback',['field'=>'organization_id'])</div>< div class =''form-group {{$ errors-> has('email_domain')?'has-danger':''}}'>< label class ="form-control-label"for ="input-email_domain"> {{__('Email Domain')}}</label><输入类型=文本";name ="email_domain"id ="input-email_domain"class =" form-control {{$ errors-> has('email_domain')?'is-invalid':``}}''';placeholder =''{{__('Email Domain')}}''';value =" {{old('email_domain',$ email_domain-> email_domain)}}'"必需的自动对焦>@include('alerts.feedback',['field'=>'email_domain'])</div>< div class =文本中心">< button type =提交";class =" btn btn-success mt-4"> {{__('Save')}}</button></div></div></form> 

,这是 OrganizationEmailDomainController

中的编辑和更新方法

 /***显示用于编辑指定资源的表格.** @param \ App \ OrganizationEmailDomain $ email_domain* @return \ Illuminate \ Http \ Response*/公用功能edit(Request $ request,OrganizationEmailDomain $ email_domain,Organization $ model){$ path = $ request-> path();$ id =(int)explode('/',$ path)[1];$ emailDomain = OrganizationEmailDomain :: find($ id);返回视图('organizations.emaildomains.edit',['email_domain'=> $ emailDomain-> load('organization'),'organisations'=> $ model :: where('id',$ emailDomain-> organization_id)-> get(['id','name'])]));}/***更新存储中的指定资源.** @param \ Illuminate \ Http \ Request $ request* @param \ App \ OrganizationEmailDomain $ email_domain* @return \ Illuminate \ Http \ Response*/公共功能更新(请求$ request,OrganizationEmailDomain $ email_domain){$ email_domain-> update($ request-> all());$ organization_id =(int)$ request-> all()['organization_id'];return redirect()-> route('organizations.emaildomains.index',['organization'=> $ organization_id])-> withStatus(__("Org的电子邮件域已成功更新."));} 

这是模型(请注意,我使用的表的名称与默认情况下的名称不同- protected $ table ='email_domains';

  class OrganizationEmailDomain扩展模型{受保护的$ fillable = ['email_domain','organization_id'];保护$ table ='email_domains';/***获得组织** @返回\组织*/公共职能组织{返回$ this-> belongsTo(Organization :: class);}} 

解决方案

向路径或控制器操作注入模型ID时,通常会查询数据库以检索与该ID对应的模型.Laravel路线模型绑定提供了一种方便的方法,可以将模型实例直接自动注入到您的路线中.例如,您可以注入与给定ID匹配的整个OrganizationEmailDomain模型实例,而不是注入OrganizationEmailDomain的ID.

Laravel自动解析在路由或控制器操作中定义的口才模型,这些操作的类型提示变量名称与路由段名称匹配.例如:

 使用App \ OrganizationEmailDomain;路线:: put('emaildomains/{emailDomain}',[OrganizationEmailDomainController :: class,'update'])); 

然后将以下内容放在您的控制器中

 /***更新存储中的指定资源.** @param \ Illuminate \ Http \ Request $ request* @param \ App \ OrganizationEmailDomain $ emailDomain* @return \ Illuminate \ Http \ Response*/公共功能更新(请求$ request,OrganizationEmailDomain $ emailDomain){$ emailDomain-> update($ request-> all());返回redirect()-> route('organizations.emaildomains.index',['organization'=>$ request-> organization_id])-> withStatus(__("Org的电子邮件域已成功更新.")));} 

请注意,如果变量名称 $ emailDomain 与路由段 {emailDomain} 不同,则laravel将无法解析模型.因此,您将获得一个空的OrganizationEmailDomain模型,并且它不会更新任何数据.因此,请确保输入在路由中定义的相同名称.

要检查路线的正确名称,请运行命令 php artisan route:list ,您将看到路线和路段的名称.


编辑

为了解决这个问题,我跑了

  php artisan route:列表 

其中显示

organizations/{organization}/emaildomains/{emaildomain} |Organizations.emaildomains.update

因此,将 OrganizationEmailDomainController.php 更改为

 /***更新存储中的指定资源.** @param \ Illuminate \ Http \ OrganizationEmailDomainRequest $ request* @param \ App \ OrganizationEmailDomain $ emaildomain* @return \ Illuminate \ Http \ Response*/公共功能更新(OrganizationEmailDomainRequest $ request,OrganizationEmailDomain $ emaildomain){$ emaildomain-> update($ request-> all());return redirect()-> route('organizations.emaildomains.index',['organization'=> $ request-> organization_id])-> withStatus(__("Org的电子邮件域已成功更新."));} 

足够了.

请注意,唯一需要进行的更改是将控制器从 $ email_domain 更改为 $ emaildomain ,但同时也删除了不必要的部分以获取organization_id,并通过上面的建议使用$ request.

I'm using the following resource using shallow nesting

Route::resource('organizations.emaildomains', 'OrganizationEmailDomainController', ['except' => ['show']])->shallow();

Got the following table with two records which is the result of an index.blade.php

Let's say we want to edit tiagoperes.eu to stackoverflow.com. I'd go to the edit view

change the respective field and click the save button. This is the result

As you can see, the record isn't updated.

Checking the $request->all() in the update() of the controller

and the form data in the network tab

and the data is posted to

http://localhost/app/public/emaildomains/7

which matches the URI in shallow nesting.


In edit.blade.php I have the following form to handle the updates

<form method="post" action="{{ route('emaildomains.update', ['emaildomain' => $email_domain->id]) }}" autocomplete="off">
    @csrf
    @method('put')

    <h6 class="heading-small text-muted mb-4">{{ __('Email Domain information') }}</h6>
    <div class="pl-lg-4">
        <div class="form-group{{ $errors->has('organization_id') ? ' has-danger' : '' }}">
            <label class="form-control-label" for="input-organization_id">{{ __('Organization') }}</label>
            <select name="organization_id" id="input-organization" class="form-control{{ $errors->has('organization_id') ? ' is-invalid' : '' }}" placeholder="{{ __('Organization') }}" required>
                @foreach ($organizations as $organization)
                    <option value="{{ $organization->id }}" {{ $organization->id == old('organization_id', $email_domain->organization->id) ? 'selected' : '' }}>{{ $organization->name }}</option>
                @endforeach
            </select>
            @include('alerts.feedback', ['field' => 'organization_id'])
        </div>

        <div class="form-group{{ $errors->has('email_domain') ? ' has-danger' : '' }}">
            <label class="form-control-label" for="input-email_domain">{{ __('Email Domain') }}</label>
            <input type="text" name="email_domain" id="input-email_domain" class="form-control{{ $errors->has('email_domain') ? ' is-invalid' : '' }}" placeholder="{{ __('Email Domain') }}" value="{{ old('email_domain', $email_domain->email_domain) }}" required autofocus>

            @include('alerts.feedback', ['field' => 'email_domain'])
        </div>

        <div class="text-center">
            <button type="submit" class="btn btn-success mt-4">{{ __('Save') }}</button>
        </div>
    </div>
</form>

and here's both the edit and update methods in the OrganizationEmailDomainController

/**
 * Show the form for editing the specified resource.
 *
 * @param  \App\OrganizationEmailDomain  $email_domain
 * @return \Illuminate\Http\Response
 */
public function edit(Request $request, OrganizationEmailDomain $email_domain, Organization $model)
{
    $path = $request->path();

    $id = (int)explode('/', $path)[1];

    $emailDomain = OrganizationEmailDomain::find($id);

    return view('organizations.emaildomains.edit', ['email_domain' => $emailDomain->load('organization'), 'organizations' => $model::where('id', $emailDomain->organization_id)->get(['id', 'name'])]);        

}

/**
 * Update the specified resource in storage.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \App\OrganizationEmailDomain  $email_domain
 * @return \Illuminate\Http\Response
 */
public function update(Request $request, OrganizationEmailDomain $email_domain)
{

    $email_domain->update($request->all());

    $organization_id = (int)$request->all()['organization_id'];

    return redirect()->route('organizations.emaildomains.index', ['organization' => $organization_id])->withStatus(__("Org's email domain successfully updated."));
}

and this is the model (notice I'm using a table with a different name than the expected by default - protected $table = 'email_domains';)

class OrganizationEmailDomain extends Model
{
    protected $fillable = [
        'email_domain', 'organization_id'
    ];

    protected $table = 'email_domains';

    /**
     * Get the organization
     *
     * @return \Organization
     */
    public function organization()
    {
        return $this->belongsTo(Organization::class);
    }

}

解决方案

When injecting a model ID to a route or controller action, you will often query the database to retrieve the model that corresponds to that ID. Laravel route model binding provides a convenient way to automatically inject the model instances directly into your routes. For example, instead of injecting a OrganizationEmailDomain's ID, you can inject the entire OrganizationEmailDomain model instance that matches the given ID.

Laravel automatically resolves Eloquent models defined in routes or controller actions whose type-hinted variable names match a route segment name. For example:

use App\OrganizationEmailDomain;

Route::put('emaildomains/{emailDomain}', [OrganizationEmailDomainController::class, 'update']);

Then the following should be in your controller

/**
 * Update the specified resource in storage.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \App\OrganizationEmailDomain  $emailDomain
 * @return \Illuminate\Http\Response
 */
public function update(Request $request, OrganizationEmailDomain $emailDomain)
{

    $emailDomain->update($request->all());

    return redirect()->route('organizations.emaildomains.index', [
            'organization' => $request->organization_id
    ])->withStatus(__("Org's email domain successfully updated."));
}

Note that if the variable name $emailDomain is different from the route segment {emailDomain}, then laravel will not be able to resolve the model. Therefore you will get an empty OrganizationEmailDomain model and it will not update any data. So make sure to put the same name defined in the route.

To check which is the correct name of the route run the command php artisan route:list and you will see the route and the name of the segment.


Edit

In order to solve the problem, I ran

php artisan route:list

which showed

organizations/{organization}/emaildomains/{emaildomain} | organizations.emaildomains.update

So, changing the OrganizationEmailDomainController.php to

/**
 * Update the specified resource in storage.
 *
 * @param  \Illuminate\Http\OrganizationEmailDomainRequest  $request
 * @param  \App\OrganizationEmailDomain  $emaildomain
 * @return \Illuminate\Http\Response
 */
public function update(OrganizationEmailDomainRequest $request, OrganizationEmailDomain $emaildomain)
{

    $emaildomain->update($request->all());

    return redirect()->route('organizations.emaildomains.index', ['organization' => $request->organization_id])->withStatus(__("Org's email domain successfully updated."));
}

was enough.

Notice that the only needed change was in the controller from $email_domain to $emaildomain yet also removed the unnecessary bit to get the organization_id and used instead the suggsted above through the $request.

这篇关于Laravel编辑浅层嵌套资源的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆