196 lines
5 KiB
PHP
196 lines
5 KiB
PHP
<?php
|
|
|
|
/** Information about tables and columns structure
|
|
*/
|
|
interface NotORM_Structure {
|
|
|
|
/** Get primary key of a table in $db->$table()
|
|
* @param string
|
|
* @return string
|
|
*/
|
|
function getPrimary($table);
|
|
|
|
/** Get column holding foreign key in $table[$id]->$name()
|
|
* @param string
|
|
* @param string
|
|
* @return string
|
|
*/
|
|
function getReferencingColumn($name, $table);
|
|
|
|
/** Get target table in $table[$id]->$name()
|
|
* @param string
|
|
* @param string
|
|
* @return string
|
|
*/
|
|
function getReferencingTable($name, $table);
|
|
|
|
/** Get column holding foreign key in $table[$id]->$name
|
|
* @param string
|
|
* @param string
|
|
* @return string
|
|
*/
|
|
function getReferencedColumn($name, $table);
|
|
|
|
/** Get table holding foreign key in $table[$id]->$name
|
|
* @param string
|
|
* @param string
|
|
* @return string
|
|
*/
|
|
function getReferencedTable($name, $table);
|
|
|
|
/** Get sequence name, used by insert
|
|
* @param string
|
|
* @return string
|
|
*/
|
|
function getSequence($table);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Structure described by some rules
|
|
*/
|
|
class NotORM_Structure_Convention implements NotORM_Structure {
|
|
protected $primary, $foreign, $table, $prefix;
|
|
|
|
/** Create conventional structure
|
|
* @param string %s stands for table name
|
|
* @param string %1$s stands for key used after ->, %2$s for table name
|
|
* @param string %1$s stands for key used after ->, %2$s for table name
|
|
* @param string prefix for all tables
|
|
*/
|
|
function __construct($primary = 'id', $foreign = '%s_id', $table = '%s', $prefix = '') {
|
|
$this->primary = $primary;
|
|
$this->foreign = $foreign;
|
|
$this->table = $table;
|
|
$this->prefix = $prefix;
|
|
}
|
|
|
|
function getPrimary($table) {
|
|
return sprintf($this->primary, $this->getColumnFromTable($table));
|
|
}
|
|
|
|
function getReferencingColumn($name, $table) {
|
|
return $this->getReferencedColumn(substr($table, strlen($this->prefix)), $this->prefix . $name);
|
|
}
|
|
|
|
function getReferencingTable($name, $table) {
|
|
return $this->prefix . $name;
|
|
}
|
|
|
|
function getReferencedColumn($name, $table) {
|
|
return sprintf($this->foreign, $this->getColumnFromTable($name), substr($table, strlen($this->prefix)));
|
|
}
|
|
|
|
function getReferencedTable($name, $table) {
|
|
return $this->prefix . sprintf($this->table, $name, $table);
|
|
}
|
|
|
|
function getSequence($table) {
|
|
return null;
|
|
}
|
|
|
|
protected function getColumnFromTable($name) {
|
|
if ($this->table != '%s' && preg_match('(^' . str_replace('%s', '(.*)', preg_quote($this->table)) . '$)', $name, $match)) {
|
|
return $match[1];
|
|
}
|
|
return $name;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Structure reading meta-informations from the database
|
|
*/
|
|
class NotORM_Structure_Discovery implements NotORM_Structure {
|
|
protected $connection, $cache, $structure = array();
|
|
protected $foreign;
|
|
|
|
/** Create autodisovery structure
|
|
* @param PDO
|
|
* @param NotORM_Cache
|
|
* @param string use "%s_id" to access $name . "_id" column in $row->$name
|
|
*/
|
|
function __construct(PDO $connection, NotORM_Cache $cache = null, $foreign = '%s') {
|
|
$this->connection = $connection;
|
|
$this->cache = $cache;
|
|
$this->foreign = $foreign;
|
|
if ($cache) {
|
|
$this->structure = $cache->load("structure");
|
|
}
|
|
}
|
|
|
|
/** Save data to cache
|
|
*/
|
|
function __destruct() {
|
|
if ($this->cache) {
|
|
$this->cache->save("structure", $this->structure);
|
|
}
|
|
}
|
|
|
|
function getPrimary($table) {
|
|
$return = &$this->structure["primary"][$table];
|
|
if (!isset($return)) {
|
|
$return = "";
|
|
foreach ($this->connection->query("EXPLAIN $table") as $column) {
|
|
if ($column[3] == "PRI") { // 3 - "Key" is not compatible with PDO::CASE_LOWER
|
|
if ($return != "") {
|
|
$return = ""; // multi-column primary key is not supported
|
|
break;
|
|
}
|
|
$return = $column[0];
|
|
}
|
|
}
|
|
}
|
|
return $return;
|
|
}
|
|
|
|
function getReferencingColumn($name, $table) {
|
|
$name = strtolower($name);
|
|
$return = &$this->structure["referencing"][$table];
|
|
if (!isset($return[$name])) {
|
|
foreach ($this->connection->query("
|
|
SELECT TABLE_NAME, COLUMN_NAME
|
|
FROM information_schema.KEY_COLUMN_USAGE
|
|
WHERE TABLE_SCHEMA = DATABASE()
|
|
AND REFERENCED_TABLE_SCHEMA = DATABASE()
|
|
AND REFERENCED_TABLE_NAME = " . $this->connection->quote($table) . "
|
|
AND REFERENCED_COLUMN_NAME = " . $this->connection->quote($this->getPrimary($table)) //! may not reference primary key
|
|
) as $row) {
|
|
$return[strtolower($row[0])] = $row[1];
|
|
}
|
|
}
|
|
return $return[$name];
|
|
}
|
|
|
|
function getReferencingTable($name, $table) {
|
|
return $name;
|
|
}
|
|
|
|
function getReferencedColumn($name, $table) {
|
|
return sprintf($this->foreign, $name);
|
|
}
|
|
|
|
function getReferencedTable($name, $table) {
|
|
$column = strtolower($this->getReferencedColumn($name, $table));
|
|
$return = &$this->structure["referenced"][$table];
|
|
if (!isset($return[$column])) {
|
|
foreach ($this->connection->query("
|
|
SELECT COLUMN_NAME, REFERENCED_TABLE_NAME
|
|
FROM information_schema.KEY_COLUMN_USAGE
|
|
WHERE TABLE_SCHEMA = DATABASE()
|
|
AND REFERENCED_TABLE_SCHEMA = DATABASE()
|
|
AND TABLE_NAME = " . $this->connection->quote($table) . "
|
|
") as $row) {
|
|
$return[strtolower($row[0])] = $row[1];
|
|
}
|
|
}
|
|
return $return[$column];
|
|
}
|
|
|
|
function getSequence($table) {
|
|
return null;
|
|
}
|
|
|
|
}
|