Skip to main content

Using composite key in Laravel

In this blog will be show you how to enable Laravel to support composite primary key (multiple column key). First of all you need to create class that override method save of class Model to support composite key. Below is the code. You can copy to your project.


  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use DB;

class BaseModel extends Model
{

    public function save(array $options = []) {
        if( ! is_array($this->getKeyName()))
        {
            return parent::save($options);
        }

        // Fire Event for others to hook
        if($this->fireModelEvent('saving') === false) return false;

        // Prepare query for inserting or updating
        $query = $this->newQueryWithoutScopes();

        // Perform Update
        if ($this->exists)
        {
            if (count($this->getDirty()) > 0)
            {
                // Fire Event for others to hook
                if ($this->fireModelEvent('updating') === false)
                {
                    return false;
                }

                // Touch the timestamps
                if ($this->timestamps)
                {
                    $this->updateTimestamps();
                }

                //
                // START FIX
                //


                // Convert primary key into an array if it's a single value
                $primary = (count($this->getKeyName()) > 1) ? $this->getKeyName() : [$this->getKeyName()];

                // Fetch the primary key(s) values before any changes
                $unique = array_intersect_key($this->original, array_flip($primary));

                // Fetch the primary key(s) values after any changes
                $unique = !empty($unique) ? $unique : array_intersect_key($this->getAttributes(), array_flip($primary));

                // Fetch the element of the array if the array contains only a single element
                //$unique = (count($unique) <> 1) ? $unique : reset($unique);

                // Apply SQL logic
                $query->where($unique);

                //
                // END FIX
                //

                // Update the records
                $query->update($this->getDirty());

                // Fire an event for hooking into
                $this->fireModelEvent('updated', false);
            }
        }
        // Insert
        else
        {
            // Fire an event for hooking into
            if ($this->fireModelEvent('creating') === false) return false;

            // Touch the timestamps
            if($this->timestamps)
            {
                $this->updateTimestamps();
            }

            // Retrieve the attributes
            $attributes = $this->attributes;

            if ($this->incrementing && !is_array($this->getKeyName()))
            {
                $this->insertAndSetId($query, $attributes);
            }
            else
            {
                $query->insert($attributes);
            }

            // Set exists to true in case someone tries to update it during an event
            $this->exists = true;

            // Fire an event for hooking into
            $this->fireModelEvent('created', false);
        }

        // Fires an event
        $this->fireModelEvent('saved', false);

        // Sync
        $this->original = $this->attributes;

        // Touches all relations
        if (array_get($options, 'touch', true)) $this->touchOwners();

        return true;
    }    
}

Then you must extends your model class as example below. You can define $primaryKey to multiple column fields (see line 13).


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use App\Models\BaseModel;

class MyTable extends BaseModel
{

    protected $table = 'MyTable';
    protected $primaryKey = ['MY_KEY_COLUMN_1', 'MY_KEY_COLUMN_2', 'MY_KEY_COLUMN_3'];
    
    public $incrementing = false;
    public $timestamps = false;

}


Example:


1
2
3
4
5
6
7
$myTable = new MyTable;
$myTable->FIELD1 = 'Feild1_Value';
$myTable->FIELD2 = 'Field2_Value';
$myTable->MY_KEY_COLUMN1 = 'Key1_Value';
$myTable->MY_KEY_COLUMN2 = 'Key2_Value';
$myTable->MY_KEY_COLUMN3 = 'Key3_Value';
$myTable->save();

Credits

-Method Save in BaseModel is from post of mr. tsilenzio in website https://github.com/laravel/framework/issues/5517


Comments

Popular posts from this blog

Serialize and Deserialize JSON data with C#

This post is about example for serialize and deserialize json data with C#. This example using Newtonsoft.Json to be a library to work with json data. You can add Newtonsoft.Json by download from  https://www.newtonsoft.com/json  or using Nuget to add it into your project. In this example is Bill object that hold billing data about Car object. Serialize Object to String Below is example code to serialize object to json string. At line 39 is code to convert object into json string with beautiful json format. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; namespace JSON { class JSonExample { static void Main( string [] args) { List<Car> cars = new List<Car>(); float to...

CURL SSL error in WAMP

I facing problem about certificate error when I using curl to request HTTPS domain. I find cause of problem is there is no certificate configuration in PHP. Below is how to solve my problem. Here is sample of error: * About to connect() to notify-api.line.me port 443 (#0) * Trying {IP Address}... * connected * Connected to notify-api.line.me ({IP Address}) port 443 (#0) * SSL certificate problem, verify that the CA cert is OK. Details: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed * Closing connection #0 Step to solve this problem Download  Certificate Bundle Extract and put PEM file to your web server folder or other folder. Enable mod_ssl in Apache and php_openssl.dll in php.ini Add configuration into php.ini curl.cainfo="C:/wamp/cacert.pem" openssl.cafile="C:/wamp/cacert.pem" Restart Apache Service