【问题标题】:Laravel, Form::select unable to update many to many relationshipLaravel,Form::select 无法更新多对多关系
【发布时间】:2014-04-28 17:44:52
【问题描述】:

我是 Laravel 的新手,我肯定对此很愚蠢,因为我已经阅读了文档并且我已经在谷歌上进行了搜索,但我不知道如何解决这个问题。我在画廊和艺术家之间有着 M:M 的关系。在每个图库编辑页面中,我都有一个表单来更新运行正常的图库的名称和 url。在同一页面中,我还有另外 2 个选择表单,一个用于将艺术家添加到画廊,另一个用于删除艺术家,它们需要更新一个名为“galleries_artists”的数据透视表。我为这两种表单创建了 2 个自定义方法,称为“postAdd”和“postRemove”,但无论我尝试什么,我都无法让它们发挥作用。 下面是我到目前为止的代码。希望有人能帮助我理解我正在犯的愚蠢错误。

模型 - Artist.php

class Artist extends Eloquent {

    protected $fillable = array('name');

    public static $rules = array(
        'name'=>'required|min:2'
    );

    public function galeries() {
        return $this->belongsToMany('Gallery', 'galeries_artists', 'artist_id', 'gallery_id', 'stand_id');
    }
}

模型 - Gallery.php

class Gallery extends Eloquent {

    protected $fillable = array('name', 'stand_id', 'url');

    public static $rules = array(
        'stand_id'=>'required|integer'
    );

    public function stand() {
        return $this->belongsTo('Stand');
    }

    public function artist() {
        return $this->belongsToMany('Artist', 'galleries_artists', 'gallery_id', 'artist_id', 'stand_id');
    }

}

控制器 - GalleriesController.php

public function postAdd($id, $aid) {

        $input = array_except(Input::all(), '_method');
        $v = Validator::make(Input::all(), Artist::$rules);

        if ($v->passes()) {
            $gallery = Gallery::find($id);
            $add_artist = Input::get();
            $add_artist->galleries()->attach(Input::get('add_artist'));
            $add_artist->save();

            return Redirect::route('admin.galleries.edit')
            ->with('message', 'Artist added successfully.');
        }

        return Redirect::route('admin.galleries.edit')
            ->with('message', 'Something went wrong')
            ->withErrors($v)
            ->withInput();
    }

    public function postRemove($id, $aid) {

        $input = array_except(Input::all(), '_method');
        $v = Validator::make(Input::all(), Artist::$rules);

        if ($v->passes()) {
            $gallery = Gallery::find($id);
            $remove_artist = Input::get();
            $remove_artist->galleries()->detach(Input::get('remove_artist'));
            $remove_artist->save();

            return Redirect::route('admin.galleries.edit')
            ->with('message', 'Artist removed successfully.');
        }

        return Redirect::route('admin.galleries.edit')
            ->with('message', 'Something went wrong')
            ->withErrors($v)
            ->withInput();

    }

edit.blade.php 添加表单

{{ Form::open(array('class' => '', 'method' => 'put', 'action'=> array('GalleriesController@postAdd', $gallery->id , $add_artist->id ))) }}
                                                <div class="form-group">
                                                    {{ Form::label('Add Artist:') }}
                                                    {{ Form::select('add_artist', $other_artists_name, null, array('class'=>'form-control')) }}
                                                </div>
                                                {{ Form::button('Add Artist', array('type' => 'submit', 'class'=>'btn btn-primary')) }}
                                                {{ Form::close() }}

edit.blade.php 删除表格

{{ Form::open(array('class' => '', 'method' => 'put', 'action'=>array('GalleriesController@postRemove', $id , 'aid'))) }}
                                                <div class="form-group">
                                                    {{ Form::label('Remove Artist:') }}
                                                    {{ Form::select('remove_artist', $gallery_artists_name, null, array('class'=>'form-control')) }}
                                                </div>
                                                {{ Form::button('Remove Artist', array('type' => 'submit', 'class'=>'btn btn-danger')) }}
                                                {{ Form::close() }}

Routes.php

Route::post('admin/galleries/{galleries}/add/{aid}', 'GalleriesController@postAdd');
Route::post('admin/galleries/{galleries}/remove/{aid}', 'GalleriesController@postRemove');
Route::resource('admin/galleries', 'GalleriesController');

我一直在对代码进行如此多的更改,以至于很多事情可能会混淆。对不起,如果是这样的话。

