2

I have two tables that have (1:1) relationship between each others.

customers table:
 - customerID (PK)(AI)
 - customerName
 - phone

addresses table:
 - customerID (PK&FK)
 - address
 - city
 - zipcode

I tried to update them in the same CodeIgniter view form.

update_view.php

<th>Customer Name:</th>
<td><input type="text" name="customerName"/></td>
<tr>
<th>Customer Phone:</th>
<td><input type="text" name="phone"/></td>
<tr>
<th>Address:</th>
<td><input type="text" name="address"/></td>
<tr>
<th>City:</th>
<td><input type="text" name="city"/></td>
<tr>
<th>Zip Code:</th>
<td><input type="text" name="zipcode"/></td>

This is part of the my controller code:

    public function insert()
        {      
            $this->load->database();
            $this->load->model('my_model');
            $this->my_model->insert_entry();

            $custInsert=$this->my_model->get_all_customers();
            $this->load->view('main_view',array('customer'=>$custInsert));
..
}

Note: up to this point everything was working for process the one table (customers).

This is the part of my model file:

function insert_entry()
    {
        $this->customerName   = $_POST['customerName']; 
        $this->phone = $_POST['phone'];
        $this->db->insert('customers', $this); // up to here it was working

        //$customerID=$db->insert_id;
        $customerID=$this->db->query("SELECT MAX(customerID) FROM `customers`");
        $this->customerID;
        $this->address = $_POST['address'];
        $this->city = $_POST['city'];
        $this->zipcode = $_POST['zipcode'];
        $this->db->insert('addresses', $this);
}

As for me the problem is the 'addresses' table need to customerID, but I don't insert it handly (auto_increment). I tried to many way for get it after inserted to customers table but I cant do it. Is there anybody know different way or what should I do in that way?

halfer
  • 19,824
  • 17
  • 99
  • 186
thatway_3
  • 404
  • 1
  • 10
  • 22
  • 2
    A great question, and a good improvement on the last question. Questions containing detail and prior attempts are encouraged here! +1 – halfer Jul 17 '14 at 16:44

2 Answers2

4

Doing this is a bad idea... how is your app going to handle when new customers are being added at nearly the same exact time?

$customerID=$this->db->query("SELECT MAX(customerID) FROM `customers`");

You should get rid of that line and use the method that is preferred and works. If you do not, it can and will inevitably result in you fetching the wrong record for a customer at some point in time and associating an address with the wrong customer.

This is because two clients running the code at (nearly enough) the same time might encounter the MAX() at the same point in time, and thus each could get the same value. When they both try to save, only one will succeed, and the other will fail due to the primary key constraint. This situation is known as a race condition and should be guarded against.

Use this instead:

 $this->db->insert_id()

also this:

$this->customerID;

should be:

$this->customerID = $this->db->insert_id();
halfer
  • 19,824
  • 17
  • 99
  • 186
skrilled
  • 5,350
  • 2
  • 26
  • 48
  • http://www.databaseprimer.com/pages/relationship_1to1/ I designed to one-to-one relationship according to that website. I tried $this->db->insert_id() so many times, but it dossnt working as well – thatway_3 Jul 17 '14 at 00:17
  • it doesn't work as well? can you explain that? that's the method that always works. your replaced way of doing it is a hacked up way going completely against what you should be doing, and it will fail if your application gets any type of decent traffic ever :/ – skrilled Jul 17 '14 at 00:20
  • thank you for your interest. It is trying to add all values to second table and I had this error. A Database Error Occurred Error Number: 1054 Unknown column 'customerName' in 'field list' INSERT INTO `addresses` (`customerName`, `phone`, `customerID`, `address`, `city`, `zipcode`) VALUES ('sds', 'sds', 46, 'sd', '88', '99') Filename: C:\wamp\www\CodeIgniter_2\system\database\DB_driver.php Line Number: 330 – thatway_3 Jul 17 '14 at 01:21
  • 1
    @sadik_3 in address table there is only 3 fields, only id,name,phone – Adarsh M Pallickal Jul 17 '14 at 04:03
  • updated with a bit more explanation as you suggested – skrilled Jul 17 '14 at 18:45
  • 1
    Thanks. I've edited it further, mainly to explain race conditions; feel free to tweak as you wish. +1 – halfer Jul 17 '14 at 18:52
-1

