Question

I think I'm missing something because this is so obvious that I can't imagine it really works this way:

class ApiUser extends CActiveRecord {HAS_MANY ApiLog}

class ApiLog extends CActiveRecord {BELONGS_TO ApiUser}

now I want to save a new ApiLog record:

class ApiLog:
/**
 * Logs a call to the API
 * 
 * @param type $apiUser 
 * @param type $apiCall 
 * @param type $executionTime
 * @param type $resultCount
 * @param type $message
 */
public static function Log($apiUser, $apiCall, $executionTime = null, $resultCount = null, $message = '') {
    $log = new ApiLog();
    $log->apiUser = $apiUser;
    $log->apiCall = $apiCall;
    $log->clientIp = $_SERVER['REMOTE_ADDR'];
    $log->executiontime = $executionTime;
    $log->resultCount = $resultCount;
    $log->logText = $message;
    $log->save(false);
}

But an exception occurs on this line : $log->save(false);

CDbCommand failed to execute the SQL statement: SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails

Expected behaviour: $log->apiUser = $apiUser; sets the $log->apiuser_id property. If I do this by hand ($log->apiuser_id = $apiUser->id) no problem and it saves the object accordingly.

crazy thing is, I'm looking at the following code:

class CActiveRecord
/**
 * PHP setter magic method.
 * This method is overridden so that AR attributes can be accessed like properties.
 * @param string $name property name
 * @param mixed $value property value
 */
public function __set($name,$value)
{
    if($this->setAttribute($name,$value)===false)
    {
        if(isset($this->getMetaData()->relations[$name]))
            $this->_related[$name]=$value;
        else
            parent::__set($name,$value);
    }
}

Why does it store the reference to the related object, but doesn't update the foreign key property accordingly? Neither does the sql commandbuilder that builds the insertquery recognize the related object / foreign key thingy >

CActiveRecord
// ... //
public function insert($attributes=null) {
// ... //
    $builder=$this->getCommandBuilder();
    $table=$this->getMetaData()->tableSchema;
    $command=$builder->createInsertCommand($table,$this->getAttributes($attributes));
    if($command->execute()) {

it just passed the attributes array which does not include the set related object, just the record properties (which does includes the $apiuser_id) but doesnt retrieve the foreign id from the related object.

my question: what am I missing here...

Was it helpful?

Solution

Not missing anything. That is the way it works. You have to set the attributes directly rather than implicitly through the relation.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top