Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

issue #1762 : Forge / Add Foreign Keys #2096

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
82 changes: 81 additions & 1 deletion system/database/DB_forge.php
Expand Up @@ -63,6 +63,13 @@ abstract class CI_DB_forge {
*/
public $primary_keys = array();

/**
* Foreign Keys data
*
* @var array
*/
public $foreign_keys = array();

/**
* Database character set
*
Expand Down Expand Up @@ -262,6 +269,35 @@ public function add_key($key = '', $primary = FALSE)

// --------------------------------------------------------------------

/**
* Add Foreign Key
*
* Accepts a string or an array. A string would be the foreign key SQL syntax.
* An array will have the following elements:
* field (string) - name of the field for the foreign key
* foreign_table (string) - name of the table being referenced
* foreign_field (string) - name of the field being referenced in the foreign table
* delete (string) - the reference option for delete [optional]
* update (string) - the reference option for update [optional]
* Only 1 Foreign Key can be added per method call
*
* @param string|array $key The foreign key being added
* @return CI_DB_forge
*/
public function add_foreign_key($key = '')
{
if (empty($key))
{
show_error('Key information is required for that operation.');
}

$this->foreign_keys[] = $key;

return $this;
}

// --------------------------------------------------------------------

/**
* Add Field
*
Expand Down Expand Up @@ -397,7 +433,8 @@ protected function _create_table($table, $if_not_exists)
}

$columns = implode(',', $columns)
.$this->_process_primary_keys($table);
.$this->_process_primary_keys($table)
.$this->_process_foreign_keys();

// Are indexes created from within the CREATE TABLE statement? (e.g. in MySQL)
if ($this->_create_table_keys === TRUE)
Expand Down Expand Up @@ -956,6 +993,49 @@ protected function _process_primary_keys($table)

// --------------------------------------------------------------------

/**
* Process Adding of Foreign Keys
* Called by _create_table()
*
* @return string SQL statement component
*/
protected function _process_foreign_keys()
{
$sql = '';

// If we have any foreign keys to process...
if (count($this->foreign_keys) > 0)
{
foreach ($this->foreign_keys as $foreign_key)
{
// If this is an array, construct the statement
if (is_array($foreign_key))
{
// Initialize default actions and use them if needed
// Then put array into variables for simplicity
$vars = extract(array_merge(array(
'delete' => 'NO ACTION', 'update' => 'NO ACTION'), $foreign_key));

// Construct the SQL to add the foreign constraint
$sql .= ", \n\tCONSTRAINT FOREIGN KEY (".$this->db->escape_identifiers($field).') '
.' REFERENCES '.$this->db->escape_identifiers($foreign_table
.'('.$this->db->escape_identifiers($foreign_field).')')
.' ON DELETE '.strtoupper($delete).' ON UPDATE '.strtoupper($update).' ';

}
// Otherwise add the string statement as-is
else
{
$sql .= ', '.$foreign_key.' ';
}
}
}

return $sql;
}

// --------------------------------------------------------------------

/**
* Process indexes
*
Expand Down
1 change: 1 addition & 0 deletions user_guide_src/source/changelog.rst
Expand Up @@ -121,6 +121,7 @@ Release Date: Not Released
- Added support for SQLite3 database driver.
- Added Interbase/Firebird database support via the *ibase* driver.
- Added ODBC support for ``create_database()``, ``drop_database()`` and ``drop_table()`` in :doc:`Database Forge <database/forge>`.
- Added capability to add foreign keys via ``add_foreign_key()`` method in :doc:`Database Forge <database/forge>`.
- :doc:`Query Builder <database/query_builder>` changes include:
- Renamed the Active Record class to Query Builder to remove confusion with the Active Record design pattern.
- Added the ability to insert objects with ``insert_batch()``.
Expand Down
32 changes: 32 additions & 0 deletions user_guide_src/source/database/forge.rst
Expand Up @@ -181,6 +181,38 @@ below is for MySQL.
// gives KEY `blog_name_blog_label` (`blog_name`, `blog_label`)


Adding Foreign Keys
===================

Foreign keys can be added using a call to $this->dbforge->add_foreign_key(). The
method expects an array with the following elements: Note that add_foreign_key()
must be followed by a call to create_table().

- field: the name of the field that the foreign key is being set on
- foreign_table: the table being referenced
- foreign_field: the field in the table being referenced
- delete: the reference option for delete actions [default: NO ACTION]
- update: the reference option for update actions [default: NO ACTION]

Optionally, a string can be passed to the method. The string should be the custom
SQL syntax you want to use to create the foreign key constraint. This is provided
to easily allow for more complex foreign key requirements

The method can only create one foreign key per method call. If you need multiple
foreign keys, either pass a custom string or use multiple calls to the method.
Sample output is shown below.

::
$this->dbforge->add_foreign_key(
array('field' => 'myField',
'foreign_table' => 'testTable',
'foreign_field' => 'testField',
'delete' => 'cascade',
'update' => 'cascade');
//gives CONSTRAINT FOREIGN KEY `fk_testTable_testField` (`myField`)
// REFERENCES testTable(`testField`) ON DELETE CASCADE ON UPDATE CASCADE


Creating a table
================

Expand Down