1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Duplicate entry - _getUpdateCondition not working

Discussion in 'XenForo Development Discussions' started by chrisj, Jul 8, 2012.

  1. chrisj

    chrisj Active Member

    I set up a cron go through the users and create a psn record for each user. It creates the record correctly but when I run the command again, instead of trying to update the record, gets a duplicate entry error. I was following Fuhrmann's read and write to database and cron tutorials.

    Error
    Code:
    Mysqli statement execute error : Duplicate entry '1' for key 'PRIMARY'
     
    Zend_Db_Statement_Mysqli->_execute() in Zend/Db/Statement.php at line 317
    Zend_Db_Statement->execute() in Zend/Db/Adapter/Abstract.php at line 479
    Zend_Db_Adapter_Abstract->query() in Zend/Db/Adapter/Abstract.php at line 574
    Zend_Db_Adapter_Abstract->insert() in XenForo/DataWriter.php at line 1591
    XenForo_DataWriter->_insert() in XenForo/DataWriter.php at line 1580
    XenForo_DataWriter->_save() in XenForo/DataWriter.php at line 1381
    XenForo_DataWriter->save() in PsnLeaderboards/CronEntry.php at line 109
    PsnLeaderboards_CronEntry::getPsnUsers()
    call_user_func() in XenForo/Model/Cron.php at line 356
    XenForo_Model_Cron->runEntry() in XenForo/ControllerAdmin/Cron.php at line 204
    XenForo_ControllerAdmin_Cron->actionRun() in XenForo/FrontController.php at line 310
    XenForo_FrontController->dispatch() in XenForo/FrontController.php at line 132
    XenForo_FrontController->run() in /Users/chris/Development/xf_dev/admin.php at line 13
    DataWriter
    PHP:
    <?php
    class PsnLeaderboards_DataWriter_PsnUser extends XenForo_DataWriter
    {
     
    /**
    * Gets the fields that are defined for the table. See parent for explanation.
    *
    * @return array
    */
    protected function _getFields() {
       return array(
           
    'psn_user' => array(
               
    'xf_user_id'=> array(
                   
    'type'=> self::TYPE_UINT,
    'required'=> true
               
    ),
               
    'username'=> array(
                   
    'type'=> self::TYPE_STRING,
    'required'=> true
               
    ),
               
    'country'=> array(
                   
    'type'=> self::TYPE_STRING,
                   
    'required'=> true
               
    ),
    'avatar'=> array(
                   
    'type'=> self::TYPE_STRING,
                   
    'required'=> true
               
    ),
    'color'=> array(
                   
    'type'=> self::TYPE_STRING,
                   
    'required'=> true
               
    ),
    'psnplus'=> array(
                   
    'type'=> self::TYPE_STRING,
                   
    'required'=> true
               
    ),
    'points'=> array(
                   
    'type'=> self::TYPE_UINT,
                   
    'required'=> true
               
    ),
    'platinum'=> array(
                   
    'type'=> self::TYPE_UINT,
                   
    'required'=> true
               
    ),
    'gold'=> array(
                   
    'type'=> self::TYPE_UINT,
                   
    'required'=> true
               
    ),
    'silver'=> array(
                   
    'type'=> self::TYPE_UINT,
                   
    'required'=> true
               
    ),
    'bronze'=> array(
                   
    'type'=> self::TYPE_UINT,
                   
    'required'=> true
               
    ),
           )
       );
    }
     
    /**
    * Gets the actual existing data out of data that was passed in. See parent for explanation.
    *
    * @param mixed
    *
    * @see XenForo_DataWriter::_getExistingData()
    *
    * @return array|false
    */
    protected function _getExistingData($data)
    {
       if (!
    $id $this->_getExistingPrimaryKey($data'xf_user_id'))
       {
           return 
    false;
       }
     
       return array(
    'psn_user' => $this->_getPsnUserModel()->getPsnUserById($id));
    }
     
    /**
    * Gets SQL condition to update the existing record.

    * @see XenForo_DataWriter::_getUpdateCondition() 
    *
    * @return string
    */
    protected function _getUpdateCondition($tableName)
    {
       return 
    'xf_user_id = ' $this->_db->quote($this->getExisting('xf_user_id'));
    }
     
    /**
    * Get the psn user model.
    *
    * @return PsnLeaderboards_Model_PsnUser
    */
    protected function _getPsnUserModel()
    {
       return 
    $this->getModelFromCache 'PsnLeaderboards_Model_PsnUser' );
    }
    }
    ?>
    Model
    PHP:
    <?php
    class PsnLeaderboards_Model_PsnUser extends Xenforo_Model
    {
    /**
    * Get only one row using the data passed. 
    */
    public function getPsnUserById($id)
    {
       return 
    $this->_getDb()->fetchRow('
           SELECT * FROM psn_user WHERE xf_user_id = ?'
    $id);
    }
     
    /**
    * Get all the rows of our table.
    *
    */
    public function getAllPsnUser()
    {
       return 
    $this->fetchAllKeyed('SELECT * FROM psn_user ORDER BY points DESC''xf_user_id');
    }
    }
    ?>
     
  2. Jake Bunce

    Jake Bunce XenForo Moderator Staff Member

    If you want to update an existing record using your datawriter then you need to use setExistingData(). Here is a function from the model in one of my addons that writes out a node record:

    Code:
    	public function saveOptions(array $node)
    	{
    		if (!$node['node_id'])
    		{
    			return;
    		}
    
    		$dw = XenForo_DataWriter::create('NodesAsTabs_DataWriter_Options');
    
    		$existing = $this->getOptionsById($node['node_id']);
    		if (!empty($existing['node_id']))
    		{
    			$dw->setExistingData($existing['node_id']);
    		}
    
    		$dw->bulkSet($node);
    
    		$dw->save();
    	}
    
    It starts by trying to select an existing record by node_id. If it exists then it calls setExistingData() before saving.
     
    Pereira and chrisj like this.

Share This Page