CI ORM (Object Relational Mapper) 对象关系映射 [PHP5]
作者:沧蓝
[1.5.4] ORM (Object Relational Mapper) 对象关系映射 [PHP5]
注意事项
- 本程序仅支持PHP5。
- 本程序是07年9月份的时候写的,之后一直没再碰过。
- 本程序未开发完成!目前仅能检索数据。
- 发布本程序一是希望抛砖引玉,二是因为这个程序可能不再继续开发了,我可能会转为开发Kohana的版本。
- 程序没有优化过,所以如果看到很小白的地方请见谅啊。
什么是ORM?
对象关系映射(Object Relational Mapping,简称ORM)是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将java程序中的对象自动持久化到关系数据库中。本质上就是将数据从一种形式转换到另外一种形式。 这也同时暗示者额外的执行开销;然而,如果ORM作为一种中间件实现,则会有很多机会做优化,而这些在手写的持久层并不存在。更重要的是用于控制转换的元数据需要提供和管理;但是同样,这些花费要比维护手写的方案要少;而且就算是遵守ODMG规范的对象数据库依然需要类级别的元数据。
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
/**
* Object Relational Mapper
* Maps database tables with associations to programming objects
*
* Database requirement (optional but recommended, for schema caching):
*
* CREATE TABLE orm_schema (
* id INT NOT NULL AUTO_INCREMENT,
* table_name VARCHAR(30) NULL,
* table_schema TEXT NULL,
* PRIMARY KEY(id)
* )
*
* Please don't forget to set $cache to TRUE in the code
*
* @package CodeIgniter
* @subpackage library
* @author Fred Wu
* @version 0.1.0
* @license GNU Lesser General Public License (LGPL) [url]http://www.gnu.org/licenses/lgpl.html[/url]
**/
class ORM {
/**
* CI database object
*
* @access protected
* @var object
**/
protected $db;
/**
* Table name
*
* @access public
* @var string
**/
public $table;
/**
* Schema cache
* uses database to cache the table schema
*
* @access protected
* @var bool
**/
protected $cache = FALSE; // <-- set to TRUE to enable caching, FALSE to disable it
protected $tableMeta;
/**
* Constructor
*
* @access public
* @param string $table table name
**/
public function __construct($table = NULL)
{
if ($table == NULL)
{
$msg = 'ORM initilization failed, no table specified';
log_message('error', $msg);
show_error($msg);
}
else
{
// calls CodeIgniter's database functions
$this->db =& get_instance()->db;
$this->table = $table;
// loading complete
log_message('debug', 'ORM Initialized for '.ucfirst($table).' table.');
}
}
/**
* Table Metadata
* constructs table metadata
*
* @access private
* @param bool $initialCall initial call to the function (default is true)
* @return array table metadata
**/
private function _tableMeta($initialCall = TRUE)
{
$table = $this->table;
if ($initialCall == TRUE && $this->cache == TRUE)
{
$query_schema = $this->db->query('SELECT * FROM orm_schema WHERE table_name = "'.$table.'"');
$result_schema = $query_schema->result_array();
}
if (isset($result_schema[0]) && $this->cache == TRUE)
{
$metadata = unserialize($result_schema[0]['table_schema']);
}
else
{
// SHOW CREATE TABLE query
$query_showTable = $this->db->query('SHOW CREATE TABLE '.$table);
$result_showTable = $query_showTable->result_array();
$showTable = $result_showTable[0]['Create Table'];
/*echo '<pre>';
print_r($showTable);
echo '</pre>';*/
/********************
Primary Keys
********************/
// reads the primary key definition line
preg_match('/PRIMARY KEY +(`.*`)/i', $showTable, $match_PKs);
$str_PK = $match_PKs[0];
// cleans up the PK string so that we can split it into a list of primary keys
preg_match('/.*(`(.*)`)/', $str_PK, $str_PKClean);
$PKs = preg_split('/`,`/', $str_PKClean[1]);
// reorganises the primary keys
foreach ($PKs as $PK)
{
// does the primary key auto_increment? (regex in caseless and multiline mode)
if (preg_match('/'.$PK.'.*auto_increment,$/im', $showTable))
{
$metadata['PKs'][$PK] = 'AUTO_INCREMENT';
}
else
{
$metadata['PKs'][$PK] = NULL;
}
}
/********************
Foreign Keys
********************/
// reads the foreign key definition lines
preg_match_all('/CONSTRAINT.*FOREIGN KEY +(`(.*)`) +REFERENCES +`(.*)` +(`(.*)`).*/i',
$showTable, $match_FKs, PREG_SET_ORDER);
// reorganises the foreign keys
$i = 0;
foreach ($match_FKs as $FK)
{
$FK_id = $FK[1];
// the foreign key
$metadata['FKs'][$i]['FK'] = $FK_id;
// reference table of the foreign key
$metadata['FKs'][$i]['ref'] = $FK[2];
// primary key of the referenced table
$metadata['FKs'][$i]['refPK'] = $FK[3];
// reference tables (for the conjunction table)
foreach($PKs as $PK)
{
if ($FK_id == $PK)
{
// is a conjunction table: a list of the referenced tables
$metadata['isConjunction'][] = $metadata['FKs'][$i]['ref'];
}
}
// belongsTo tables
if (!isset($metadata['isConjunction']))
{
$belongsTo_table = $metadata['FKs'][$i]['ref'];
$metadata['belongsTo'][$belongsTo_table]['FK'] = $FK_id;
$metadata['belongsTo'][$belongsTo_table]['refPK'] = $metadata['FKs'][$i]['refPK'];
}
$i++;
}
/********************
Primary Key Attributes
********************/
// shows attributes only if they're non-foreign keys and non-AUTO_INCREMENT
foreach ($PKs as $PK)
{
$fields = $this->db->field_data($table);
if (!isset($metadata['isConjunction']) && $metadata['PKs'][$PK] != 'AUTO_INCREMENT')
{
foreach ($fields as $field)
{
if ($PK == $field->name)
{
$metadata['PKs'][$PK][] = $this->_fieldType($table, $PK, 'type');
$metadata['PKs'][$PK][] = $this->_fieldType($table, $PK, 'max_length');
}
}
}
}
/********************
Fields
********************/
if ($initialCall == TRUE && !isset($metadata['isConjunction']))
{
$fields = $this->db->field_data($table);
foreach ($fields as $field)
{
// lists only non-key fields
if (array_key_exists($field->name, $metadata['PKs']) OR
isset($metadata['FKs']) && array_key_exists($field->name, $metadata['FKs']))
{
}
else
{
$metadata['fields'][$field->name][] = $this->_fieldType($field->name, 'type');
$metadata['fields'][$field->name][] = $this->_fieldType($field->name, 'max_length');
}
}
}
/********************
Associations
********************/
// only run this once
if ($initialCall == TRUE && !isset($metadata['isConjunction']))
{
// a list of all tables
$tables_rebuild = $this->db->list_tables();
// rebuilds each individual table
foreach ($tables_rebuild as $table_rebuild)
{
// prepares to rebuild the data
$this->table = $table_rebuild;
$metadata_rebuild[$table_rebuild] = $this->_tableMeta($initialCall = FALSE);
$this->table = $table;
$initialCall = TRUE;
}
// goes through each tables
foreach ($metadata_rebuild as $table_rebuild_name => $table_rebuild_data)
{
// hasOneMany
if (isset($table_rebuild_data['belongsTo']))
{
// goes through each 'belongsTo' relationships
foreach ($table_rebuild_data['belongsTo'] as $table_associated => $table_associated_PK)
{
if ($table == $table_associated)
{
foreach ($table_rebuild_data['FKs'] as $table_rebuild_FK)
{
if ($table_rebuild_FK['ref'] == $table_associated)
{
$refPK = array_keys($table_rebuild_data['PKs']);
$metadata['HOM'][$table_rebuild_name]['refFK'] = $table_rebuild_FK['FK'];
$metadata['HOM'][$table_rebuild_name]['refPK'] = $refPK[0];
}
}
}
}
}
// hasAndBelongsToMany
if (isset($table_rebuild_data['isConjunction']))
{
if ($table == $table_rebuild_data['isConjunction'][0])
{
$table_rebuild_data_HABTMTable = $table_rebuild_data['isConjunction'][1];
$table_remote_PK = $table_rebuild_data['FKs'][1]['refPK'];
}
elseif ($table == $table_rebuild_data['isConjunction'][1])
{
$table_rebuild_data_HABTMTable = $table_rebuild_data['isConjunction'][0];
$table_remote_PK = $table_rebuild_data['FKs'][0]['refPK'];
}
if (isset($table_rebuild_data_HABTMTable))
{
foreach ($table_rebuild_data['FKs'] as $table_rebuild_FK)
{
if ($table_rebuild_FK['ref'] == $table)
{
$metadata['HABTM'][$table_rebuild_data_HABTMTable]['conjTable'] = $table_rebuild_name;
$metadata['HABTM'][$table_rebuild_data_HABTMTable]['PK'] = $PK;
$metadata['HABTM'][$table_rebuild_data_HABTMTable]['refFK'] = $table_rebuild_FK['FK'];
$refPKs = array_keys($table_rebuild_data['PKs']);
foreach ($refPKs as $refPK)
{
if ($refPK != $table_rebuild_FK['FK'])
{
$metadata['HABTM'][$table_rebuild_data_HABTMTable]['refPK'] = $refPK;
}
}
$metadata['HABTM'][$table_rebuild_data_HABTMTable]['refPKPK'] = $table_remote_PK;
}
}
}
}
}
}
if ($initialCall == TRUE && $this->cache == TRUE)
{
// stores metadata to database
$this->db->query('INSERT INTO orm_schema (table_name, table_schema)
VALUES ("'.$table.'", "'.addslashes(serialize($metadata)).'");');
}
}
if ($initialCall == TRUE)
{
/*echo '<pre> <b>metadata for '.$table.'</b>
';
print_r($metadata);
echo '
';
echo '</pre>';*/
}
$this->tableMeta = $metadata;
return $metadata;
}
/**
* Field Type
* finds field type and max_length
* this function is needed because MySQL/CodeIgniter's inbuilt function does not work
*
* @access private
* @param string $field field name
* @param string $returnType 'type' or 'max_length', default returns the field type string
* @return string field type data
**/
private function _fieldType($field, $returnType = NULL)
{
$table = $this->table;
// SHOW COLUMNS query
$query_fieldsData = $this->db->query('SHOW COLUMNS FROM '.$table);
$result_fieldsData = $query_fieldsData->result_array();
foreach ($result_fieldsData as $fieldData)
{
if ($fieldData['Field'] == $field)
{
$fieldType['str'] = $fieldData['Type'];
}
}
// analyses the field type string
preg_match('/(D+)((d+)).*/', $fieldType['str'], $match_type);
// returns type
if ($returnType == 'type')
{
if (isset($match_type[1]))
{
return $fieldType['type'] = $match_type[1];
}
// for fields like 'text' where there is no brackets and max length
else
{
return $fieldType['str'];
}
}
// returns max_length
elseif ($returnType == 'max_length')
{
if (isset($match_type[2]))
{
return $fieldType['max_length'] = $match_type[2];
}
}
// returns the string
else
{
return $fieldType['str'];
}
}
/**
* Find
* finds table data with an optional WHERE query and associated data
*
* @access public
* @param string or array $withAssoc associated tables in an array or 'ALL' for all associated tables
* @param string $query_where optional WHERE query
* @return array table data (objects) in an array
**/
public function find($withAssoc = NULL, $query_where = NULL)
{
$table = $this->table;
// initial table data with no associated data
if (isset($query_where) && preg_match('/= +w/i', $query_where))
{
$query_tableData = $this->db->query("SELECT * FROM $table WHERE $query_where");
}
// ignores the query if the passed value is NULL or is empty
elseif (isset($query_where) AND !preg_match('/= +w/i', $query_where) || stristr($query_where, '= NULL'))
{
log_message('info', 'Query error detected and ignored in $this->orm->find() for table: '.$this->table);
return FALSE;
}
else
{
$query_tableData = $this->db->query('SELECT * FROM '.$table);
}
$result_tableData = $query_tableData->result();
if ($withAssoc != NULL)
{
// table metadata
$tableMeta = $this->_tableMeta($table);
// available associated tables
$assoc_belongsTo = (array)$tableMeta['belongsTo'];
$assoc_HOM = (array)$tableMeta['HOM'];
$assoc_HABTM = (array)$tableMeta['HABTM'];
$assoc_All = @array_merge($assoc_belongsTo, $assoc_HOM, $assoc_HABTM);
if ($withAssoc == 'ALL')
{
$withAssoc_new = $assoc_All;
}
// populates association schema
else
{
foreach ($withAssoc as $assocTable)
{
if (array_key_exists($assocTable, $assoc_All))
{
$withAssoc_new[$assocTable] = $assoc_All[$assocTable];
}
}
}
$withAssoc = $withAssoc_new;
// applies every associated table
foreach ($withAssoc as $assocTable => $assocSchema)
{
$i = 0;
// applies to every data record
foreach ($result_tableData as $dataRecord)
{
// belongsTo
if (array_key_exists($assocTable, $assoc_belongsTo) && $dataRecord->$assocSchema['FK'] != NULL)
{
$this->table = $assocTable;
$assocData = $this->find(NULL, $assocSchema['refPK'].' = '.$dataRecord->$assocSchema['FK']);
$this->table = $table;
$dataRecord->$assocTable = $assocData[0];
}
// hasOneMany
elseif (array_key_exists($assocTable, $assoc_HOM) && $dataRecord->$assocSchema['refPK'] != NULL)
{
$this->table = $assocTable;
$dataRecord->$assocTable = $this->find(NULL, $assocSchema['refFK'].' = '.$dataRecord->$assocSchema['refPK']);
$this->table = $table;
}
// hasAndBelongsToMany
elseif (array_key_exists($assocTable, $assoc_HABTM))
{
// fetches data from the conjunction table
$this->table = $assocSchema['conjTable'];
$conjData = $this->find(NULL, $assocSchema['refFK'].' = '.$dataRecord->$assocSchema['PK']);
// fetches data from the remotely linked table
if (!empty($conjData))
{
$this->table = $assocTable;
foreach ($conjData as $conjRecord)
{
$conjRecordNew = $this->find(NULL, $assocSchema['refPKPK'].' = '.$conjRecord->$assocSchema['refPK']);
$conjDataNew[$i][] = $conjRecordNew[0];
}
$dataRecord->$assocTable = $conjDataNew[$i];
$this->table = $table;
}
}
$result_tableData[$i] = $dataRecord;
$i++;
}
}
}
foreach ($result_tableData as $dataObj)
{
//$this->save() = $dataObj->save();
}
if (isset($withAssoc))
{
echo '<pre> <b>table data for '.$table.'</b>
';
print_r($result_tableData);
echo '
';
echo '</pre>';
}
$this->table = $table;
return $result_tableData;
}
public function add()
{
$table = $this->table;
$tableMeta = $this->_tableMeta($table);
$yo = $this->db->list_fields($table);
echo '<pre>';
print_r($tableMeta);
echo '</pre>';
}
public function save()
{
}
public function &__get($prop)
{
$prop = (string) $prop;
$fields = $this->tableMeta['fields'];
if (array_key_exists($fields, $prop))
{
echo 'yes';
}
else
{
echo 'no';
}
}
public function __set($prop, $value)
{
$prop = (string) $prop;
}
public function __call($method, $args)
{
}
}
?>
/**
* Object Relational Mapper
* Maps database tables with associations to programming objects
*
* Database requirement (optional but recommended, for schema caching):
*
* CREATE TABLE orm_schema (
* id INT NOT NULL AUTO_INCREMENT,
* table_name VARCHAR(30) NULL,
* table_schema TEXT NULL,
* PRIMARY KEY(id)
* )
*
* Please don't forget to set $cache to TRUE in the code
*
* @package CodeIgniter
* @subpackage library
* @author Fred Wu
* @version 0.1.0
* @license GNU Lesser General Public License (LGPL) [url]http://www.gnu.org/licenses/lgpl.html[/url]
**/
class ORM {
/**
* CI database object
*
* @access protected
* @var object
**/
protected $db;
/**
* Table name
*
* @access public
* @var string
**/
public $table;
/**
* Schema cache
* uses database to cache the table schema
*
* @access protected
* @var bool
**/
protected $cache = FALSE; // <-- set to TRUE to enable caching, FALSE to disable it
protected $tableMeta;
/**
* Constructor
*
* @access public
* @param string $table table name
**/
public function __construct($table = NULL)
{
if ($table == NULL)
{
$msg = 'ORM initilization failed, no table specified';
log_message('error', $msg);
show_error($msg);
}
else
{
// calls CodeIgniter's database functions
$this->db =& get_instance()->db;
$this->table = $table;
// loading complete
log_message('debug', 'ORM Initialized for '.ucfirst($table).' table.');
}
}
/**
* Table Metadata
* constructs table metadata
*
* @access private
* @param bool $initialCall initial call to the function (default is true)
* @return array table metadata
**/
private function _tableMeta($initialCall = TRUE)
{
$table = $this->table;
if ($initialCall == TRUE && $this->cache == TRUE)
{
$query_schema = $this->db->query('SELECT * FROM orm_schema WHERE table_name = "'.$table.'"');
$result_schema = $query_schema->result_array();
}
if (isset($result_schema[0]) && $this->cache == TRUE)
{
$metadata = unserialize($result_schema[0]['table_schema']);
}
else
{
// SHOW CREATE TABLE query
$query_showTable = $this->db->query('SHOW CREATE TABLE '.$table);
$result_showTable = $query_showTable->result_array();
$showTable = $result_showTable[0]['Create Table'];
/*echo '<pre>';
print_r($showTable);
echo '</pre>';*/
/********************
Primary Keys
********************/
// reads the primary key definition line
preg_match('/PRIMARY KEY +(`.*`)/i', $showTable, $match_PKs);
$str_PK = $match_PKs[0];
// cleans up the PK string so that we can split it into a list of primary keys
preg_match('/.*(`(.*)`)/', $str_PK, $str_PKClean);
$PKs = preg_split('/`,`/', $str_PKClean[1]);
// reorganises the primary keys
foreach ($PKs as $PK)
{
// does the primary key auto_increment? (regex in caseless and multiline mode)
if (preg_match('/'.$PK.'.*auto_increment,$/im', $showTable))
{
$metadata['PKs'][$PK] = 'AUTO_INCREMENT';
}
else
{
$metadata['PKs'][$PK] = NULL;
}
}
/********************
Foreign Keys
********************/
// reads the foreign key definition lines
preg_match_all('/CONSTRAINT.*FOREIGN KEY +(`(.*)`) +REFERENCES +`(.*)` +(`(.*)`).*/i',
$showTable, $match_FKs, PREG_SET_ORDER);
// reorganises the foreign keys
$i = 0;
foreach ($match_FKs as $FK)
{
$FK_id = $FK[1];
// the foreign key
$metadata['FKs'][$i]['FK'] = $FK_id;
// reference table of the foreign key
$metadata['FKs'][$i]['ref'] = $FK[2];
// primary key of the referenced table
$metadata['FKs'][$i]['refPK'] = $FK[3];
// reference tables (for the conjunction table)
foreach($PKs as $PK)
{
if ($FK_id == $PK)
{
// is a conjunction table: a list of the referenced tables
$metadata['isConjunction'][] = $metadata['FKs'][$i]['ref'];
}
}
// belongsTo tables
if (!isset($metadata['isConjunction']))
{
$belongsTo_table = $metadata['FKs'][$i]['ref'];
$metadata['belongsTo'][$belongsTo_table]['FK'] = $FK_id;
$metadata['belongsTo'][$belongsTo_table]['refPK'] = $metadata['FKs'][$i]['refPK'];
}
$i++;
}
/********************
Primary Key Attributes
********************/
// shows attributes only if they're non-foreign keys and non-AUTO_INCREMENT
foreach ($PKs as $PK)
{
$fields = $this->db->field_data($table);
if (!isset($metadata['isConjunction']) && $metadata['PKs'][$PK] != 'AUTO_INCREMENT')
{
foreach ($fields as $field)
{
if ($PK == $field->name)
{
$metadata['PKs'][$PK][] = $this->_fieldType($table, $PK, 'type');
$metadata['PKs'][$PK][] = $this->_fieldType($table, $PK, 'max_length');
}
}
}
}
/********************
Fields
********************/
if ($initialCall == TRUE && !isset($metadata['isConjunction']))
{
$fields = $this->db->field_data($table);
foreach ($fields as $field)
{
// lists only non-key fields
if (array_key_exists($field->name, $metadata['PKs']) OR
isset($metadata['FKs']) && array_key_exists($field->name, $metadata['FKs']))
{
}
else
{
$metadata['fields'][$field->name][] = $this->_fieldType($field->name, 'type');
$metadata['fields'][$field->name][] = $this->_fieldType($field->name, 'max_length');
}
}
}
/********************
Associations
********************/
// only run this once
if ($initialCall == TRUE && !isset($metadata['isConjunction']))
{
// a list of all tables
$tables_rebuild = $this->db->list_tables();
// rebuilds each individual table
foreach ($tables_rebuild as $table_rebuild)
{
// prepares to rebuild the data
$this->table = $table_rebuild;
$metadata_rebuild[$table_rebuild] = $this->_tableMeta($initialCall = FALSE);
$this->table = $table;
$initialCall = TRUE;
}
// goes through each tables
foreach ($metadata_rebuild as $table_rebuild_name => $table_rebuild_data)
{
// hasOneMany
if (isset($table_rebuild_data['belongsTo']))
{
// goes through each 'belongsTo' relationships
foreach ($table_rebuild_data['belongsTo'] as $table_associated => $table_associated_PK)
{
if ($table == $table_associated)
{
foreach ($table_rebuild_data['FKs'] as $table_rebuild_FK)
{
if ($table_rebuild_FK['ref'] == $table_associated)
{
$refPK = array_keys($table_rebuild_data['PKs']);
$metadata['HOM'][$table_rebuild_name]['refFK'] = $table_rebuild_FK['FK'];
$metadata['HOM'][$table_rebuild_name]['refPK'] = $refPK[0];
}
}
}
}
}
// hasAndBelongsToMany
if (isset($table_rebuild_data['isConjunction']))
{
if ($table == $table_rebuild_data['isConjunction'][0])
{
$table_rebuild_data_HABTMTable = $table_rebuild_data['isConjunction'][1];
$table_remote_PK = $table_rebuild_data['FKs'][1]['refPK'];
}
elseif ($table == $table_rebuild_data['isConjunction'][1])
{
$table_rebuild_data_HABTMTable = $table_rebuild_data['isConjunction'][0];
$table_remote_PK = $table_rebuild_data['FKs'][0]['refPK'];
}
if (isset($table_rebuild_data_HABTMTable))
{
foreach ($table_rebuild_data['FKs'] as $table_rebuild_FK)
{
if ($table_rebuild_FK['ref'] == $table)
{
$metadata['HABTM'][$table_rebuild_data_HABTMTable]['conjTable'] = $table_rebuild_name;
$metadata['HABTM'][$table_rebuild_data_HABTMTable]['PK'] = $PK;
$metadata['HABTM'][$table_rebuild_data_HABTMTable]['refFK'] = $table_rebuild_FK['FK'];
$refPKs = array_keys($table_rebuild_data['PKs']);
foreach ($refPKs as $refPK)
{
if ($refPK != $table_rebuild_FK['FK'])
{
$metadata['HABTM'][$table_rebuild_data_HABTMTable]['refPK'] = $refPK;
}
}
$metadata['HABTM'][$table_rebuild_data_HABTMTable]['refPKPK'] = $table_remote_PK;
}
}
}
}
}
}
if ($initialCall == TRUE && $this->cache == TRUE)
{
// stores metadata to database
$this->db->query('INSERT INTO orm_schema (table_name, table_schema)
VALUES ("'.$table.'", "'.addslashes(serialize($metadata)).'");');
}
}
if ($initialCall == TRUE)
{
/*echo '<pre> <b>metadata for '.$table.'</b>
';
print_r($metadata);
echo '
';
echo '</pre>';*/
}
$this->tableMeta = $metadata;
return $metadata;
}
/**
* Field Type
* finds field type and max_length
* this function is needed because MySQL/CodeIgniter's inbuilt function does not work
*
* @access private
* @param string $field field name
* @param string $returnType 'type' or 'max_length', default returns the field type string
* @return string field type data
**/
private function _fieldType($field, $returnType = NULL)
{
$table = $this->table;
// SHOW COLUMNS query
$query_fieldsData = $this->db->query('SHOW COLUMNS FROM '.$table);
$result_fieldsData = $query_fieldsData->result_array();
foreach ($result_fieldsData as $fieldData)
{
if ($fieldData['Field'] == $field)
{
$fieldType['str'] = $fieldData['Type'];
}
}
// analyses the field type string
preg_match('/(D+)((d+)).*/', $fieldType['str'], $match_type);
// returns type
if ($returnType == 'type')
{
if (isset($match_type[1]))
{
return $fieldType['type'] = $match_type[1];
}
// for fields like 'text' where there is no brackets and max length
else
{
return $fieldType['str'];
}
}
// returns max_length
elseif ($returnType == 'max_length')
{
if (isset($match_type[2]))
{
return $fieldType['max_length'] = $match_type[2];
}
}
// returns the string
else
{
return $fieldType['str'];
}
}
/**
* Find
* finds table data with an optional WHERE query and associated data
*
* @access public
* @param string or array $withAssoc associated tables in an array or 'ALL' for all associated tables
* @param string $query_where optional WHERE query
* @return array table data (objects) in an array
**/
public function find($withAssoc = NULL, $query_where = NULL)
{
$table = $this->table;
// initial table data with no associated data
if (isset($query_where) && preg_match('/= +w/i', $query_where))
{
$query_tableData = $this->db->query("SELECT * FROM $table WHERE $query_where");
}
// ignores the query if the passed value is NULL or is empty
elseif (isset($query_where) AND !preg_match('/= +w/i', $query_where) || stristr($query_where, '= NULL'))
{
log_message('info', 'Query error detected and ignored in $this->orm->find() for table: '.$this->table);
return FALSE;
}
else
{
$query_tableData = $this->db->query('SELECT * FROM '.$table);
}
$result_tableData = $query_tableData->result();
if ($withAssoc != NULL)
{
// table metadata
$tableMeta = $this->_tableMeta($table);
// available associated tables
$assoc_belongsTo = (array)$tableMeta['belongsTo'];
$assoc_HOM = (array)$tableMeta['HOM'];
$assoc_HABTM = (array)$tableMeta['HABTM'];
$assoc_All = @array_merge($assoc_belongsTo, $assoc_HOM, $assoc_HABTM);
if ($withAssoc == 'ALL')
{
$withAssoc_new = $assoc_All;
}
// populates association schema
else
{
foreach ($withAssoc as $assocTable)
{
if (array_key_exists($assocTable, $assoc_All))
{
$withAssoc_new[$assocTable] = $assoc_All[$assocTable];
}
}
}
$withAssoc = $withAssoc_new;
// applies every associated table
foreach ($withAssoc as $assocTable => $assocSchema)
{
$i = 0;
// applies to every data record
foreach ($result_tableData as $dataRecord)
{
// belongsTo
if (array_key_exists($assocTable, $assoc_belongsTo) && $dataRecord->$assocSchema['FK'] != NULL)
{
$this->table = $assocTable;
$assocData = $this->find(NULL, $assocSchema['refPK'].' = '.$dataRecord->$assocSchema['FK']);
$this->table = $table;
$dataRecord->$assocTable = $assocData[0];
}
// hasOneMany
elseif (array_key_exists($assocTable, $assoc_HOM) && $dataRecord->$assocSchema['refPK'] != NULL)
{
$this->table = $assocTable;
$dataRecord->$assocTable = $this->find(NULL, $assocSchema['refFK'].' = '.$dataRecord->$assocSchema['refPK']);
$this->table = $table;
}
// hasAndBelongsToMany
elseif (array_key_exists($assocTable, $assoc_HABTM))
{
// fetches data from the conjunction table
$this->table = $assocSchema['conjTable'];
$conjData = $this->find(NULL, $assocSchema['refFK'].' = '.$dataRecord->$assocSchema['PK']);
// fetches data from the remotely linked table
if (!empty($conjData))
{
$this->table = $assocTable;
foreach ($conjData as $conjRecord)
{
$conjRecordNew = $this->find(NULL, $assocSchema['refPKPK'].' = '.$conjRecord->$assocSchema['refPK']);
$conjDataNew[$i][] = $conjRecordNew[0];
}
$dataRecord->$assocTable = $conjDataNew[$i];
$this->table = $table;
}
}
$result_tableData[$i] = $dataRecord;
$i++;
}
}
}
foreach ($result_tableData as $dataObj)
{
//$this->save() = $dataObj->save();
}
if (isset($withAssoc))
{
echo '<pre> <b>table data for '.$table.'</b>
';
print_r($result_tableData);
echo '
';
echo '</pre>';
}
$this->table = $table;
return $result_tableData;
}
public function add()
{
$table = $this->table;
$tableMeta = $this->_tableMeta($table);
$yo = $this->db->list_fields($table);
echo '<pre>';
print_r($tableMeta);
echo '</pre>';
}
public function save()
{
}
public function &__get($prop)
{
$prop = (string) $prop;
$fields = $this->tableMeta['fields'];
if (array_key_exists($fields, $prop))
{
echo 'yes';
}
else
{
echo 'no';
}
}
public function __set($prop, $value)
{
$prop = (string) $prop;
}
public function __call($method, $args)
{
}
}
?>
Incoming search terms:
- ci orm
- php ci ORM
- CI框架 orm
- mapper
- php orm 的支持
- Mapper method saveMembers (interface cn neusoft mapper members MembersMapper) attempted to return
- php5 orm
- object(orm)[8]
- Object Relational Mapper
- Mapper php
Tags: CodeIgniter, ORM