Search code examples
phplaravelvue.jspolymorphism

Laravel Form best way to store polymorphic relationship


I have a notes model. Which has a polymorphic 'noteable' method that ideally anything can use. Probably up to 5 different models such as Customers, Staff, Users etc can use.

I'm looking for the best possible solution for creating the note against these, as dynamically as possible.

At the moment, i'm adding on a query string in the routes. I.e. when viewing a customer there's an "Add Note" button like so:

route('note.create', ['customer_id' => $customer->id])

In my form then i'm checking for any query string's and adding them to the post request (in VueJS) which works.

Then in my controller i'm checking for each possible query string i.e.:

if($request->has('individual_id'))
{
   $individual = Individual::findOrFail($request->individual_id_id);
   // store against individual
   // return note
   }elseif($request->has('customer_id'))
   {
      $customer = Customer::findOrFail($request->customer_id);
      // store against the customer
      // return note
   }

I'm pretty sure this is not the best way to do this. But, i cannot think of another way at the moment.

I'm sure someone else has come across this in the past too!

Thank you


Solution

  • Not sure about the best way but I have a similar scenario to yours and this is the code that I use.

    my form actions looks like this

    action="{{ route('notes.store', ['model' => 'Customer', 'id' => $customer->id]) }}"
    action="{{ route('notes.store', ['model' => 'User', 'id' => $user->id]) }}"
    

    etc..

    And my controller looks this

    public function store(Request $request)
    {
        // Build up the model string
        $model = '\App\Models\\'.$request->model;
        // Get the requester id
        $id = $request->id;
    
        if ($id) {
            // get the parent 
            $parent = $model::find($id);
            // validate the data and create the note
            $parent->notes()->create($this->validatedData());
            // redirect back to the requester
            return Redirect::back()->withErrors(['msg', 'message']);
        } else {
            // validate the data and create the note without parent association
            Note::create($this->validatedData());
            // Redirect to index view
            return redirect()->route('notes.index');
        }
    }
    
    protected function validatedData()
    {
        // validate form fields
        return request()->validate([
            'name' => 'required|string',
            'body' => 'required|min:3',
        ]);
    }