Search code examples
mysqlyiirelational-database

Foreign Key In MySQL using Yii


I have the database just like this

==== Invoices ====
id
customer_id
description

==== Customers ===
id
firstname
lastname

Now I have made the relation in between models just like this. In Invoices models the relation is as like this

public function relations()
{
    return array(
        'customer' => array(self::BELONGS_TO, 'Customer', 'customer_id')
    );
}

In customer model the relation is just like this

public function relations()
{
    return array(
      'invoice' => array(self::HAS_MANY, 'Invoices','customer_id')
    );
}

Now as my relation is defined one customer has many invoices and the invoice is belongs to the customer.

Now I made multimodel and loaded the Customer model into Invoice model just like this.

public function actionCreate()
{
    $model = new Invoices;
    $customers = new Customers;
    // Uncomment the following line if AJAX validation is needed
    // $this->performAjaxValidation($model);

    if (isset($_POST['Invoices'],$_POST['Customers']))
    {
      $model->attributes = $_POST['Invoices'];
      $customers->attributes = $_POST['Customers'];
      $valid = $model->validate();
      $valid = $customers->validate();
      if($valid)
      {
        $model->save(false);
        $customers->id = $model->customer_id;
        $customers->save(false);
        $this->redirect(array('view','id'=>$model->id));
      }
    }

    $this->render('create',array(
      'model'=>$model,
      'customers'=>$customers,
    ));
}

Here everything is okay. I can insert the data for both models easily. But my problem comes here in the way that when I am inserting data from Invoice multimodel the foreign key id is not changing. It is showing zero every time. Can some one tell me where I am wrong.

Any help and suggestions will be highly appreciated.


Solution

  • My guess is that you are overriding the customer's primary key with the invoice's foreign key. I do not say that's not correct that way (maybe in your scenario it makes sense).

    Let me explain what you are doing in that code:

    • First, you create new instances of two models, Invoices and Customers. Yii understands that as "they wish to insert new items in the database".

    • Then, you check if there are the items coming from an ajax form. If true, then,

    • You populate Invoices (defined as $model. I'd change it to $invoice, in case you need to edit and understand it further).
    • You also popupulate the customer's information, overriding the $valid value (so, you don't know if invoice is actually valid).
    • If valid (remember you're only validating customer's information), do,
    • Save the invoice
    • Override customer's id with invoice's foreing key to customer.
    • Save the customer, and redirect.

    Now, what I got from that:

    • $valid doesn't work as expected: I'd change that to an incremental assignment.
    • You may not be passing a customer_id coming from the ajax form. Foreing keys are integers, and so if not defined within a model, it becomes 0 or NULL.
    • You are always passing id = 0 / NULL to Customer's model, so it would probably warn you when validating. However, you are using save(false), which means it doesn't pre-validate on save, so you never know it doesn't work.

    So, according to this:

      public function actionCreate()
      {
        $invoice = new Invoices;
        $customers = new Customers;
        // Uncomment the following line if AJAX validation is needed
        // $this->performAjaxValidation($invoice);
    
        if (isset($_POST['Invoices'],$_POST['Customers']))
        {
          $invoice->attributes = $_POST['Invoices'];
          $customers->attributes = $_POST['Customers'];
          $valid = true; /* expect it is always valid */
          $valid &= $invoice->validate(); /* if $invoice is not valid, $valid will be false (true&false = false) */
          $valid &= $customers->validate(); /* same as the above line */
          if($valid)
          {
            $customers->save(); /* First save customers. It's the Foreign item */
            $invoice->customer_id = $customers->getPrimaryKey(); /* new instances use getPrimaryKey() to get its id */
            $invoice->save(); /* Save invoice AFTER getting customer's primary key */
            $this->redirect(array('view','id'=>$invoice->id));
          }
        }
    
        $this->render('create',array(
          'invoice'=>$invoice,
          'customers'=>$customers,
        ));
      }
    

    I hope this solves your problem.