ycs77/laravel-wizard

Eloquently Save Multiple, Related Models

mcatieno opened this issue · 12 comments

Setting relationship this way is not very clear: public function model(Request $request)
{
return $request->user()->posts();
}

i have this scenario and i would want to save the data in the third step. Basically for me i have 3 steps Claim option, personal details and payment steps.

$claim = new Claim();
$claim->id = $request->claim_id;
$claim->name = $request->name;
$claim->sponsor_letter = $letter;
$claim->exitdate = $request->exitdate;

$nextkin = new NextKin();
$nextkin->kin = $request->kin;
$nextkin->kin_id = $request->kin_id;
$nextkin->kin_email = $request->kin_email;

$payment = new Payment();
$payment->bank = $request->bank;
$payment->branch = $request->branch;
$payment->accountname = $request->accountname;

$claim->save();
$claim->nextkin()->save($nextkin);
$claim->payment()->save($payment);

So i have three steps in which i collect data for the 3 models Claim, NextKin and Payment. The claim_id references the other two tables. How do we save this data. How do to go to the previous step without saving. I believe the last step is to display result.

ycs77 commented

Hi @mcatieno, you can reference Save data on another step part to save your all models data.

This provide a example for last step to saving:

<?php

class LastStep extends Step
{
    public function model(Request $request)
    {
        //
    }

    public function saveData(Request $request, $data = null, $model = null)
    {
        $data = $this->getStepsData();
        dd($data); // check current your all form data
        // save data into models
    }
}
ycs77 commented

This is an example with your provide code:

<?php

class ClaimStep extends Step
{
    public function model(Request $request)
    {
        // don't write any code
    }

    public function saveData(Request $request, $data = null, $model = null)
    {
        // don't write any code
    }
}
<?php

class NextKinStep extends Step
{
    public function model(Request $request)
    {
        // don't write any code
    }

    public function saveData(Request $request, $data = null, $model = null)
    {
        // don't write any code
    }
}
<?php

class PaymentStep extends Step
{
    public function model(Request $request)
    {
        // don't write any code
    }

    public function saveData(Request $request, $data = null, $model = null)
    {
        $data = $this->getStepsData();

        $claim = new Claim();
        $claim->id = $data['claim_id'];
        $claim->name = $data['name'];
        $claim->sponsor_letter = $letter;
        $claim->exitdate = $data['exitdate'];

        $nextkin = new NextKin();
        $nextkin->kin = $data['kin'];
        $nextkin->kin_id = $data['kin_id'];
        $nextkin->kin_email = $data['kin_email'];

        $payment = new Payment();
        $payment->bank = $data['bank'];
        $payment->branch = $data['branch'];
        $payment->accountname = $data['accountname'];

        $claim->save();
        $claim->nextkin()->save($nextkin);
        $claim->payment()->save($payment);
    }
}
ycs77 commented

is not seems not to work on my end.

Please provide more information.

ycs77 commented

If you want to save uploaded file you could try this:

<?php

class PaymentStep extends Step
{
    public function saveData(Request $request, $data = null, $model = null)
    {
        $data = $this->getStepsData();

        $claim = new Claim();

        $sponsor_letter_filename = time().'_'.$data['sponsor_letter']->getClientOriginalName();

        $claim->sponsor_letter = $data['sponsor_letter']->storeAs('documents', $sponsor_letter_filename, [
            'disk' => 'public',
        ]);
        ...
    }
}

Because the file is not uploaded on this request (this example is upload to ClaimStep), you can't use $request->file('...') to get the file, instead of $data['sponsor_letter'].

The $this->getStepsData() will get the cached user input/uploaded data and clean when the wizard ended.

ycs77 commented

Please for me the screenshot of the error.

ycs77 commented

If you want to save the original name of the uploaded image filename, you can change it to this:

First, into your WizardController add a wizardStepSaved(), it will be triggered on step saved or cached, at this time you can save the original filename of the uploaded image into the session:

<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Session;
use Ycs77\LaravelWizard\Step;
use Ycs77\LaravelWizard\Wizardable;

class UserWizardController extends Controller
{
    use Wizardable;

    ...

    protected function wizardStepSaved(Request $request, Step $step)
    {
        if ($step instanceof ClaimStep && $request->hasFile('sponsor_letter')) {
            $originalFilename = $request->file('sponsor_letter')->getClientOriginalName();
            Session::put('sponsor_letter_original_filename', $originalFilename);
        }
    }
}

Then pull the filename into the session on the last step:

<?php

use Illuminate\Support\Facades\Session;

class PaymentStep extends Step
{
    public function saveData(Request $request, $data = null, $model = null)
    {
        $data = $this->getStepsData();

        $originalFilename = Session::pull('sponsor_letter_original_filename');
        $data['sponsor_letter'] = $data['sponsor_letter']->storeAs('documents', time().'_'.$originalFilename, [
            'disk' => 'public',
        ]);

        dd($data);
    }
}