0
votes

I have two tables. A users table and a profile table. The profile table has a foreign key of users_id. The models for the tables are set up with one to one relationships. When I try and save some data I get this error:

Fatal error: Uncaught exception 'Doctrine_Connection_Mysql_Exception' with message 'SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'users_id' cannot be null' in

If I just save data to the users table then I know that it is auto_incrementing and generating a new id value. However, for some reason when I try and link the tables together or call $users->id then it returns a value of NULL.

Here is my code:

$u = new Users();
// Users table.
        $u->username   = $username;
        $u->password   = $password;
        $u->email      = $email;
        $u->groups_id   = $group_id;
        $u->ip_address = $ip_address;
        $u->last_login = now();
        $u->active     = 1;

    if ($this->store_salt)
    {
        $u->salt = $salt;
    }
    $u->save();

    // Profile table.
    $p = new Profile(); 
    $p->first = $additional_data['first'];
    $p->last = $additional_data['last'];
    $p->role = $additional_data['role'];
    $p->Users = $u;
    $p->save(); return;

Here are the models:

 /**
 * BaseUsers
 * 
 * This class has been auto-generated by the Doctrine ORM Framework
    • @property integer $id
    • @property string $username
    • @property string $password
    • @property string $ip_address
    • @property date $created_at
    • @property date $updated_at
    • @property string $salt
    • @property string $email
    • @property string $activation_code
    • @property string $forgotten_password_code
    • @property string $remember_code
    • @property integer $last_login
    • @property integer $active
    • @property integer $groups_id
    • @property Groups $Groups
      • @package ##PACKAGE##
    • @subpackage ##SUBPACKAGE##
    • @author ##NAME## <##EMAIL##>
    • @version SVN: $Id: Builder.php 6401 2009-09-24 16:12:04Z guilhermeblanco $ */
 abstract class BaseUsers extends Doctrine_Record
 {
     public function setTableDefinition()
     {
    $this->actAs("Timestampable");
    $this->setTableName('users');
    $this->hasColumn('id', 'integer', 4, array(
         'type' => 'integer',
         'length' => 4,
         'unsigned' => 0,
         'primary' => true,
         'autoincrement' => true,
         ));
    $this->hasColumn('username', 'string', 45, array(
         'type' => 'string',
         'length' => 45,
         'fixed' => false,
         'primary' => false,
         'notnull' => false,
         'autoincrement' => false,
         ));
    $this->hasColumn('password', 'string', 45, array(
         'type' => 'string',
         'length' => 45,
         'fixed' => false,
         'primary' => false,
         'notnull' => false,
         'autoincrement' => false,
         ));
    $this->hasColumn('ip_address', 'string', 16, array(
         'type' => 'string',
         'length' => 16,
         'fixed' => true,
         'primary' => false,
         'notnull' => false,
         'autoincrement' => false,
         ));
    $this->hasColumn('created_at', 'date', null, array(
         'type' => 'date',
         'primary' => false,
         'notnull' => true,
         'autoincrement' => false,
         ));
    $this->hasColumn('updated_at', 'date', null, array(
         'type' => 'date',
         'primary' => false,
         'notnull' => true,
         'autoincrement' => false,
         ));
    $this->hasColumn('salt', 'string', 40, array(
         'type' => 'string',
         'length' => 40,
         'fixed' => false,
         'primary' => false,
         'notnull' => false,
         'autoincrement' => false,
         ));
    $this->hasColumn('email', 'string', 40, array(
         'type' => 'string',
         'length' => 40,
         'fixed' => false,
         'primary' => false,
         'notnull' => false,
         'autoincrement' => false,
         ));
    $this->hasColumn('activation_code', 'string', 40, array(
         'type' => 'string',
         'length' => 40,
         'fixed' => false,
         'primary' => false,
         'notnull' => false,
         'autoincrement' => false,
         ));
    $this->hasColumn('forgotten_password_code', 'string', 40, array(
         'type' => 'string',
         'length' => 40,
         'fixed' => false,
         'primary' => false,
         'notnull' => false,
         'autoincrement' => false,
         ));
    $this->hasColumn('remember_code', 'string', 40, array(
         'type' => 'string',
         'length' => 40,
         'fixed' => false,
         'primary' => false,
         'notnull' => false,
         'autoincrement' => false,
         ));
    $this->hasColumn('last_login', 'integer', 4, array(
         'type' => 'integer',
         'length' => 4,
         'unsigned' => 1,
         'primary' => false,
         'notnull' => false,
         'autoincrement' => false,
         ));
    $this->hasColumn('active', 'integer', 1, array(
         'type' => 'integer',
         'length' => 1,
         'unsigned' => 1,
         'primary' => false,
         'notnull' => false,
         'autoincrement' => false,
         ));
    $this->hasColumn('groups_id', 'integer', 4, array(
         'type' => 'integer',
         'length' => 4,
         'unsigned' => 1,
         'primary' => true,
         'autoincrement' => false,
         ));
}

public function setUp()
{
    parent::setUp();
$this->hasOne('Groups', array(
         'local' => 'groups_id',
         'foreign' => 'id'));
$this->hasOne('Profile', array(
        'local' => 'id',
        'foreign' => 'users_id'));
}
 }

 <?php

