Love Fuel?    Donate

FuelPHP Forums

Ask your question about FuelPHP in the appropriate forum, or help others by answering their questions.
Data entry with ORM and has one and has many relationships
  • I am struggling to work out how to get the ORM to create data in all the required tables (2 of). I could of course create the address, get its ID and use that in the Organisation model, create that and then update the address entry with the new organisations ID (Needed as orgs can have several addresses and we need to know who the address owner is). That, however, seems very inefficient - can the ORM save() method do this? Here is my code (i am aware there is no addresses property, it's just copied from where I have been playing):
    $add = new Model_Organisation();
       $add->user_id = self::$user_id;
       $add->type = 'O'; // Organisation, churches added elsewhere
       $add->name = Input::post('name');
       $add->addresses[] = new Model_Address();
       $add->addresses->user_id = $add->user_id;
       $add->addresses->org_id = $add->id;
       $add->addresses->post_code = Input::post('post_code');
       $add->addresses->address_1 = Input::post('address_1');
       $add->addresses->address_2 = Input::post('address_2');
       $add->addresses->town = Input::post('town');
       $add->addresses->county = Input::post('county');
       $add->addresses->email = Input::post('email');
       $add->addresses->phone = Input::post('phone');
       $add->addresses->mobile = Input::post('mobile');
       $add->addresses->website_uri = Input::post('website_uri');
       $add->addresses->facebook_uri = Input::post('facebook_uri');
       $add->addresses->twitter_uri = Input::post('twitter_uri');
       $add->address_id = $add->addresses->id;
       $add->description = Input::post('description');
       $add->save();
    

    Here is my Organisation_Model:
    protected static $_properties = array(
      'id',
      'user_id',
      'type',
      'name',
      'slug',
      'address_id',
      'description',
     );
     
     // Set relationships
     protected static $_belongs_to = array(
         'user' => array(
       'key_from' => 'user_id',
       'model_to' => 'Model_User',
       'key_to' => 'id',
       'cascade_save' => true,
       'cascade_delete' => false,
         )
     );
     
     protected static $_has_one = array(
         'address' => array(
       'key_from' => 'address_id',
       'model_to' => 'Model_Address',
       'key_to' => 'id',
       'cascade_save' => true,
       'cascade_delete' => false,
         )
     );
     
     protected static $_has_many = array(
         'event' => array(
       'key_from' => 'id',
       'model_to' => 'Model_Event',
       'key_to' => 'org_id',
       'cascade_save' => true,
       'cascade_delete' => false,
         ),
      'addresses' => array(
       'key_from' => 'id',
       'model_to' => 'Model_Address',
       'key_to' => 'org_id',
       'cascade_save' => true,
       'cascade_delete' => false,
         ),
     );
    

    Here is my Address_Model:
    protected static $_properties = array(
      'id',
      'user_id',
      'org_id',
      'post_code',
      'address_1',
      'address_2',
      'town',
      'county',
      'email',
      'phone',
      'mobile',
      'website_uri',
      'facebook_uri',
      'twitter_uri',
     );
     
     // Set any relationships
     protected static $_belongs_to = array(
         'users' => array(
       'key_from' => 'user_id',
       'model_to' => 'Model_User',
       'key_to' => 'id',
       'cascade_save' => true,
       'cascade_delete' => false,
         ),
      'organisations' => array(
       'key_from' => 'org_id',
       'model_to' => 'Model_Organisation',
       'key_to' => 'id',
       'cascade_save' => true,
       'cascade_delete' => false,
         ),
      'organisation' => array(
       'key_from' => 'id',
       'model_to' => 'Model_Organisation',
       'key_to' => 'address_id',
       'cascade_save' => true,
       'cascade_delete' => false,
         ),
      'event' => array(
       'key_from' => 'id',
       'model_to' => 'Model_Event',
       'key_to' => 'address_id',
       'cascade_save' => true,
       'cascade_delete' => false,
         )
     );
    

    What I basically want to do when creating an organisation for the first time is to store the address ID of the (only) address in the organisation table and in the address table store the user ID and organisation ID of the address owner. Even if I had a separate table with user ID, org ID and address ID I would still have this problem if using one save method because at some point there will be an unknown org or address ID. Is this bad data structure design or is there a way to achieve it using one save so I can rollback/cascade if necessary? If the former, how should I go about it? Help is greatly appreciated as I've bee kicking around with this for ages now.
  • Sorry about replying to my own post. I thought it might be prudent to leave the above in case someone else has similar issues to me and it could be a useful learning point. What I was actually trying to achieve (as it transpires) is a many_many relationship. I discovered this by removing the address_id from the organisation model and having an is_default column in the address model. So I have created the pre-requisite table for a many/many relationship but can't get it to read the address details out of the db or insert them into it (it's running a blank query). Any suggestions?
    $val = Model_Organisation::validate('organisation');
       
       if ($val->run())
       {
        // validation successful, try and save the details
        $org = new Model_Organisation();
        $org->user_id = self::$user_id;
        $org->type = 'O'; // Organisation, churches added elsewhere
        $org->name = Input::post('name');
        $org->description = Input::post('description');
        $org->address[] = new Model_Address();
        $org->address->user_id = $org->user_id;    //->user_id = self::$user_id;
        $org->address->is_default = true;
        $org->address->post_code = Input::post('post_code');
        $org->address->address_1 = Input::post('address_1');
        $org->address->address_2 = Input::post('address_2');
        $org->address->town = Input::post('town');
        $org->address->county = Input::post('county');
        $org->address->email = Input::post('email');
        $org->address->phone = Input::post('phone');
        $org->address->mobile = Input::post('mobile');
        $org->address->website_uri = Input::post('website_uri');
        $org->address->facebook_uri = Input::post('facebook_uri');
        $org->address->twitter_uri = Input::post('twitter_uri');
        
        if($org and $org->save())
        {
         // success!
         Session::set_flash('success', 'Organisation successfully added.');
         Response::redirect('user/account');
        }
        else
        {
         // oops, we couldn't save it
         Session::set_flash('error', 'Could not add organisation.');
        }
       }
    
    
    Org:
     protected static $_many_many = array(
      'address' => array(
       'key_from' => 'id',
       'key_through_from' => 'address_id',
       'table_through' => 'addresses_organisations',
       'key_through_to' => 'organisation_id',
       'model_to' => 'Model_Address',
       'key_to' => 'id',
       'cascade_save' => true,
       'cascade_delete' => false,
         )
     );
    
    Add:
     protected static $_many_many = array(
      'organisation' => array(
       'key_from' => 'id',
       'key_through_from' => 'organisation_id',
       'table_through' => 'addresses_organisations',
       'key_through_to' => 'address_id',
       'model_to' => 'Model_Organisation',
       'key_to' => 'id',
       'cascade_save' => true,
       'cascade_delete' => false,
         )
     );
    
    The Error when reading (this worked before the change to many/many):
    Notice!
    
    ErrorException [ Notice ]: Undefined index: town
    
    APPPATH/views/user/account/organisation.php @ line 8:
    
    7: <li><?php echo $org->name; ?></li>
    8: <li><?php echo $org->address['town']; ?></li>
    

    I have cascade delete turned off currently and it is creating the organisation in the DB and it knows to insert the address details (it's just trying to insert NULL values for everything). I can now insert to the DB:
    $org->address[0]->field_name = value
    
    Is there a better way to do this? Would I be better passing in the array as a property when I create the new address object? If I print_r() the object I am trying to read, I can see an empty array for address. Is this a problem with my relationship or with the query I am performing? As an aside, it seems to be ignoring my validation for address, do I have to call a separate validation instance on it?
  • Solved: I had the relationship key_from and key_to the wrong way around in both models so was getting the wrong data in my through_table, hence the empty array. GIGO! Also, as this result is limited to one address and the query returns an array with an unknown key number (based on the ID of the address) it is safe to do
    $address = current($org->address);
    

    It gets the job done but I wonder if there is a better way to achieve it?
  • This obviously doesn't work:
    $org->address[] = new Model_Address();
    $org->address->user_id = $org->user_id;
    
    In a many-to many, the relation is an array of objects, so the first line is correct (you create a new array element). But in the second line you access the array as an object? Better do
    $org->address[] = new Model_Address(
        array('user_id' => $org->user_id)
    );
    
    to create a new object.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion