Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

littledaggers's avatar

Can't store foreign key when I add a new entry to database

I'm working on a situation where I wanna create a new Quotation Followup to an existing Quotation. When I create a new Quotation Followup , everything but the Quotation id (foreign key) is saving.

My Followup migration is

public function up()
    {
        Schema::create('quotation_followup', function (Blueprint $table) {
            $table->id();
            $table->bigInteger('client_quotation_id')->unsigned()->index()->nullable();
            $table->foreign('client_quotation_id')->references('id')->on('client_quotation')->onDelete('cascade');
            $table->string('followup_method');
            $table->mediumText('client_feedback');
            $table->integer('done');
            $table->date('date')->nullable();
            $table->string('created_by');
            $table->tinyinteger('holding_id')->default('1');
            $table->timestamps();
        });
    }

My Quotation Followup Model:

class QuotationFollowup extends Model
{
    use HasFactory;


    protected $table = 'quotation_followup';

      protected $fillable = [
            'client_quotation_id',
            'followup_method',
            'client_feedback',
            'done',
            'date',
            'created_by',
            'holding_id'
      ];

      public function quotation()
      {
        return $this->hasOne(ClientQuotation::class, 'client_quotation_id');
      }
}

my Quotation Model:

class ClientQuotation extends Model
 
{
    use HasFactory;

    protected $table = 'client_quotation';

      protected $fillable = [
            'name',
            'email',
            'phone_number',
            'contact_person',
            'date_of_sending_inquiry',
            'joinery_name',
            'verification_date',
            'notes',
            'verified_receipt',
            'created_by',
            'holding_id'
      ];

      public function followup()
      {
          return $this->belongsTo(QuotationFollowup::class, 'id', 'client_quotation_id');
      }

    }

my FollowupController is:

    public function addfollowup(Request $request)
    {
        $quot = ClientQuotation::get();
        $validatedData = $request->validate([
            'followup_method' => 'required',
        ]);

        $follow = new QuotationFollowup;
        $quot = ClientQuotation::find(1);
        $quot->followup()->associate($follow);
        $follow->followup_method = json_encode($request->followup_method);
        $follow->client_feedback = $request->input('client_feedback');
        $follow->done = $request->done == true ? '1':'0';
        $follow->date = $request->input('date');
        $follow->created_by = auth()->user()->name;
        $follow->save();

  return redirect()->route('quot.index')->with('status','Quotation Followup Added Successfully');
    }

My question is do I have the logic inverted in my mind? should the foreign key be on the quotation followup migration or the quotation migration? And in case I am on the right path, what should I change in the addfollowup function in the controller?

Thank you in advance.

0 likes
11 replies
tykus's avatar
tykus
Best Answer
Level 104

First associate really expects a Model that has already been persisted - if you new-up a Followup instance, then it doesn't have an id.

IMO, a Quotation hasOne Followup; a Followup belongsTo a Quotation.

Also, you if want to ensure that there is only one Followup allowed, I would maybe change the Controller code as follows (depending on how you intend to force hasOne:

public function addfollowup(Request $request)
{
    $validatedData = $request->validate([
        'followup_method' => 'required',
    ]);

    $follow = QuotationFollowup::updateOrCreate([
            'client_quotation_id' => 1 // why always `1` above????
    ], [
        'followup_method' => json_encode($request->followup_method),
        'client_feedback' => $request->input('client_feedback'),
        'done' => $request->done,
        'date' => $request->input('date'),
        'created_by' => auth()->user()->name, // would be better as a FK!
    ])
1 like
littledaggers's avatar

@tykus thank you for your answer, but I have a question. In that case if the Quotation hasOne Followup, does that mean I should add the foreign key in the Quotation table instead of the Followup table?

littledaggers's avatar

as for why 1, I thought the 1 means find 1 id? or does it mean find the id of value 1? in that case should I use find($id) instead?

littledaggers's avatar

@tykus and I cannot make the user()->name as a FK because Im updating the code of a website that is already published and I don't wanna risk losing any data by editing any of the code that the coder before me made, but I will keep that as a memo for my future projects, thank you!

tykus's avatar

@littledaggers

In that case if the Quotation hasOne Followup, does that mean I should add the foreign key in the Quotation table instead of the Followup table?

For a one-to-one, technically the FK can be on either table, but I would ask which comes first... the Quotation or the Followup. In your case I would argue that a Followup belongs to a Quotation, so the FK would be on the Followup model.

as for why 1, I thought the 1 means find 1 id? or does it mean find the id of value 1? in that case should I use find($id) instead?

Yes, providing you are getting that ID from the Request (URL segment or Request payload). Otherwise, you are ever only working with one Quotation (the one with ID of 1).

I cannot make the user()->name as a FK because Im updating the code of a website that is already published

Understood.

littledaggers's avatar

@tykus

For a one-to-one, technically the FK can be on either table, but I would ask which comes first... the Quotation or the Followup. In your case I would argue that a Followup belongs to a Quotation, so the FK would be on the Followup model.

Yes you are correct, Quotation comes first, Followup comes next.

Yes, providing you are getting that ID from the Request (URL segment or Request payload). Otherwise, you are ever only working with one Quotation (the one with ID of 1).

I still have an issue with implement the find($id). If I was to use:

$quot = ClientQuotation::find($id); 

what should come first to make that id defined? Cause it is always throwing me an error that the id is undefined whether I use:

$quot = ClientQuotation::get();

or 

$quot = ClientQuotation::all();
tykus's avatar

@littledaggers obviously $id is undefined, then you'll get an error message - this is why I mention "providing you are getting that ID from the Request".

What does the Route for that addfollowup action look like?

get and all both return a Collection of Models - you don't want this.

1 like
littledaggers's avatar

@tykus The Route looks like:

Route::get('/addfollowup', [FollowupController::class ,'addfollowupview'])->name('followup.addfollowup');

And now that you explained it better, I see what you mean. If I was to call for $id, my route should have '/addfollowup/{$id} and my function should be

public function addquot(Request $request, $id)

so thank you so much for the clarification! I think that my issue begins with updating the route to have the ability to include an id

tykus's avatar

@littledaggers correct, except there would be no $ on the wildcard segment /addfollowup/{id}

Otherwise, a nested resource approach would be:

Route::post('quotations/{quotation}/followup', [/* Controller and Action */]);
1 like
littledaggers's avatar

@tykus true true, I just made a silly typo with adding $. As for the main issue at hand, I will keep on updating everything that I need to change in my code. As an intern who is still learning laravel from scratch it's taking me some time to do the changes, so might take me some time (maybe till tomorrow if couldn't before my shift ends) to see if implementing the changes fixes my issue.

But thank you for your time!

littledaggers's avatar

@tykus Never mind! It took me no time! You're such a time saver! The main issue is resolved, I'm getting the id of the followup linked to the id of the quotation, thank you so much!

Please or to participate in this conversation.