/** * BaseProfile * * This class has been auto-generated by the Doctrine ORM Framework * * @property integer $id * @property string $role * @property string $first * @property string $last * @property string $email * @property string $phone_1 * @property string $phone_2 * @property string $address * @property string $postcode * @property date $created_at * @property date $updated_at * @property Doctrine_Collection $Member * @property Doctrine_Collection $Post * @property Doctrine_Collection $ThreadHasProfile * @property Doctrine_Collection $UserSetting * * @package ##PACKAGE## * @subpackage ##SUBPACKAGE## * @author ##NAME## <##EMAIL##> * @version SVN: $Id: Builder.php 6401 2009-09-24 16:12:04Z guilhermeblanco $ */ abstract class BaseProfile extends Doctrine_Record { public function setTableDefinition() { $this->actAs("Timestampable"); $this->setTableName('profile'); $this->hasColumn('id', 'integer', 4, array( 'type' => 'integer', 'length' => 4, 'unsigned' => 0, 'primary' => true, 'autoincrement' => true, )); $this->hasColumn('users_id', 'integer', 4, array( 'type' => 'integer', 'length' => 4, 'unsigned' => 0, 'primary' => false, 'autoincrement' => false, )); $this->hasColumn('role', 'string', null, array( 'type' => 'string', 'fixed' => false, 'primary' => false, 'notnull' => true, 'autoincrement' => false, )); $this->hasColumn('first', 'string', 45, array( 'type' => 'string', 'length' => 45, 'fixed' => false, 'primary' => false, 'notnull' => true, 'autoincrement' => false, )); $this->hasColumn('last', 'string', 45, array( 'type' => 'string', 'length' => 45, 'fixed' => false, 'primary' => false, 'notnull' => true, 'autoincrement' => false, )); $this->hasColumn('phone_1', 'string', 45, array( 'type' => 'string', 'length' => 45, 'fixed' => false, 'primary' => false, 'notnull' => false, 'autoincrement' => false, )); $this->hasColumn('phone_2', 'string', 45, array( 'type' => 'string', 'length' => 45, 'fixed' => false, 'primary' => false, 'notnull' => false, 'autoincrement' => false, )); $this->hasColumn('address', 'string', 200, array( 'type' => 'string', 'length' => 200, 'fixed' => false, 'primary' => false, 'notnull' => false, 'autoincrement' => false, )); $this->hasColumn('postcode', 'string', 10, array( 'type' => 'string', 'length' => 10, 'fixed' => false, 'primary' => false, 'notnull' => false, 'autoincrement' => false, )); $this->hasColumn('created_at', 'date', null, array( 'type' => 'date', 'primary' => false, 'notnull' => true, 'autoincrement' => false, )); $this->hasColumn('updated_at', 'date', null, array( 'type' => 'date', 'primary' => false, 'notnull' => true, 'autoincrement' => false, )); }

public function setUp()
{
    parent::setUp();
$this->hasMany('Member', array(
         'local' => 'id',
         'foreign' => 'profile_id'));

    $this->hasMany('Post', array(
         'local' => 'id',
         'foreign' => 'profile_id'));

    $this->hasMany('ThreadHasProfile', array(
         'local' => 'id',
         'foreign' => 'profile_id'));

    $this->hasMany('UserSetting', array(
         'local' => 'id',
         'foreign' => 'profile_id'));

    $this->hasOne('Users', array(
        'local' => 'users_id',
        'foreign' => 'id'));
}

}

2
can you provide your doctrine models (either in PHP or YAML) to help in answering the questionSo Over It

2 Answers

1
votes

There are a number of ways to skin this cat. I have created a simplified example based loosely on what I can gather from your question.

Firstly, here is the YAML that I use to generate for my one-to-one model classes:

Identity:
  columns:
    username: string(50)
    password: string(50)
    email: string(50)

Profile:
  columns:
    identity_id: integer(10)
    firstname: string(50)
    lastname: string(50)
  relations:
    Identity:
      foreignType: one

Now in PHP I can create a new Identity (or User in your case) and add related Profile data by simply:

        $identity = new Identity();
        $identity->username = 'james';
        $identity->password = 'secret';
        $identity->email = '[email protected]';
        //now adding the related data
        $identity->Profile->firstname = 'james';
        $identity->Profile->lastname = 'bond';
        $identity->save();

Hopefully this example will help you a bit.

edit:

here are the generated classes from the YAML in case that also helps:

BaseIdentity.php

<?php
abstract class BaseIdentity extends Doctrine_Record
{
    public function setTableDefinition()
    {
        $this->setTableName('identity');
        $this->hasColumn('username', 'string', 50, array(
             'type' => 'string',
             'length' => '50',
             ));
        $this->hasColumn('password', 'string', 50, array(
             'type' => 'string',
             'length' => '50',
             ));
        $this->hasColumn('email', 'string', 50, array(
             'type' => 'string',
             'length' => '50',
             ));
    }

    public function setUp()
    {
        parent::setUp();
        $this->hasOne('Profile', array(
             'local' => 'id',
             'foreign' => 'identity_id'));
    }
}

BaseProfile.php

<?php

abstract class BaseProfile extends Doctrine_Record
{
    public function setTableDefinition()
    {
        $this->setTableName('profile');
        $this->hasColumn('identity_id', 'integer', 10, array(
             'type' => 'integer',
             'length' => '10',
             ));
        $this->hasColumn('firstname', 'string', 50, array(
             'type' => 'string',
             'length' => '50',
             ));
        $this->hasColumn('lastname', 'string', 50, array(
             'type' => 'string',
             'length' => '50',
             ));
    }

    public function setUp()
    {
        parent::setUp();
        $this->hasOne('Identity', array(
             'local' => 'identity_id',
             'foreign' => 'id'));
    }
}
0
votes

Before $p->save();, have $p->users_id = $u->id.

Also, why are you calling the table Users (plural)? That's just going to make code very confusing.

Also again, if you have separate tables to hold different info about the user (a User and a user's Profile) because you saw it in sfGuardPlugin, PLEASE DO NOT DO THIS! It is a ridiculous idea that will only make you regret it later. I don't know what the Symfony/Doctrine team were drinking when they thought of that idea...