skip to Main Content

Given a Dues and Payment Laravel Eloquent models with the following defined relationships:

    /**
     * Get the payment(s) for this set of dues
     */
    public function payments()
    {
        return $this->hasMany(Payment::class);
    }

    /**
     * Get the Dues to which this payment belongs.
     */
    public function dues()
    {
        return $this->belongsTo(Dues::class, 'dues_id'); // custom key because Laravel assumes no s on model name
    }

where more than one Payment can be assigned to a Dues model (i.e. broken into multiple payments), I am trying to create a Payment and associate it to the Dues model in my controller, and address the case where the Dues model may or may not exist. My thought is to use Eloquent methods to find an existing model if it exists"

    public function store(StorePaymentRequest $request, User $user)
    {
        $validated = $request->validated();

        $calculator = new DuesRenewalCalculator($validated['user_id']);
        $year = Carbon::now()->year;

        $dues = Dues::firstOrNew(
            ['user_id' => $validated['user_id'], 'year' => $year],
            [
                'year' => $year,
                'type' => 'renewal',
                'member_dues' => $calculator->dues,
                'building_assessment' => $calculator->buildingAssessment,
                'work_hours_assessment' => $calculator->workHours,
                'nra_dues' => $calculator->nra,
                'associate_dues' => $calculator->associate,
                'junior_dues' => $calculator->juniors,
                'total' => $calculator->total
            ]
        );

        $dues->user()->associate($user);
        $dues->save();

        $payment = new Payment([
            'payment_date' => $validated['date'],
            'amount' => $validated['amount'],
            'refund' => $validated['refund'],
            'reference' => $validated['reference'],
            'comments' => $validated['comments'],
            'mode' => $validated['mode']
        ]);

        $payment->dues()->associate($dues);
        $payment->save();

        return Redirect::route('user.dues.index', ['user' => $validated['user_id']])->with('success', 'Work Hours saved');
    }

This code works perfectly if both models are new, but if $dues already exists, I get an error that Column dues_id cannot be null. on $payment->dues()->associate($dues);. Is this because associate() only works when the parent model doesn’t exist?

If i try

$dues->payments()->save($payment);

I get

Column not found: 1054 Unknown column 'dues_dues_id' in 'field list'     

What is the easiest way to handle both possibilities (that the parent Dues model does or doesn’t exist)?

2

Answers


  1. Chosen as BEST ANSWER

    Because the model instance returned from firstOrNew() has an id if it's an existing one and doesn't if it is creating a new one, I was able to get my process to work like so:

        public function store(StorePaymentRequest $request, User $user)
        {
            $validated = $request->validated();
    
            $calculator = new DuesRenewalCalculator($validated['user_id']);
            $year = Carbon::now()->year;
    
            $dues = Dues::firstOrNew(
                ['user_id' => $validated['user_id'], 'year' => $year],
                [
                    'year' => $year,
                    'type' => 'renewal',
                    'member_dues' => $calculator->dues,
                    'building_assessment' => $calculator->buildingAssessment,
                    'work_hours_assessment' => $calculator->workHours,
                    'nra_dues' => $calculator->nra,
                    'associate_dues' => $calculator->associate,
                    'junior_dues' => $calculator->juniors,
                    'total' => $calculator->total
                ]
            );
    
            if (!$dues->id) {
                $dues->user()->associate($user);
                $dues->save();
            }
    
            $payment = new Payment([
                'payment_date' => $validated['date'],
                'amount' => $validated['amount'],
                'refund' => $validated['refund'],
                'reference' => $validated['reference'],
                'comments' => $validated['comments'],
                'mode' => $validated['mode']
            ]);
    
            if (!$dues->id) {
                $payment->dues()->associate($dues);
            } else {
                $dues->payments()->save($payment);
            }
    
            $payment->save();
    
            return Redirect::route('user.dues.index', ['user' => $validated['user_id']])->with('success', 'Payment saved');
        }
    

  2. $payment->dues()->associate($dues) only works when $dues exists. if you get an error that Column dues_id cannot be null, it means $dues doesn’t not exist.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search