A cleaner way to achieve what you want is to use arrays instead of $this. You will have all the info you need and nothing more. There is a lot of stuff in your $this object than you don't need.

In your controller

public function insert()
{      
    $this->load->database();
    $this->load->model('my_model');

    $data_user = array(
      'customerName' => $this->input->post('customerName'),
      'phone'        => $this->input->post('phone')
    );

    $data_address = array(
      'address'    => $this->input->post('address'),
      'city'       => $this->input->post('city'),
      'zipcode'    => $this->input->post('zipcode')
    );    

    $this->my_model->insert_entry($data_user, $data_address);

    [...]
}

In your model

function insert_entry($data_user, $data_address) {

    $this->db->insert('customers', $data_user);

    $data_address['customerID'] = $this->db->insert_id();

    $this->db->insert('addresses', $data_address);
}

A good practice is also to use the Input Class of Codeigniter when you get your $_POST variables. Just use the following :

$this->input->post('VAR_NAME') instead of $_POST['VAR_NAME']

Adrian Tombu
  • 696
  • 6
  • 11
  • This is the exactly answer of my question :) Thanks – thatway_3 Jul 17 '14 at 11:14
  • downvoted since bad practice to use post within a model itself. MVC architecture clearly recommends "The Controller transforms $_POST data into a Model's object and only passes the object to Model." You solved OP's answer by teaching him to do something completely against the concepts he should be learning (and you did his work for him instead of teaching him anything) – skrilled Jul 17 '14 at 18:37
  • 2
    @skrilled (and Adrian) isn't the code here a controller rather than a model? – halfer Jul 17 '14 at 18:40
  • No, it's a model. I didn't have time to go into it yesterday as I was only trying to answer OP's original question (before he edited) which was how to insert the relationship. – skrilled Jul 17 '14 at 18:44
  • I'm not familiar with CodeIgniter @skrilled, but surely if this was a model, `$this->input` (to contain the superglobals in an object) would not be available? Surely that class _would_ be available in a controller class? – halfer Jul 17 '14 at 18:46
  • CodeIgniter makes it available in both the controller unlike many other frameworks. Sadly their forums are littered with people recommending things that simply work but go against best practices. – skrilled Jul 17 '14 at 18:48
  • "makes it available in both the controller" - expect you meant to say "and the model" here. If so, ouch! – halfer Jul 17 '14 at 18:55
  • @skrilled, this is [from the docs](http://ellislab.com/codeigniter/user-guide/general/models.html): _Note: For the sake of simplicity in this [model] example we're using $_POST directly. This is generally bad practice, and a more common approach would be to use the Input Class $this->input->post('title')_. – halfer Jul 17 '14 at 19:05
  • That's still bad. MVC architecture clearly explains that accessing POST data within a model is poor practices. Sure it works, but are you always going to be using $_POST to register a user? What happens when you go make an API that also inserts users. What happens when you are working on the admin section which uses entirely different fields. This function is now only good for one purpose and one purpose only, and therefore defeats the concept of using a model to begin with. OP could have put this all in a controller and it'd be better than trying to access $_POST within a model. – skrilled Jul 17 '14 at 19:08
  • 1
    The possibilities of inserting a user shouldn't be limited to a $_POST request and nothing else. What OP did is defeat the entire purpose of using a model to begin with. http://stackoverflow.com/questions/13359818/what-is-the-right-way-to-handle-post-data-in-mvc "In the MVC and MVC-inspired design patterns the model should be aware of neither the user interface nor of the presentation layer as whole. The $_POST variable in PHP is a superglobal. If you use it with model layer, your code becomes bound to the web interface and even the specific request method." – skrilled Jul 17 '14 at 19:09
  • Just to be clear, I didn't wan't to lose `thatway_3` by changing all his code, this is why I made that shorcut using the `$_POST` in his model. That was obviously a bad idea, you are right about that. So I changed my answer to respect better the good practices of MVC. – Adrian Tombu Jul 17 '14 at 21:46
  • And that would be a bit intelligent to remove your downvotes, by the way. People coming here won't take this answer seriously, even though it's a correct one. – Adrian Tombu Jul 18 '14 at 21:28
  • Thanks for the laugh bro, digging out a 1 1/2 year downvoted answer, you just made my day <3 – Adrian Tombu Jan 01 '16 at 14:15