Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a form for hasManyThrough relationship, with pivot, in a Laravel5 view

I am coming from a Rails background where we can create has_many_through pretty easily with the right references.

My models in this project: Deal <=> DealsFaqs <=> Faqs

In the Deals model I have:

    public function faqs(){
        return $this->hasManyThrough('App\Faq', 'App\DealsFaqs');
    }

DealsFaqs has:

    public function deals()
    {
        return $this->belongsTo('App\Deal');
    } 

     public function faqs()
     {
         return $this->belongsTo('App\Faq');
     }

and my Faq model has:

    public function deals(){
        return $this->hasManyThrough('App\Deal', 'App\DealsFaqs');
    }

A deal needs to be able to be associated with N faqs.

So I created a table for DealsFaqs that has a deal_id and a faq_id fields.

I am easily able to list the FAQ's on the Deal form page, but that isn't tied to the DealsFaqs.

How do I output the faqs but submit them through the form in a way that I can then check the relationship in the controller on submission?

--- EDIT BASED ON REQUEST FOR MORE CODE AND DETAIL:

Ultimately there will be roughly 20-30 faqs. And a growing number of deals. As the admin creates each deal they need to select which FAQ's are relevant to the deal. Some will be relevant and others won't be. Then those FAQ's will be output to the page.

I assumed I needed a hasManyThrough because I can't just put a single faq_id field on the Deal as it needs many and the same on the FAQ. FAQ's belong to many deals.

My DealCreate Method in the Controller:

    ///////////////////
    // ASSOCIATE FAQ's TO DEALS
    ///////////////////
    if($request->faqs){
        foreach($request->faqs as $key => $faq){

            // Create new DealsFaqs
            $entry = new \App\DealsFaqs;

            // Populate it
            $entry->faq_id = $faq['id']; 
            $entry->deal_id = $deal->id;            

            $entry->save(); // Save the DealsFaqs
        }
    }

Then my current form section to relate FAQ's to deals:

       <?php $a=0; foreach($faqs as $faq): ?>
        <div class="col-sm-12">
            <label>
                <input type="radio" name="faqs[{{ $a }}][id]" value="{{ $faq->id }}">
                {{ $faq->name }} 
            </label>
        </div>
        <?php $a++; endforeach; ?>

When I select 1 or all of them a new relationship is created on the deals_faqs table I created. But then for obvious reasons (I don't know how to solve) But the radios don't know to stay checked, and I don't know how to access/update in the controller. ALSO is this the right way to do this or am I wrong with the relationships?

like image 926
TJ Sherrill Avatar asked Mar 07 '16 23:03

TJ Sherrill


1 Answers

You said you're dealing with a has many through relationship, which as I understand it requires 3 separate models to work. I feel like you're working with a many to many relationship as it only appears you're working with two models.

As you said you're coming from a Rails background I feel like I'm either making a huge mistake and don't understand your db relationships or you have got many to many and has many through mixed up.

FYI: Has many through, from the laravel docs:

The "has-many-through" relationship provides a convenient short-cut for accessing distant relations via an intermediate relation. For example, a Country model might have many Post models through an intermediate User model.

Read further here: https://laravel.com/docs/5.2/eloquent-relationships#has-many-through

and on many to many: https://laravel.com/docs/5.2/eloquent-relationships#many-to-many

If you're working with many to many, I feel your database schema should consist of three tables:

deals, faqs and the intermediate table deal_faq, the third table name follows laravel conventions for an intermediate table where the singular names of the connected tables are used in alphabetical order with an underscore between. The table deal_faq would need a deal_id and faq_id.

You would then require two models (only two, not three)

Deal and Faq, with the following relationship methods:

Deal model:

public function faqs(){
    return $this->belongsToMany('App\Deal');
}

Faq model:

public function deals(){
    return $this->belongsToMany('App\Faq');
}

Now, to make use of these you can do the following, for example:

// get a deal
$deal = App\Deal::first(); // grab the first one in the db

// get faqs linked to deal
$deal->faqs;

// connect an faq and deal together
$faq = App\Faq::first();
$deal->attach($faq->id); // where id is the primary key attribute

Please note this answer assumes you're following the conventions laravel sets when defining relationships.

And I'm sorry to say, I don't quite fully understand this part of your question: "How do I output the faqs but submit them through the form in a way that I can then check the relationship in the controller on submission?"

I am assuming you're asking, if I submit an Faq in a form, how can I grab the Faq's relationship. In that case you could do something like this, if you're using the Faq's id in your form request.

$faqId = $request->faq_id;

$faq = App\Faq::find($faqId);

$deals = $faq->deals;

As you haven't shown much code it's hard to say and I've made a lot of assumptions. Anyway, hope this helped and if you need some further clarification please ask and provide more details of your code if you can.

like image 178
haakym Avatar answered Nov 09 '22 12:11

haakym