Pergunta

I'm new to Laravel, and I'm being dumb on this for sure, cause i've read the documentation and i've searched all over google but i'm not getting how to go over this. I have a M:M relationship between galleries and artist. Inside each gallery edit page I have a form to update the name and url for the gallery that is working fine. In the same page I have 2 other select forms, one for adding artists to the gallery and another to remove artists, that need to update a pivot table called "galleries_artists". I created 2 custom methods for both these forms called "postAdd" and "postRemove" but I can't put them to work regardless of what I try. Below is the code i have so far. Hope somebody can help me understand the dumb mistakes i'm making.

Model - 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');
    }
}

Model - 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');
    }

}

Controller - 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 Add Form

{{ 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 Remove Form

{{ 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');

I've been doing so many changes to the code that a lot of things might be mixed up. Sorry if that's the case.

Foi útil?

Solução

You are making it pretty difficult. Here is what I did, but with checkboxes, which allowed me to cut down on the number of functions and forms I needed to work with. I've skipped the validation, but what I do have was tested and seems to work fine.

Swapping out the checkboxes for a select shouldn't be too much additional work, but I'd suggest going with a multi-select in that case, because again, it would be much simpler to work with for you and much easier to use from the user's standpoint. Let me know if I should modify my answer if it has to be selects.

Controller

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);
    }
}

View

@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

Routes

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

Edit

Just getting your postAdd() method to work, all that should be required is something like this...

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();
}

I may be a little confused on the purpose of this function. As I wrote it, it will attach a selected artist to a gallery. I'm not sure of the purpose of using input. It looks as though you may also be attempting to save a new artist as though you wish your users to be able to create a new artist and assign that artist to a gallery when the artist is created? If you are passing in the artist id and the gallery id, that should be all you need and there is no need for the Input class.

Usually though, you'd be only passing in the gallery id which you would have generated a link for and it would be in the URI and the artist would be passed in via the form, in which case you would need to use Input::get('add_artist') and that would keep your URI much cleaner as well.

The postRemove() function would be the exact same, except you'd want to use detach() instead. This is all assuming of course all the rest of the functionality which is responsible for passing in the gallery id and artist id are working as well as the relationships themselves you've already setup in your models.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top