【问题讨论】:

    标签: select laravel laravel-4 many-to-many pivot-table


    【解决方案1】:

    你让事情变得非常困难。这是我所做的,但使用了复选框,这使我能够减少需要使用的函数和表单的数量。我跳过了验证,但我所做的已经过测试并且似乎工作正常。

    为选择换出复选框不应该是太多额外的工作,但我建议在这种情况下使用多选,因为同样,它对您来说更简单,也更容易从用户的角度来使用。如果必须选择,请告诉我是否应该修改答案。

    控制器

    class ArtController extends BaseController {
    
        public function getIndex($artist_id)
        {
            // Get our artist with associated galleries
            $artist = Artist::find($artist_id);
            $artist->load('galleries');
    
            // Get all galleries to populate our checkboxes
            $galleries = Gallery::all();
    
            // Show form
            return View::make('art.gallery_update_form')->with('artist', $artist)->with('galleries', $galleries);
        }
    
        public function postIndex($artist_id)
        {
            // Grab our artist
            $artist = Artist::find($artist_id);
    
            // Sync the galleries.  If no galleries were chosen, send it an empty array.  Sync will perform both write and delete operations for you in one shot.  Very handy.
            $artist->galleries()->sync(Input::get('galleries', array()));
    
            // Reshow the form
            return $this->getIndex($artist_id);
        }
    }
    

    查看

    @section('content')
        {{ Form::open() }}
    
        <!-- Get a list of our ID's so we can check/uncheck the checkboxes as we go -->
        <?php $artist_galleries = $artist->galleries->lists('id'); ?>
    
        <!-- Create checkbox for each gallery -->
        @foreach($galleries as $gallery)
            {{ Form::label($gallery->id, $gallery->name) }}
    
            <!-- 3rd parameter is where the magic happens, it's looking in our list of galleries 
            we created a few lines up for the id to see if the artist belongs to that gallery or not -->
            {{ Form::checkbox('galleries[]', $gallery->id, in_array($gallery->id, $artist_galleries), array('id' => $gallery->id)) }}
            <br />
        @endforeach
    
        {{ Form::submit() }}
        {{ Form::close() }}
    @stop
    

    路线

    Route::get('art/{artist_id}', array('uses' => 'ArtController@getIndex'));
    Route::post('art/{artist_id}', array('uses' => 'ArtController@postIndex'));
    

    编辑

    只要让你的 postAdd() 方法工作,所需要的就是这样的......

    public function postAdd($id, $aid) 
    {
    
        $input = array_except(Input::all(), '_method');
        $v = Validator::make(Input::all(), Artist::$rules);
    
        if ($v->passes()) {
            $gallery = Gallery::find($id);
            $gallery->artists()->attach($aid);
    
            return Redirect::route('admin.galleries.edit')
            ->with('message', 'Artist added successfully.');
        }
    
        return Redirect::route('admin.galleries.edit')
            ->with('message', 'Something went wrong')
            ->withErrors($v)
            ->withInput();
    }
    

    我可能对这个函数的目的有点困惑。正如我写的那样,它会将选定的艺术家附加到画廊。我不确定使用输入的目的。看起来您可能还试图保存新艺术家,就好像您希望您的用户能够创建新艺术家并在创建艺术家时将该艺术家分配到画廊?如果您传入艺术家 ID 和画廊 ID,这应该就是您所需要的,并且不需要 Input 类。

    不过,通常情况下,您只会传入您会为其生成链接的画廊 ID,它会在 URI 中,并且艺术家将通过表单传入,在这种情况下,您需要使用Input::get('add_artist'),这也会让你的 URI 更干净。

    postRemove() 函数将完全相同,只是您想改用 detach()。当然,这一切都是假设负责传递画廊 ID 和艺术家 ID 的所有其他功能以及您已经在模型中设置的关系本身都正常工作。

    【讨论】:

    • 谢谢您,非常感谢您的回答。我还没有用复选框尝试过你的建议(对不起),但我今天花了几个小时试图吸收你的建议逻辑,并进行更多研究,以便我可以通过选择输入来解决这个问题。仍然没有成功。这可能是一个顽固的 UI 选择,但我宁愿通过选择来实现这一点。如果我只能理解如何解决 postAdd 方法...我只是无法理解将输入 id 附加到数据透视表的方式...我要疯了 =/
    • 我在我的答案中添加了一个更新的 postAdd() 函数,希望对你有用..
    • 我刚刚开发了整个过程,因为您正在做的一些事情对 URI 等没有多大意义……希望它有助于解决您可能遇到的任何问题。可以在这里查看...laravel.io/bin/oXjz2
    • 非常感谢!这绝对有很大帮助!
    猜你喜欢
    • 2018-07-16
    • 2014-09-02
    • 1970-01-01
    • 2020-03-05
    • 1970-01-01
    • 1970-01-01
    • 2021-11-25
    • 2018-09-26
    • 2019-12-11
    相关资源
    最近更新 更多