Answers.Body: <p>This should be fixed in the next (<a href="https://craftcms.com/changelog#build2791" rel="nofollow">post 2.6.2791</a>) release so that plugins can define composite primary keys in their records.</p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-06-21T07:57:57.837Z
Answers.Text: You boys don't mess around do you! Thanks for the quick turnaround on this, it's much appreciated.
Answers.UserDisplayName: Steve Holland
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-06-21T03:50:46.277Z
Answers.LastActivityDate: 2016-06-21T03:50:46.277Z
Answers.UserDisplayName: Brad Bell
Answers.Body: <p>It would appear not unfortunately.</p>
  
  <p>Craft's <code>BaseRecord</code> (which a <code>Record</code> should inherit from) tries to uses the <code>primaryKey()</code> method call to help create the table, but assumes a single column name is returned, not an Array and so falls over on the <code>isset</code> call.</p>
  
  <pre><code>$pk = $this-&gt;primaryKey();
  
  if (isset($columns[$pk]))
  {
    $columns[$pk]['primaryKey'] = true;
    $addIdColumn = false;
  }
  else
  {
    $addIdColumn = true;
  }
  </code></pre>
  
  <p>I'm guessing it should work because the <code>CActiveRecord</code> (which the <code>BaseRecord</code> inherits from) states in it's comments for PrimaryKey:</p>
  
  <pre><code>@return mixed the primary key of the associated database table.
  
  If the key is a composite one consisting of several columns, it should
  return the array of the key column names.
  </code></pre>
  
  <p>EDIT: In the end I added the following to my Plugin file, and that seemed to do the trick:</p>
  
  <pre><code>public function onAfterInstall()
  {
    craft()-&gt;db-&gt;createCommand()-&gt;dropColumn('myplugin_merchant_order', 'id');
    craft()-&gt;db-&gt;createCommand()-&gt;addPrimaryKey('myplugin_merchant_order', ['merchant_id', 'order_id']);
  }
  </code></pre>
  
  <p>I also had to add this to my Record, to stop the validation failing because I'd removed the <code>id</code> column in the above step:</p>
  
  <pre><code>public function primaryKey()
  {
      return null;
  }
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-06-16T19:03:33.000Z
Answers.Text: Yeah, I'd consider that a bug since it works in Yii (see here http://www.yiiframework.com/doc/guide/1.1/en/database.ar#defining-ar-class).  Will look into fixing it.
Answers.UserDisplayName: Brad Bell
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-06-16T16:07:21.037Z
Answers.LastActivityDate: 2016-06-17T12:38:20.643Z
Answers.LastEditDate: 2016-06-17T12:38:20.643Z
Answers.UserDisplayName: Steve Holland
Body: <p>I've structured my Record as such:</p>
  
  <pre><code>&lt;?php
  namespace Craft;
  
  class MyPlugin_MerchantOrderRecord extends BaseRecord
  {
    public function getTableName()
    {
      return 'myplugin_merchant_orders';
    }
  
    protected function defineAttributes()
    {
      return [
        'merchant_id' =&gt; AttributeType::Number,
        'order_id' =&gt; AttributeType::Number,
        ...
      ];
    }
  
    public function primaryKey()
    {
      return ['merchant_id', 'order_id'];
    }
  
    public function defineRelations()
    {
        return [
          'merchant' =&gt; [static::BELONGS_TO, 'MyPlugin_MerchantRecord', 'merchant_id', 
                 'required' =&gt; true, 'onDelete' =&gt; static::CASCADE],
          'order' =&gt; [static::BELONGS_TO, 'Commerce_OrderRecord', 'order_id', 
                 'required' =&gt; true, 'onDelete' =&gt; static::CASCADE],
        ];
    }
  }
  </code></pre>
  
  <p>When I install the plugin I get the following error:</p>
  
  <p><code>Illegal offset type in isset or empty</code></p>
  
  <p>If I take away the <code>primaryKey()</code> definition, the table is created successfully and the <code>foreign keys</code> are in place as expected.</p>
  
  <p>Any help gratefully received.</p>
  
Tags: <plugin-development><database><records>
Title: Is it possible to create composite Primary Keys in Records?
ThreadText: # Is it possible to create composite Primary Keys in Records?
  
  (Asked by: username_0 on 2016-06-16)
  
  I've structured my Record as such:
  
  ```
  <?php
  namespace Craft;
  
  class MyPlugin_MerchantOrderRecord extends BaseRecord
  {
    public function getTableName()
    {
      return 'myplugin_merchant_orders';
    }
  
    protected function defineAttributes()
    {
      return [
        'merchant_id' => AttributeType::Number,
        'order_id' => AttributeType::Number,
        ...
      ];
    }
  
    public function primaryKey()
    {
      return ['merchant_id', 'order_id'];
    }
  
    public function defineRelations()
    {
        return [
          'merchant' => [static::BELONGS_TO, 'MyPlugin_MerchantRecord', 'merchant_id', 
                 'required' => true, 'onDelete' => static::CASCADE],
          'order' => [static::BELONGS_TO, 'Commerce_OrderRecord', 'order_id', 
                 'required' => true, 'onDelete' => static::CASCADE],
        ];
    }
  }
  
  ```
  
  When I install the plugin I get the following error:
  
  `Illegal offset type in isset or empty`
  
  If I take away the `primaryKey()` definition, the table is created successfully and the `foreign keys` are in place as expected.
  
  Any help gratefully received.
  
  **Tags:** plugin-development, database, records
  
  
  ---
  
  ## 2 answers
  
  ### Answer by username_1 on 2016-06-21. Score: 2 | Accepted answer
  
  This should be fixed in the next ([post 2.6.2791](https://craftcms.com/changelog#build2791)) release so that plugins can define composite primary keys in their records.
  
  > **Comments:**
  > **username_0**: You boys don't mess around do you! Thanks for the quick turnaround on this, it's much appreciated.  
  
  ---
  
  ### Answer by username_0 on 2016-06-16. Score: 2
  
  It would appear not unfortunately.
  
  Craft's `BaseRecord` (which a `Record` should inherit from) tries to uses the `primaryKey()` method call to help create the table, but assumes a single column name is returned, not an Array and so falls over on the `isset` call.
  
  ```
  $pk = $this->primaryKey();
  
  if (isset($columns[$pk]))
  {
    $columns[$pk]['primaryKey'] = true;
    $addIdColumn = false;
  }
  else
  {
    $addIdColumn = true;
  }
  
  ```
  
  I'm guessing it should work because the `CActiveRecord` (which the `BaseRecord` inherits from) states in it's comments for PrimaryKey:
  
  ```
  @return mixed the primary key of the associated database table.
  
  If the key is a composite one consisting of several columns, it should
  return the array of the key column names.
  
  ```
  
  EDIT: In the end I added the following to my Plugin file, and that seemed to do the trick:
  
  ```
  public function onAfterInstall()
  {
    craft()->db->createCommand()->dropColumn('myplugin_merchant_order', 'id');
    craft()->db->createCommand()->addPrimaryKey('myplugin_merchant_order', ['merchant_id', 'order_id']);
  }
  
  ```
  
  I also had to add this to my Record, to stop the validation failing because I'd removed the `id` column in the above step:
  
  ```
  public function primaryKey()
  {
      return null;
  }
  
  ```
  
  > **Comments:**
  > **username_1**: Yeah, I'd consider that a bug since it works in Yii (see here http://www.yiiframework.com/doc/guide/1.1/en/database.ar#defining-ar-class).  Will look into fixing it.  
  
  ---
  
  