1
0
mirror of synced 2025-01-18 22:41:43 +03:00

Finally first, very basic, running CRUD tests for Doctrine 2

This commit is contained in:
romanb 2009-01-07 17:46:02 +00:00
parent 1f6676f1d9
commit d97336373d
48 changed files with 801 additions and 656 deletions

View File

@ -216,9 +216,7 @@ class Doctrine_DBAL_Connection
*/ */
public function connect() public function connect()
{ {
if ($this->_isConnected) { if ($this->_isConnected) return false;
return false;
}
$driverOptions = isset($this->_params['driverOptions']) ? $driverOptions = isset($this->_params['driverOptions']) ?
$this->_params['driverOptions'] : array(); $this->_params['driverOptions'] : array();
@ -259,6 +257,7 @@ class Doctrine_DBAL_Connection
*/ */
public function delete($tableName, array $identifier) public function delete($tableName, array $identifier)
{ {
$this->connect();
$criteria = array(); $criteria = array();
foreach (array_keys($identifier) as $id) { foreach (array_keys($identifier) as $id) {
$criteria[] = $this->quoteIdentifier($id) . ' = ?'; $criteria[] = $this->quoteIdentifier($id) . ' = ?';
@ -282,6 +281,7 @@ class Doctrine_DBAL_Connection
*/ */
public function update($tableName, array $data, array $identifier) public function update($tableName, array $data, array $identifier)
{ {
$this->connect();
if (empty($data)) { if (empty($data)) {
return false; return false;
} }
@ -316,6 +316,7 @@ class Doctrine_DBAL_Connection
*/ */
public function insert($tableName, array $data) public function insert($tableName, array $data)
{ {
$this->connect();
if (empty($data)) { if (empty($data)) {
return false; return false;
} }
@ -326,7 +327,7 @@ class Doctrine_DBAL_Connection
$a = array(); $a = array();
foreach ($data as $columnName => $value) { foreach ($data as $columnName => $value) {
$cols[] = $this->quoteIdentifier($columnName); $cols[] = $this->quoteIdentifier($columnName);
if ($value instanceof Doctrine_Expression) { if ($value instanceof Doctrine_DBAL_Expression) {
$a[] = $value->getSql(); $a[] = $value->getSql();
unset($data[$columnName]); unset($data[$columnName]);
} else { } else {
@ -395,6 +396,7 @@ class Doctrine_DBAL_Connection
*/ */
public function quote($input, $type = null) public function quote($input, $type = null)
{ {
$this->connect();
return $this->_conn->quote($input, $type); return $this->_conn->quote($input, $type);
} }
@ -492,10 +494,10 @@ class Doctrine_DBAL_Connection
*/ */
public function prepare($statement) public function prepare($statement)
{ {
echo $statement;
$this->connect(); $this->connect();
try { try {
$stmt = $this->_conn->prepare($statement); return $this->_conn->prepare($statement);
return new Doctrine_DBAL_Statement($this, $stmt);
} catch (PDOException $e) { } catch (PDOException $e) {
$this->rethrowException($e, $this); $this->rethrowException($e, $this);
} }
@ -530,6 +532,7 @@ class Doctrine_DBAL_Connection
{ {
$this->connect(); $this->connect();
try { try {
echo $query . PHP_EOL;
if ( ! empty($params)) { if ( ! empty($params)) {
$stmt = $this->prepare($query); $stmt = $this->prepare($query);
$stmt->execute($params); $stmt->execute($params);
@ -566,7 +569,7 @@ class Doctrine_DBAL_Connection
return $count; return $count;
} }
} catch (PDOException $e) { } catch (PDOException $e) {
$this->rethrowException($e, $this); throw $e;
} }
} }
@ -577,7 +580,7 @@ class Doctrine_DBAL_Connection
*/ */
public function rethrowException(Exception $e, $invoker) public function rethrowException(Exception $e, $invoker)
{ {
throw $exc; throw $e;
} }
/** /**
@ -667,6 +670,7 @@ class Doctrine_DBAL_Connection
*/ */
public function lastInsertId($seqName = null) public function lastInsertId($seqName = null)
{ {
$this->connect();
return $this->_conn->lastInsertId($seqName); return $this->_conn->lastInsertId($seqName);
} }
@ -680,6 +684,7 @@ class Doctrine_DBAL_Connection
*/ */
public function beginTransaction() public function beginTransaction()
{ {
$this->connect();
if ($this->_transactionNestingLevel == 0) { if ($this->_transactionNestingLevel == 0) {
return $this->_conn->beginTransaction(); return $this->_conn->beginTransaction();
} }

View File

@ -11,7 +11,7 @@
interface Doctrine_DBAL_Driver_Connection interface Doctrine_DBAL_Driver_Connection
{ {
public function prepare($prepareString); public function prepare($prepareString);
public function query($queryString); public function query();
public function quote($input); public function quote($input);
public function exec($statement); public function exec($statement);
public function lastInsertId(); public function lastInsertId();
@ -22,4 +22,3 @@ interface Doctrine_DBAL_Driver_Connection
public function errorInfo(); public function errorInfo();
} }
?>

View File

@ -59,7 +59,7 @@ class Doctrine_DBAL_Driver_PDOSqlite_Driver implements Doctrine_DBAL_Driver
* Gets the schema manager that is relevant for this driver. * Gets the schema manager that is relevant for this driver.
* *
* @param Doctrine\DBAL\Connection $conn * @param Doctrine\DBAL\Connection $conn
* @return Doctrine\DBAL\Schema\AbstractSchemaManager * @return Doctrine\DBAL\Schema\SqliteSchemaManager
*/ */
public function getSchemaManager(Doctrine_DBAL_Connection $conn) public function getSchemaManager(Doctrine_DBAL_Connection $conn)
{ {

View File

@ -1,4 +1,6 @@
<?php <?php
class Doctrine_DBAL_Driver_PDOStatement extends PDOStatement implements Doctrine_DBAL_Driver_Statement class Doctrine_DBAL_Driver_PDOStatement extends PDOStatement implements Doctrine_DBAL_Driver_Statement
{} {
private function __construct() {}
}

View File

@ -46,7 +46,7 @@ interface Doctrine_DBAL_Driver_Statement
* @param integer $type Data type of the parameter, specified by the Doctrine::PARAM_* constants. * @param integer $type Data type of the parameter, specified by the Doctrine::PARAM_* constants.
* @return boolean Returns TRUE on success or FALSE on failure * @return boolean Returns TRUE on success or FALSE on failure
*/ */
public function bindColumn($column, $param, $type = null); public function bindColumn($column, &$param, $type = null);
/** /**
* bindValue * bindValue
@ -292,5 +292,5 @@ interface Doctrine_DBAL_Driver_Statement
* @param integer $mode The fetch mode must be one of the Doctrine::FETCH_* constants. * @param integer $mode The fetch mode must be one of the Doctrine::FETCH_* constants.
* @return boolean Returns 1 on success or FALSE on failure. * @return boolean Returns 1 on success or FALSE on failure.
*/ */
public function setFetchMode($mode, $arg1 = null, $arg2 = null); public function setFetchMode($mode, $arg1);
} }

View File

@ -991,7 +991,7 @@ abstract class Doctrine_DBAL_Platforms_AbstractPlatform
throw new Doctrine_Export_Exception('no fields specified for table ' . $name); throw new Doctrine_Export_Exception('no fields specified for table ' . $name);
} }
$queryFields = $this->getFieldDeclarationList($columns); $queryFields = $this->getFieldDeclarationListSql($columns);
if (isset($options['primary']) && ! empty($options['primary'])) { if (isset($options['primary']) && ! empty($options['primary'])) {
$queryFields .= ', PRIMARY KEY(' . implode(', ', array_values($options['primary'])) . ')'; $queryFields .= ', PRIMARY KEY(' . implode(', ', array_values($options['primary'])) . ')';
@ -1193,7 +1193,7 @@ abstract class Doctrine_DBAL_Platforms_AbstractPlatform
} }
/** /**
* Get declaration of a number of field in bulk * Get declaration of a number of fields in bulk
* *
* @param array $fields a multidimensional associative array. * @param array $fields a multidimensional associative array.
* The first dimension determines the field name, while the second * The first dimension determines the field name, while the second
@ -1223,9 +1223,9 @@ abstract class Doctrine_DBAL_Platforms_AbstractPlatform
*/ */
public function getFieldDeclarationListSql(array $fields) public function getFieldDeclarationListSql(array $fields)
{ {
$queryFields = array();
foreach ($fields as $fieldName => $field) { foreach ($fields as $fieldName => $field) {
$query = $this->getDeclarationSql($fieldName, $field); $query = $this->getDeclarationSql($fieldName, $field);
$queryFields[] = $query; $queryFields[] = $query;
} }
return implode(', ', $queryFields); return implode(', ', $queryFields);
@ -1265,33 +1265,64 @@ abstract class Doctrine_DBAL_Platforms_AbstractPlatform
*/ */
public function getDeclarationSql($name, array $field) public function getDeclarationSql($name, array $field)
{ {
$default = $this->getDefaultFieldDeclarationSql($field); $default = $this->getDefaultFieldDeclarationSql($field);
$charset = (isset($field['charset']) && $field['charset']) ?
$charset = (isset($field['charset']) && $field['charset']) ? ' ' . $this->getCharsetFieldDeclarationSql($field['charset']) : '';
' ' . $this->getCharsetFieldDeclarationSql($field['charset']) : '';
$collation = (isset($field['collation']) && $field['collation']) ? $collation = (isset($field['collation']) && $field['collation']) ?
' ' . $this->getCollationFieldDeclarationSql($field['collation']) : ''; ' ' . $this->getCollationFieldDeclarationSql($field['collation']) : '';
$notnull = (isset($field['notnull']) && $field['notnull']) ? ' NOT NULL' : '';
$unique = (isset($field['unique']) && $field['unique']) ?
' ' . $this->getUniqueFieldDeclarationSql() : '';
$check = (isset($field['check']) && $field['check']) ?
' ' . $field['check'] : '';
$notnull = (isset($field['notnull']) && $field['notnull']) ? ' NOT NULL' : ''; $typeDecl = $field['type']->getSqlDeclaration($field, $this);
$unique = (isset($field['unique']) && $field['unique']) ? return $this->quoteIdentifier($name, true) . ' ' . $typeDecl . $charset . $default . $notnull . $unique . $check . $collation;
' ' . $this->getUniqueFieldDeclarationSql() : '';
$check = (isset($field['check']) && $field['check']) ?
' ' . $field['check'] : '';
$method = 'get' . $field['type'] . 'Declaration';
if (method_exists($this, $method)) {
return $this->$method($name, $field);
} else {
$dec = $this->getNativeDeclaration($field);
}
return $this->quoteIdentifier($name, true) . ' ' . $dec . $charset . $default . $notnull . $unique . $check . $collation;
} }
/**
*
* @param <type> $name
* @param <type> $field
*/
abstract public function getIntegerTypeDeclarationSql(array $columnDef);
/**
* Gets the SQL snippet that declares a BIGINT column.
*
* @return string
*/
abstract public function getBigIntTypeDeclarationSql(array $columnDef);
/**
* Gets the SQL snippet that declares a TINYINT column.
*
* @return string
*/
abstract public function getTinyIntTypeDeclarationSql(array $columnDef);
/**
* Gets the SQL snippet that declares a SMALLINT column.
*
* @return string
*/
abstract public function getSmallIntTypeDeclarationSql(array $columnDef);
/**
* Gets the SQL snippet that declares a MEDIUMINT column.
*
* @return string
*/
abstract public function getMediumIntTypeDeclarationSql(array $columnDef);
/**
* Gets the SQL snippet that declares common properties of an integer column.
*
* @return string
*/
abstract protected function _getCommonIntegerTypeDeclarationSql(array $columnDef);
/** /**
* getDefaultDeclaration * getDefaultDeclaration
* Obtain DBMS specific SQL code portion needed to set a default value * Obtain DBMS specific SQL code portion needed to set a default value
@ -1858,7 +1889,18 @@ abstract class Doctrine_DBAL_Platforms_AbstractPlatform
{ {
return true; return true;
} }
public function getIdentityColumnNullInsertSql()
{
return "";
}
/**
* Gets the SQL snippet used to declare a VARCHAR column on the MySql platform.
*
* @params array $field
*/
abstract public function getVarcharDeclarationSql(array $field);
} }
?>

View File

@ -230,7 +230,9 @@ class Doctrine_DBAL_Platforms_MySqlPlatform extends Doctrine_DBAL_Platforms_Abst
} }
/** /**
* @TEST * Gets the SQL snippet used to declare a VARCHAR column on the MySql platform.
*
* @params array $field
*/ */
public function getVarcharDeclarationSql(array $field) public function getVarcharDeclarationSql(array $field)
{ {
@ -243,7 +245,7 @@ class Doctrine_DBAL_Platforms_MySqlPlatform extends Doctrine_DBAL_Platforms_Abst
} }
$length = ($field['length'] <= $this->getVarcharMaxLength()) ? $field['length'] : false; $length = ($field['length'] <= $this->getVarcharMaxLength()) ? $field['length'] : false;
$fixed = (isset($field['fixed'])) ? $field['fixed'] : false; $fixed = (isset($field['fixed'])) ? $field['fixed'] : false;
return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)') return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)')
: ($length ? 'VARCHAR(' . $length . ')' : 'TEXT'); : ($length ? 'VARCHAR(' . $length . ')' : 'TEXT');
@ -1037,7 +1039,37 @@ class Doctrine_DBAL_Platforms_MySqlPlatform extends Doctrine_DBAL_Platforms_Abst
* declare the specified field. * declare the specified field.
* @override * @override
*/ */
public function getIntegerDeclarationSql($name, $field) public function getIntegerTypeDeclarationSql(array $field)
{
return 'INT ' . $this->_getCommonIntegerTypeDeclarationSql($field);
}
/** @override */
public function getBigIntTypeDeclarationSql(array $field)
{
return 'BIGINT ' . $this->_getCommonIntegerTypeDeclarationSql($field);
}
/** @override */
public function getTinyIntTypeDeclarationSql(array $field)
{
return 'TINYINT ' . $this->_getCommonIntegerTypeDeclarationSql($field);
}
/** @override */
public function getSmallIntDeclarationSql(array $field)
{
return 'SMALLINT ' . $this->_getCommonIntegerTypeDeclarationSql($field);
}
/** @override */
public function getMediumIntDeclarationSql(array $field)
{
return 'MEDIUMINT ' . $this->_getCommonIntegerTypeDeclarationSql($field);
}
/** @override */
protected function _getCommonIntegerTypeDeclarationSql(array $columnDef)
{ {
$default = $autoinc = ''; $default = $autoinc = '';
if ( ! empty($field['autoincrement'])) { if ( ! empty($field['autoincrement'])) {
@ -1058,9 +1090,7 @@ class Doctrine_DBAL_Platforms_MySqlPlatform extends Doctrine_DBAL_Platforms_Abst
$notnull = (isset($field['notnull']) && $field['notnull']) ? ' NOT NULL' : ''; $notnull = (isset($field['notnull']) && $field['notnull']) ? ' NOT NULL' : '';
$unsigned = (isset($field['unsigned']) && $field['unsigned']) ? ' UNSIGNED' : ''; $unsigned = (isset($field['unsigned']) && $field['unsigned']) ? ' UNSIGNED' : '';
$name = $this->quoteIdentifier($name, true); return $unsigned . $default . $notnull . $autoinc;
return $name . ' ' . $this->getNativeDeclaration($field) . $unsigned . $default . $notnull . $autoinc;
} }
/** /**

View File

@ -391,6 +391,162 @@ class Doctrine_DBAL_Platforms_SqlitePlatform extends Doctrine_DBAL_Platforms_Abs
{ {
return 'PRAGMA read_uncommitted = ' . $this->_getTransactionIsolationLevelSql($level); return 'PRAGMA read_uncommitted = ' . $this->_getTransactionIsolationLevelSql($level);
} }
/** @override */
public function prefersIdentityColumns() {
return true;
}
/** @override */
public function getIntegerTypeDeclarationSql(array $field)
{
return 'INT ' . $this->_getCommonIntegerTypeDeclarationSql($field);
}
/** @override */
public function getBigIntTypeDeclarationSql(array $field)
{
return 'BIGINT ' . $this->_getCommonIntegerTypeDeclarationSql($field);
}
/** @override */
public function getTinyIntTypeDeclarationSql(array $field)
{
return 'TINYINT ' . $this->_getCommonIntegerTypeDeclarationSql($field);
}
/** @override */
public function getSmallIntTypeDeclarationSql(array $field)
{
return 'SMALLINT ' . $this->_getCommonIntegerTypeDeclarationSql($field);
}
/** @override */
public function getMediumIntTypeDeclarationSql(array $field)
{
return 'MEDIUMINT ' . $this->_getCommonIntegerTypeDeclarationSql($field);
}
/** @override */
protected function _getCommonIntegerTypeDeclarationSql(array $columnDef)
{
$default = $autoinc = '';
if ( ! empty($columnDef['autoincrement'])) {
$autoinc = ' AUTO_INCREMENT';
} else if (array_key_exists('default', $columnDef)) {
if ($field['default'] === '') {
$field['default'] = empty($columnDef['notnull']) ? null : 0;
}
if (is_null($columnDef['default'])) {
$default = ' DEFAULT NULL';
} else {
$default = ' DEFAULT ' . $this->quote($columnDef['default']);
}
} else if (empty($columnDef['notnull'])) {
$default = ' DEFAULT NULL';
}
$notnull = (isset($columnDef['notnull']) && $columnDef['notnull']) ? ' NOT NULL' : '';
$unsigned = (isset($columnDef['unsigned']) && $columnDef['unsigned']) ? ' UNSIGNED' : '';
return $unsigned . $default . $notnull . $autoinc;
}
/**
* create a new table
*
* @param string $name Name of the database that should be created
* @param array $fields Associative array that contains the definition of each field of the new table
* The indexes of the array entries are the names of the fields of the table an
* the array entry values are associative arrays like those that are meant to be
* passed with the field definitions to get[Type]Declaration() functions.
* array(
* 'id' => array(
* 'type' => 'integer',
* 'unsigned' => 1
* 'notnull' => 1
* 'default' => 0
* ),
* 'name' => array(
* 'type' => 'text',
* 'length' => 12
* ),
* 'password' => array(
* 'type' => 'text',
* 'length' => 12
* )
* );
* @param array $options An associative array of table options:
*
* @return void
* @override
*/
public function getCreateTableSql($name, array $fields, array $options = array())
{
if ( ! $name) {
throw new Doctrine_Exception('no valid table name specified');
}
if (empty($fields)) {
throw new Doctrine_Exception('no fields specified for table '.$name);
}
$queryFields = $this->getFieldDeclarationListSql($fields);
$autoinc = false;
foreach($fields as $field) {
if (isset($field['autoincrement']) && $field['autoincrement'] ||
(isset($field['autoinc']) && $field['autoinc'])) {
$autoinc = true;
break;
}
}
if ( ! $autoinc && isset($options['primary']) && ! empty($options['primary'])) {
$keyColumns = array_values($options['primary']);
$keyColumns = array_map(array($this->_conn, 'quoteIdentifier'), $keyColumns);
$queryFields.= ', PRIMARY KEY('.implode(', ', $keyColumns).')';
}
$name = $this->quoteIdentifier($name, true);
$sql = 'CREATE TABLE ' . $name . ' (' . $queryFields;
if ($check = $this->getCheckDeclarationSql($fields)) {
$sql .= ', ' . $check;
}
if (isset($options['checks']) && $check = $this->getCheckDeclarationSql($options['checks'])) {
$sql .= ', ' . $check;
}
$sql .= ')';
$query[] = $sql;
if (isset($options['indexes']) && ! empty($options['indexes'])) {
foreach ($options['indexes'] as $index => $definition) {
$query[] = $this->createIndexSql($name, $index, $definition);
}
}
return $query;
}
/**
* {@inheritdoc}
*/
public function getVarcharDeclarationSql(array $field)
{
if ( ! isset($field['length'])) {
if (array_key_exists('default', $field)) {
$field['length'] = $this->getVarcharMaxLength();
} else {
$field['length'] = false;
}
}
$length = ($field['length'] <= $this->getVarcharMaxLength()) ? $field['length'] : false;
$fixed = (isset($field['fixed'])) ? $field['fixed'] : false;
return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)')
: ($length ? 'VARCHAR(' . $length . ')' : 'TEXT');
}
} }
?>

View File

@ -19,7 +19,7 @@
* <http://www.phpdoctrine.org>. * <http://www.phpdoctrine.org>.
*/ */
#namespace Doctrine::DBAL::Schema; #namespace Doctrine\DBAL\Schema;
/** /**
* Base class for schema managers. Schema managers are used to inspect and/or * Base class for schema managers. Schema managers are used to inspect and/or
@ -28,14 +28,19 @@
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @author Konsta Vesterinen <kvesteri@cc.hut.fi> * @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library) * @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
* @author Roman Borschel <roman@code-factory.org>
* @version $Revision$ * @version $Revision$
* @since 2.0 * @since 2.0
* @todo Rename to AbstractSchemaManager
*/ */
abstract class Doctrine_DBAL_Schema_AbstractSchemaManager abstract class Doctrine_DBAL_Schema_AbstractSchemaManager
{ {
protected $_conn; protected $_conn;
public function __construct(Doctrine_DBAL_Connection $conn)
{
$this->_conn = $conn;
}
/** /**
* lists all databases * lists all databases
* *

View File

@ -19,7 +19,7 @@
* <http://www.phpdoctrine.org>. * <http://www.phpdoctrine.org>.
*/ */
#namespace Doctrine::DBAL::Schema; #namespace Doctrine\DBAL\Schema;
/** /**
* xxx * xxx
@ -32,11 +32,6 @@
*/ */
class Doctrine_DBAL_Schema_MySqlSchemaManager extends Doctrine_DBAL_Schema_AbstractSchemaManager class Doctrine_DBAL_Schema_MySqlSchemaManager extends Doctrine_DBAL_Schema_AbstractSchemaManager
{ {
public function __construct(Doctrine_Connection $conn)
{
$this->_conn = $conn;
}
/** /**
* lists all database sequences * lists all database sequences
* *

View File

@ -19,7 +19,7 @@
* <http://www.phpdoctrine.org>. * <http://www.phpdoctrine.org>.
*/ */
#namespace Doctrine::DBAL::Schema; #namespace Doctrine\DBAL\Schema;
/** /**
* xxx * xxx
@ -32,11 +32,6 @@
*/ */
class Doctrine_DBAL_Schema_OracleSchemaManager extends Doctrine_DBAL_Schema_AbstractSchemaManager class Doctrine_DBAL_Schema_OracleSchemaManager extends Doctrine_DBAL_Schema_AbstractSchemaManager
{ {
public function __construct(Doctrine_Connection_Oracle $conn)
{
$this->_conn = $conn;
}
/** /**
* create a new database * create a new database
* *

View File

@ -19,7 +19,7 @@
* <http://www.phpdoctrine.org>. * <http://www.phpdoctrine.org>.
*/ */
#namespace Doctrine::DBAL::Schema; #namespace Doctrine\DBAL\Schema;
/** /**
* xxx * xxx
@ -32,16 +32,6 @@
*/ */
class Doctrine_DBAL_Schema_PostgreSqlSchemaManager extends Doctrine_DBAL_Schema_AbstractSchemaManager class Doctrine_DBAL_Schema_PostgreSqlSchemaManager extends Doctrine_DBAL_Schema_AbstractSchemaManager
{ {
/**
* Enter description here...
*
* @param Doctrine_Connection_Pgsql $conn
*/
public function __construct(Doctrine_Connection_Pgsql $conn)
{
$this->_conn = $conn;
}
/** /**
* alter an existing table * alter an existing table
* *

View File

@ -19,7 +19,7 @@
* <http://www.phpdoctrine.org>. * <http://www.phpdoctrine.org>.
*/ */
#namespace Doctrine::DBAL::Schema; #namespace Doctrine\DBAL\Schema;
/** /**
* xxx * xxx
@ -32,11 +32,6 @@
*/ */
class Doctrine_DBAL_Schema_SqliteSchemaManager extends Doctrine_DBAL_Schema_AbstractSchemaManager class Doctrine_DBAL_Schema_SqliteSchemaManager extends Doctrine_DBAL_Schema_AbstractSchemaManager
{ {
public function __construct(Doctrine_Connection_Sqlite $conn)
{
$this->_conn = $conn;
}
/** /**
* lists all databases * lists all databases
* *
@ -48,7 +43,7 @@ class Doctrine_DBAL_Schema_SqliteSchemaManager extends Doctrine_DBAL_Schema_Abst
} }
/** /**
* lists all availible database functions * lists all available database functions
* *
* @return array * @return array
*/ */
@ -371,123 +366,6 @@ class Doctrine_DBAL_Schema_SqliteSchemaManager extends Doctrine_DBAL_Schema_Abst
return implode(', ', $declFields); return implode(', ', $declFields);
} }
/**
* create a new table
*
* @param string $name Name of the database that should be created
* @param array $fields Associative array that contains the definition of each field of the new table
* The indexes of the array entries are the names of the fields of the table an
* the array entry values are associative arrays like those that are meant to be
* passed with the field definitions to get[Type]Declaration() functions.
* array(
* 'id' => array(
* 'type' => 'integer',
* 'unsigned' => 1
* 'notnull' => 1
* 'default' => 0
* ),
* 'name' => array(
* 'type' => 'text',
* 'length' => 12
* ),
* 'password' => array(
* 'type' => 'text',
* 'length' => 12
* )
* );
* @param array $options An associative array of table options:
*
* @return void
*/
public function createTableSql($name, array $fields, array $options = array())
{
if ( ! $name) {
throw new Doctrine_Export_Exception('no valid table name specified');
}
if (empty($fields)) {
throw new Doctrine_Export_Exception('no fields specified for table '.$name);
}
$queryFields = $this->getFieldDeclarationList($fields);
$autoinc = false;
foreach($fields as $field) {
if (isset($field['autoincrement']) && $field['autoincrement'] ||
(isset($field['autoinc']) && $field['autoinc'])) {
$autoinc = true;
break;
}
}
if ( ! $autoinc && isset($options['primary']) && ! empty($options['primary'])) {
$keyColumns = array_values($options['primary']);
$keyColumns = array_map(array($this->_conn, 'quoteIdentifier'), $keyColumns);
$queryFields.= ', PRIMARY KEY('.implode(', ', $keyColumns).')';
}
$name = $this->_conn->quoteIdentifier($name, true);
$sql = 'CREATE TABLE ' . $name . ' (' . $queryFields;
if ($check = $this->getCheckDeclaration($fields)) {
$sql .= ', ' . $check;
}
if (isset($options['checks']) && $check = $this->getCheckDeclaration($options['checks'])) {
$sql .= ', ' . $check;
}
$sql .= ')';
$query[] = $sql;
if (isset($options['indexes']) && ! empty($options['indexes'])) {
foreach ($options['indexes'] as $index => $definition) {
$query[] = $this->createIndexSql($name, $index, $definition);
}
}
return $query;
/**
try {
if ( ! empty($fk)) {
$this->_conn->beginTransaction();
}
$ret = $this->_conn->exec($query);
if ( ! empty($fk)) {
foreach ($fk as $definition) {
$query = 'CREATE TRIGGER doctrine_' . $name . '_cscd_delete '
. 'AFTER DELETE ON ' . $name . ' FOR EACH ROW '
. 'BEGIN '
. 'DELETE FROM ' . $definition['foreignTable'] . ' WHERE ';
$local = (array) $definition['local'];
foreach((array) $definition['foreign'] as $k => $field) {
$query .= $field . ' = old.' . $local[$k] . ';';
}
$query .= 'END;';
$this->_conn->exec($query);
}
$this->_conn->commit();
}
} catch(Doctrine_Exception $e) {
$this->_conn->rollback();
throw $e;
}
*/
}
/** /**
* getAdvancedForeignKeyOptions * getAdvancedForeignKeyOptions
* Return the FOREIGN KEY query section dealing with non-standard options * Return the FOREIGN KEY query section dealing with non-standard options

View File

@ -11,8 +11,7 @@ class Doctrine_DBAL_Types_ArrayType extends Doctrine_DBAL_Types_Type
public function getName() public function getName()
{ {
return 'array'; return 'Array';
} }
} }
?>

View File

@ -0,0 +1,16 @@
<?php
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
/**
* Type that maps a database BIGINT to a PHP string.
*
* @author robo
*/
class Doctrine_DBAL_Types_BigIntType extends Doctrine_DBAL_Types_Type
{
//put your code here
}

View File

@ -30,4 +30,3 @@ class Doctrine_DBAL_Types_BooleanType extends Doctrine_DBAL_Types_Type
} }
} }
?>

View File

@ -0,0 +1,11 @@
<?php
/**
* Type that maps a database CHAR to a PHP string.
*
* @author robo
*/
class CharType {
//put your code here
}

View File

@ -1,17 +1,22 @@
<?php <?php
/** /**
* Type that maps an SQL INT/MEDIUMINT/BIGINT to a PHP integer. * Type that maps an SQL INT to a PHP integer.
* *
*/ */
class Doctrine_DBAL_Types_IntegerType extends Doctrine_DBAL_Types_Type class Doctrine_DBAL_Types_IntegerType extends Doctrine_DBAL_Types_Type
{ {
public function getName() { return "Integer"; }
public function getSqlDeclaration(array $fieldDeclaration, Doctrine_DatabasePlatform $platform) public function getSqlDeclaration(array $fieldDeclaration, Doctrine_DBAL_Platforms_AbstractPlatform $platform)
{ {
return $platform->getIntegerTypeDeclarationSql($fieldDeclaration);
}
public function convertToPHPValue($value)
{
return (int)$value;
} }
} }
?>

View File

@ -0,0 +1,15 @@
<?php
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
/**
* Description of MediumIntType
*
* @author robo
*/
class MediumIntType {
//put your code here
}

View File

@ -0,0 +1,15 @@
<?php
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
/**
* Description of SmallIntType
*
* @author robo
*/
class SmallIntType {
//put your code here
}
?>

View File

@ -1,28 +0,0 @@
<?php
#namespace Doctrine::DBAL::Types;
/**
* Type that maps an SQL VARCHAR to a PHP string.
*
* @since 2.0
*/
class Doctrine_DBAL_Types_StringType extends Doctrine_DBAL_Types_Type
{
public function getSqlDeclaration(array $fieldDeclaration, Doctrine_DatabasePlatform $platform)
{
return $platform->getVarcharDeclaration($fieldDeclaration);
}
public function getDefaultLength(Doctrine_DatabasePlatform $platform)
{
return $platform->getVarcharDefaultLength();
}
public function getName()
{
return 'string';
}
}
?>

View File

@ -7,14 +7,7 @@
*/ */
class Doctrine_DBAL_Types_TextType extends Doctrine_DBAL_Types_Type class Doctrine_DBAL_Types_TextType extends Doctrine_DBAL_Types_Type
{ {
/** /** @override */
* Enter description here...
*
* @param array $fieldDeclaration
* @param Doctrine_DatabasePlatform $platform
* @return unknown
* @override
*/
public function getSqlDeclaration(array $fieldDeclaration, Doctrine_DatabasePlatform $platform) public function getSqlDeclaration(array $fieldDeclaration, Doctrine_DatabasePlatform $platform)
{ {
return $platform->getClobDeclarationSql($fieldDeclaration); return $platform->getClobDeclarationSql($fieldDeclaration);
@ -22,4 +15,3 @@ class Doctrine_DBAL_Types_TextType extends Doctrine_DBAL_Types_Type
} }
?>

View File

@ -0,0 +1,15 @@
<?php
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
/**
* Description of TinyIntType
*
* @author robo
*/
class TinyIntType {
//put your code here
}

View File

@ -8,26 +8,35 @@ abstract class Doctrine_DBAL_Types_Type
{ {
private static $_typeObjects = array(); private static $_typeObjects = array();
private static $_typesMap = array( private static $_typesMap = array(
'integer' => 'Doctrine_DataType_IntegerType', 'integer' => 'Doctrine_DBAL_Types_IntegerType',
'string' => 'Doctrine_DataType_StringType', 'int' => 'Doctrine_DBAL_Types_IntegerType',
'text' => 'Doctrine_DataType_TextType', 'tinyint' => 'Doctrine_DBAL_Types_TinyIntType',
'datetime' => 'Doctrine_DataType_DateTimeType', 'smallint' => 'Doctrine_DBAL_Types_SmallIntType',
'decimal' => 'Doctrine_DataType_DecimalType', 'mediumint' => 'Doctrine_DBAL_Types_MediumIntType',
'double' => 'Doctrine_DataType_DoubleType' 'bigint' => 'Doctrine_DBAL_Types_BigIntType',
'varchar' => 'Doctrine_DBAL_Types_VarcharType',
'text' => 'Doctrine_DBAL_Types_TextType',
'datetime' => 'Doctrine_DBAL_Types_DateTimeType',
'decimal' => 'Doctrine_DBAL_Types_DecimalType',
'double' => 'Doctrine_DBAL_Types_DoubleType'
); );
public function convertToDatabaseValue($value, Doctrine_DBAL_Platforms_AbstractDatabasePlatform $platform) public function convertToDatabaseValue($value, Doctrine_DBAL_Platforms_AbstractPlatform $platform)
{ {
return $value; return $value;
} }
public function convertToObjectValue($value) public function convertToPHPValue($value)
{ {
return $value; return $value;
} }
abstract public function getDefaultLength(Doctrine_DBAL_Platforms_AbstractDatabasePlatform $platform); public function getDefaultLength(Doctrine_DBAL_Platforms_AbstractPlatform $platform)
abstract public function getSqlDeclaration(array $fieldDeclaration, Doctrine_DBAL_Platforms_AbstractDatabasePlatform $platform); {
return null;
}
abstract public function getSqlDeclaration(array $fieldDeclaration, Doctrine_DBAL_Platforms_AbstractPlatform $platform);
abstract public function getName(); abstract public function getName();
/** /**
@ -35,7 +44,7 @@ abstract class Doctrine_DBAL_Types_Type
* Type instances are implemented as flyweights. * Type instances are implemented as flyweights.
* *
* @param string $name The name of the type (as returned by getName()). * @param string $name The name of the type (as returned by getName()).
* @return Doctrine::DBAL::Types::Type * @return Doctrine\DBAL\Types\Type
*/ */
public static function getType($name) public static function getType($name)
{ {

View File

@ -0,0 +1,27 @@
<?php
#namespace Doctrine\DBAL\Types;
/**
* Type that maps an SQL VARCHAR to a PHP string.
*
* @since 2.0
*/
class Doctrine_DBAL_Types_VarcharType extends Doctrine_DBAL_Types_Type
{
/** @override */
public function getSqlDeclaration(array $fieldDeclaration, Doctrine_DBAL_Platforms_AbstractPlatform $platform)
{
return $platform->getVarcharDeclarationSql($fieldDeclaration);
}
/** @override */
public function getDefaultLength(Doctrine_DBAL_Platforms_AbstractPlatform $platform)
{
return $platform->getVarcharDefaultLength();
}
/** @override */
public function getName() { return 'Varchar'; }
}

View File

@ -429,12 +429,12 @@ class Doctrine_ORM_EntityManager
/** /**
* Saves the given entity, persisting it's state. * Saves the given entity, persisting it's state.
* *
* @param Doctrine\ORM\Entity $entity * @param object $object
*/ */
public function save(Doctrine_ORM_Entity $entity) public function save($object)
{ {
$this->_errorIfNotActiveOrClosed(); $this->_errorIfNotActiveOrClosed();
$this->_unitOfWork->save($entity); $this->_unitOfWork->save($object);
if ($this->_flushMode == self::FLUSHMODE_IMMEDIATE) { if ($this->_flushMode == self::FLUSHMODE_IMMEDIATE) {
$this->flush(); $this->flush();
} }
@ -496,7 +496,7 @@ class Doctrine_ORM_EntityManager
if ($customRepositoryClassName !== null) { if ($customRepositoryClassName !== null) {
$repository = new $customRepositoryClassName($entityName, $metadata); $repository = new $customRepositoryClassName($entityName, $metadata);
} else { } else {
$repository = new Doctrine_ORM_EntityRepository($entityName, $metadata); $repository = new Doctrine_ORM_EntityRepository($this, $metadata);
} }
$this->_repositories[$entityName] = $repository; $this->_repositories[$entityName] = $repository;
@ -506,11 +506,11 @@ class Doctrine_ORM_EntityManager
/** /**
* Checks if the instance is managed by the EntityManager. * Checks if the instance is managed by the EntityManager.
* *
* @param Doctrine\ORM\Entity $entity * @param object $entity
* @return boolean TRUE if this EntityManager currently manages the given entity * @return boolean TRUE if this EntityManager currently manages the given entity
* (and has it in the identity map), FALSE otherwise. * (and has it in the identity map), FALSE otherwise.
*/ */
public function contains(Doctrine_ORM_Entity $entity) public function contains($entity)
{ {
return $this->_unitOfWork->isInIdentityMap($entity) && return $this->_unitOfWork->isInIdentityMap($entity) &&
! $this->_unitOfWork->isRegisteredRemoved($entity); ! $this->_unitOfWork->isRegisteredRemoved($entity);
@ -543,8 +543,8 @@ class Doctrine_ORM_EntityManager
*/ */
private function _errorIfNotActiveOrClosed() private function _errorIfNotActiveOrClosed()
{ {
if ( ! $this->isActive() || $this->_closed) { if ($this->_closed) {
throw Doctrine_EntityManagerException::notActiveOrClosed($this->_name); throw Doctrine_ORM_Exceptions_EntityManagerException::notActiveOrClosed($this->_name);
} }
} }

View File

@ -38,10 +38,10 @@ class Doctrine_ORM_EntityRepository
protected $_em; protected $_em;
protected $_classMetadata; protected $_classMetadata;
public function __construct($entityName, Doctrine_ORM_Mapping_ClassMetadata $classMetadata) public function __construct($em, Doctrine_ORM_Mapping_ClassMetadata $classMetadata)
{ {
$this->_entityName = $entityName; $this->_entityName = $classMetadata->getClassName();
$this->_em = $classMetadata->getConnection(); $this->_em = $em;
$this->_classMetadata = $classMetadata; $this->_classMetadata = $classMetadata;
} }
@ -77,7 +77,6 @@ class Doctrine_ORM_EntityRepository
* @param $id The identifier. * @param $id The identifier.
* @param int $hydrationMode The hydration mode to use. * @param int $hydrationMode The hydration mode to use.
* @return mixed Array or Doctrine_Entity or false if no result * @return mixed Array or Doctrine_Entity or false if no result
* @todo Remove. Move to EntityRepository.
*/ */
public function find($id, $hydrationMode = null) public function find($id, $hydrationMode = null)
{ {
@ -94,7 +93,10 @@ class Doctrine_ORM_EntityRepository
$keys = $this->_classMetadata->getIdentifier(); $keys = $this->_classMetadata->getIdentifier();
} }
//TODO: check identity map? // Check identity map first
if ($entity = $this->_em->getUnitOfWork()->tryGetById($id, $this->_classMetadata->getRootClassName())) {
return $entity; // Hit!
}
return $this->_createQuery() return $this->_createQuery()
->where(implode(' = ? AND ', $keys) . ' = ?') ->where(implode(' = ? AND ', $keys) . ' = ?')

View File

@ -0,0 +1,142 @@
<?php
/*
* $Id: Export.php 4805 2008-08-25 19:11:58Z subzero2000 $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.org>.
*/
#namespace Doctrine\ORM\Export;
/**
* The ClassExporter can generate database schemas/structures from ClassMetadata
* class descriptors.
*
* @package Doctrine
* @subpackage Export
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
* @author Roman Borschel <roman@code-factory.org>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision: 4805 $
*/
class Doctrine_ORM_Export_ClassExporter
{
/** The SchemaManager */
private $_sm;
/** The EntityManager */
private $_em;
public function __construct(Doctrine_ORM_EntityManager $em)
{
$this->_em = $em;
$this->_sm = $em->getConnection()->getSchemaManager();
}
/**
* Exports entity classes to a schema.
*
* FIXME: This method is a big huge hack. The sql needs to be executed in the correct order. I have some stupid logic to
* make sure they are in the right order.
*
* @param array $classes
* @return void
*/
public function exportClasses(array $classes)
{
//TODO: order them
foreach ($classes as $class) {
$columns = array();
$options = array();
foreach ($class->getFieldMappings() as $fieldName => $mapping) {
$column = array();
$column['name'] = $mapping['columnName'];
$column['type'] = $mapping['type'];
$column['length'] = $mapping['length'];
if ($class->isIdentifier($fieldName)) {
if ($class->isIdGeneratorIdentity()) {
$column['autoincrement'] = true;
}
}
$columns[$mapping['columnName']] = $column;
}
$this->_sm->createTable($class->getTableName(), $columns, $options);
}
}
/**
* exportClassesSql
* method for exporting entity classes to a schema
*
* @throws Doctrine_Connection_Exception if some error other than Doctrine::ERR_ALREADY_EXISTS
* occurred during the create table operation
* @param array $classes
* @return void
*/
public function exportClassesSql(array $classes)
{
$models = Doctrine::filterInvalidModels($classes);
$sql = array();
$finishedClasses = array();
foreach ($models as $name) {
if (in_array($name, $finishedClasses)) {
continue;
}
$classMetadata = $this->conn->getClassMetadata($name);
// In Class Table Inheritance we have to make sure that ALL tables of parent classes
// are exported, too as soon as ONE table is exported, because the data of one class is stored
// across many tables.
if ($classMetadata->getInheritanceType() == Doctrine::INHERITANCE_TYPE_JOINED) {
$parents = $classMetadata->getParentClasses();
foreach ($parents as $parent) {
$data = $classMetadata->getConnection()->getClassMetadata($parent)->getExportableFormat();
$query = $this->conn->export->createTableSql($data['tableName'], $data['columns'], $data['options']);
$sql = array_merge($sql, (array) $query);
$finishedClasses[] = $parent;
}
}
$data = $classMetadata->getExportableFormat();
$query = $this->conn->export->createTableSql($data['tableName'], $data['columns'], $data['options']);
if (is_array($query)) {
$sql = array_merge($sql, $query);
} else {
$sql[] = $query;
}
if ($classMetadata->getAttribute(Doctrine::ATTR_EXPORT) & Doctrine::EXPORT_PLUGINS) {
$sql = array_merge($sql, $this->exportGeneratorsSql($classMetadata));
}
}
$sql = array_unique($sql);
rsort($sql);
return $sql;
}
}

View File

@ -1,311 +0,0 @@
<?php
/*
* $Id: Export.php 4805 2008-08-25 19:11:58Z subzero2000 $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.org>.
*/
#namespace Doctrine::DBAL::Export;
/**
* Doctrine_Export
*
* @package Doctrine
* @subpackage Export
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.phpdoctrine.org
* @since 1.0
* @version $Revision: 4805 $
* @todo Rename to ExportManager. Subclasses: MySqlExportManager, PgSqlExportManager etc.
*/
class Doctrine_Export extends Doctrine_Connection_Module
{
/**
* exportSchema
* method for exporting Doctrine_Entity classes to a schema
*
* if the directory parameter is given this method first iterates
* recursively trhough the given directory in order to find any model classes
*
* Then it iterates through all declared classes and creates tables for the ones
* that extend Doctrine_Entity and are not abstract classes
*
* @throws Doctrine_Connection_Exception if some error other than Doctrine::ERR_ALREADY_EXISTS
* occurred during the create table operation
* @param string $directory optional directory parameter
* @return void
*/
public function exportSchema($directory = null)
{
if ($directory !== null) {
$models = Doctrine::loadModels($directory);
} else {
$models = Doctrine::getLoadedModels();
}
$this->exportClasses($models);
}
/**
* exportClasses
*
* FIXME: This method is a big huge hack. The sql needs to be executed in the correct order. I have some stupid logic to
* make sure they are in the right order.
*
* method for exporting Doctrine_Entity classes to a schema
*
* @throws Doctrine_Connection_Exception if some error other than Doctrine::ERR_ALREADY_EXISTS
* occurred during the create table operation
* @param array $classes
* @return void
* @todo ORM stuff
*/
public function exportClasses(array $classes)
{
$connections = array();
foreach ($classes as $class) {
$record = new $class();
$connection = $record->getTable()->getConnection();
$connectionName = Doctrine_Manager::getInstance()->getConnectionName($connection);
if ( ! isset($connections[$connectionName])) {
$connections[$connectionName] = array(
'create_tables' => array(),
'create_sequences' => array(),
'alters' => array()
);
}
$sql = $this->exportClassesSql(array($class));
// Build array of all the creates
// We need these to happen first
foreach ($sql as $key => $query) {
if (strstr($query, 'CREATE TABLE')) {
$connections[$connectionName]['create_tables'][] = $query;
unset($sql[$key]);
}
if (strstr($query, 'CREATE SEQUENCE')) {
$connections[$connectionName]['create_sequences'][] = $query;
unset($sql[$key]);
}
}
$connections[$connectionName]['alters'] = array_merge($connections[$connectionName]['alters'], $sql);
}
// Loop over all the sql again to merge the creates and alters in to the same array, but so that the alters are at the bottom
$build = array();
foreach ($connections as $connectionName => $sql) {
$build[$connectionName] = array_unique(array_merge($sql['create_tables'], $sql['create_sequences'], $sql['alters']));
}
foreach ($build as $connectionName => $sql) {
$connection = Doctrine_Manager::getInstance()->getConnection($connectionName);
$connection->beginTransaction();
foreach ($sql as $query) {
try {
$connection->exec($query);
} catch (Doctrine_Connection_Exception $e) {
// we only want to silence table already exists errors
if ($e->getPortableCode() !== Doctrine::ERR_ALREADY_EXISTS) {
$connection->rollback();
throw new Doctrine_Export_Exception($e->getMessage() . '. Failing Query: ' . $query);
}
}
}
$connection->commit();
}
}
/**
* exportClassesSql
* method for exporting Doctrine_Entity classes to a schema
*
* @throws Doctrine_Connection_Exception if some error other than Doctrine::ERR_ALREADY_EXISTS
* occurred during the create table operation
* @param array $classes
* @return void
* @todo package:orm
*/
public function exportClassesSql(array $classes)
{
$models = Doctrine::filterInvalidModels($classes);
$sql = array();
$finishedClasses = array();
foreach ($models as $name) {
if (in_array($name, $finishedClasses)) {
continue;
}
$classMetadata = $this->conn->getClassMetadata($name);
// In Class Table Inheritance we have to make sure that ALL tables of parent classes
// are exported, too as soon as ONE table is exported, because the data of one class is stored
// across many tables.
if ($classMetadata->getInheritanceType() == Doctrine::INHERITANCE_TYPE_JOINED) {
$parents = $classMetadata->getParentClasses();
foreach ($parents as $parent) {
$data = $classMetadata->getConnection()->getClassMetadata($parent)->getExportableFormat();
$query = $this->conn->export->createTableSql($data['tableName'], $data['columns'], $data['options']);
$sql = array_merge($sql, (array) $query);
$finishedClasses[] = $parent;
}
}
$data = $classMetadata->getExportableFormat();
$query = $this->conn->export->createTableSql($data['tableName'], $data['columns'], $data['options']);
if (is_array($query)) {
$sql = array_merge($sql, $query);
} else {
$sql[] = $query;
}
if ($classMetadata->getAttribute(Doctrine::ATTR_EXPORT) & Doctrine::EXPORT_PLUGINS) {
$sql = array_merge($sql, $this->exportGeneratorsSql($classMetadata));
}
}
$sql = array_unique($sql);
rsort($sql);
return $sql;
}
/**
* fetches all generators recursively for given table
*
* @param Doctrine_Table $table table object to retrieve the generators from
* @return array an array of Doctrine_Record_Generator objects
* @todo package:orm
*/
public function getAllGenerators(Doctrine_ClassMetadata $table)
{
$generators = array();
foreach ($table->getGenerators() as $name => $generator) {
if ($generator === null) {
continue;
}
$generators[] = $generator;
$generatorTable = $generator->getTable();
if ($generatorTable instanceof Doctrine_Table) {
$generators = array_merge($generators, $this->getAllGenerators($generatorTable));
}
}
return $generators;
}
/**
* exportGeneratorsSql
* exports plugin tables for given table
*
* @param Doctrine_Table $table the table in which the generators belong to
* @return array an array of sql strings
* @todo package:orm
*/
public function exportGeneratorsSql(Doctrine_ClassMetadata $class)
{
$sql = array();
foreach ($this->getAllGenerators($class) as $name => $generator) {
$table = $generator->getTable();
// Make sure plugin has a valid table
if ($table instanceof Doctrine_Table) {
$data = $table->getExportableFormat();
$query = $this->conn->export->createTableSql($data['tableName'], $data['columns'], $data['options']);
$sql = array_merge($sql, (array) $query);
}
}
return $sql;
}
/**
* exportSql
* returns the sql for exporting Doctrine_Entity classes to a schema
*
* if the directory parameter is given this method first iterates
* recursively trhough the given directory in order to find any model classes
*
* Then it iterates through all declared classes and creates tables for the ones
* that extend Doctrine_Entity and are not abstract classes
*
* @throws Doctrine_Connection_Exception if some error other than Doctrine::ERR_ALREADY_EXISTS
* occurred during the create table operation
* @param string $directory optional directory parameter
* @return void
*/
public function exportSql($directory = null)
{
if ($directory !== null) {
$models = Doctrine::loadModels($directory);
} else {
$models = Doctrine::getLoadedModels();
}
return $this->exportClassesSql($models);
}
/**
* exportTable
* exports given table into database based on column and option definitions
*
* @throws Doctrine_Connection_Exception if some error other than Doctrine::ERR_ALREADY_EXISTS
* occurred during the create table operation
* @return boolean whether or not the export operation was successful
* false if table already existed in the database
* @todo ORM stuff
*/
public function exportTable(Doctrine_ClassMetadata $metadata)
{
/**
TODO: maybe there should be portability option for the following check
if ( ! Doctrine::isValidClassname($table->getOption('declaringClass')->getName())) {
throw new Doctrine_Export_Exception('Class name not valid.');
}
*/
try {
$data = $metadata->getExportableFormat();
$this->conn->export->createTable($data['tableName'], $data['columns'], $data['options']);
} catch (Doctrine_Connection_Exception $e) {
// we only want to silence table already exists errors
if ($e->getPortableCode() !== Doctrine::ERR_ALREADY_EXISTS) {
throw $e;
}
}
}
}

View File

@ -617,6 +617,8 @@ class Doctrine_ORM_Mapping_ClassMetadata
throw Doctrine_ORM_Exceptions_MappingException::missingType(); throw Doctrine_ORM_Exceptions_MappingException::missingType();
} }
$mapping['type'] = Doctrine_DBAL_Types_Type::getType($mapping['type']);
// Complete fieldName and columnName mapping // Complete fieldName and columnName mapping
if ( ! isset($mapping['columnName'])) { if ( ! isset($mapping['columnName'])) {
$mapping['columnName'] = $mapping['fieldName']; $mapping['columnName'] = $mapping['fieldName'];

View File

@ -2,14 +2,10 @@
#namespace Doctrine\ORM\Mapping\Driver; #namespace Doctrine\ORM\Mapping\Driver;
/* Addendum annotation API */ /* Addendum annotation reflection extensions */
require_once dirname(__FILE__) . '/addendum/annotations.php'; if ( ! class_exists('Addendum', false)) {
Addendum::setRawMode(false); require_once dirname(__FILE__) . '/addendum/annotations.php';
Addendum::setParsedAnnotations(array('DoctrineEntity', 'DoctrineInheritanceType', }
'DoctrineDiscriminatorColumn', 'DoctrineDiscriminatorMap',
'DoctrineSubClasses', 'DoctrineTransient', 'DoctrineId',
'DoctrineIdGenerator', 'DoctrineColumn', 'DoctrineOneToOne',
'DoctrineOneToMany', 'DoctrineManyToOne', 'DoctrineManyToMany'));
/** /**
* The AnnotationDriver reads the mapping metadata from docblock annotations. * The AnnotationDriver reads the mapping metadata from docblock annotations.
@ -122,7 +118,7 @@ final class DoctrineColumn extends Annotation {
public $type; public $type;
public $length; public $length;
public $unique; public $unique;
public $notnull; public $nullable;
} }
final class DoctrineOneToOne extends Annotation { final class DoctrineOneToOne extends Annotation {
public $targetEntity; public $targetEntity;

View File

@ -75,7 +75,7 @@ class AnnotationsBuilder {
$data = $this->parse($targetReflection); $data = $this->parse($targetReflection);
$annotations = array(); $annotations = array();
foreach($data as $class => $parameters) { foreach($data as $class => $parameters) {
if(Addendum::parses($class)) { if(is_subclass_of($class, 'Annotation')) {
foreach($parameters as $params) { foreach($parameters as $params) {
$annotationReflection = new ReflectionClass($class); $annotationReflection = new ReflectionClass($class);
$annotations[$class][] = $annotationReflection->newInstance($params, $targetReflection); $annotations[$class][] = $annotationReflection->newInstance($params, $targetReflection);
@ -296,7 +296,7 @@ class ReflectionAnnotatedProperty extends ReflectionProperty {
class Addendum { class Addendum {
private static $rawMode; private static $rawMode;
private static $parsedAnnotations; private static $ignored;
public static function getDocComment($reflection) { public static function getDocComment($reflection) {
if(self::checkRawDocCommentParsingNeeded()) { if(self::checkRawDocCommentParsingNeeded()) {
@ -324,12 +324,12 @@ class Addendum {
self::$rawMode = $enabled; self::$rawMode = $enabled;
} }
public static function setParsedAnnotations(array $annotations) { public static function ignore(array $annotations) {
self::$parsedAnnotations = array_combine($annotations, array_fill(0, count($annotations), true)); self::$ignored = array_combine($annotations, array_fill(0, count($annotations), true));
} }
public static function parses($annotation) { public static function ignores($annotation) {
return isset(self::$parsedAnnotations[$annotation]); return isset(self::$ignored[$annotation]);
} }
} }

View File

@ -66,11 +66,6 @@ abstract class Doctrine_ORM_Persisters_AbstractEntityPersister
*/ */
protected $_em; protected $_em;
/**
* Null object.
*/
//private $_nullObject;
/** /**
* Initializes a new instance of a class derived from AbstractEntityPersister * Initializes a new instance of a class derived from AbstractEntityPersister
* that uses the given EntityManager and persists instances of the class described * that uses the given EntityManager and persists instances of the class described
@ -238,48 +233,36 @@ abstract class Doctrine_ORM_Persisters_AbstractEntityPersister
protected function _prepareData($entity, array &$result, $isInsert = false) protected function _prepareData($entity, array &$result, $isInsert = false)
{ {
foreach ($this->_em->getUnitOfWork()->getDataChangeSet($entity) as $field => $change) { foreach ($this->_em->getUnitOfWork()->getDataChangeSet($entity) as $field => $change) {
list ($oldVal, $newVal) = each($change); if (is_array($change)) {
list ($oldVal, $newVal) = each($change);
} else {
$oldVal = null;
$newVal = $change;
}
$type = $this->_classMetadata->getTypeOfField($field); $type = $this->_classMetadata->getTypeOfField($field);
$columnName = $this->_classMetadata->getColumnName($field); $columnName = $this->_classMetadata->getColumnName($field);
if (is_null($newVal)) { if ($this->_classMetadata->hasAssociation($field)) {
$result[$columnName] = null;
} else if (is_object($newVal)) {
$assocMapping = $this->_classMetadata->getAssociationMapping($field); $assocMapping = $this->_classMetadata->getAssociationMapping($field);
if ( ! $assocMapping->isOneToOne() || $assocMapping->isInverseSide()) { if ( ! $assocMapping->isOneToOne() || $assocMapping->isInverseSide()) {
//echo "NOT TO-ONE OR INVERSE!"; //echo "NOT TO-ONE OR INVERSE!";
continue; continue;
} }
foreach ($assocMapping->getSourceToTargetKeyColumns() as $sourceColumn => $targetColumn) { foreach ($assocMapping->getSourceToTargetKeyColumns() as $sourceColumn => $targetColumn) {
//TODO: What if both join columns (local/foreign) are just db-only
// columns (no fields in models) ? Currently we assume the foreign column
// is mapped to a field in the foreign entity.
//TODO: throw exc if field not set //TODO: throw exc if field not set
$otherClass = $this->_em->getClassMetadata($assocMapping->getTargetEntityName()); $otherClass = $this->_em->getClassMetadata($assocMapping->getTargetEntityName());
$result[$sourceColumn] = $otherClass->getReflectionProperty( $result[$sourceColumn] = $otherClass->getReflectionProperty(
$otherClass->getFieldName($targetColumn))->getValue($newVal); $otherClass->getFieldName($targetColumn))->getValue($newVal);
} }
} else if (is_null($newVal)) {
$result[$columnName] = null;
} else { } else {
switch ($type) { $result[$columnName] = $type->convertToDatabaseValue($newVal, $this->_conn->getDatabasePlatform());
case 'array':
case 'object':
$result[$columnName] = serialize($newVal);
break;
case 'gzip':
$result[$columnName] = gzcompress($newVal, 5);
break;
case 'boolean':
$result[$columnName] = $this->_em->getConnection()->convertBooleans($newVal);
break;
default:
$result[$columnName] = $newVal;
}
} }
/*$result[$columnName] = $type->convertToDatabaseValue(
$newVal, $this->_em->getConnection()->getDatabasePlatform());*/
} }
// Populate the discriminator column on insert in Single & Class Table Inheritance // Populate the discriminator column on insert in JOINED & SINGLE_TABLE inheritance
if ($isInsert && ($this->_classMetadata->isInheritanceTypeJoined() || if ($isInsert && ($this->_classMetadata->isInheritanceTypeJoined() ||
$this->_classMetadata->isInheritanceTypeSingleTable())) { $this->_classMetadata->isInheritanceTypeSingleTable())) {
$discColumn = $this->_classMetadata->getDiscriminatorColumn(); $discColumn = $this->_classMetadata->getDiscriminatorColumn();

View File

@ -284,7 +284,8 @@ class Doctrine_ORM_UnitOfWork
$class = $this->_em->getClassMetadata($className); $class = $this->_em->getClassMetadata($className);
foreach ($entities as $entity) { foreach ($entities as $entity) {
$oid = spl_object_hash($entity); $oid = spl_object_hash($entity);
if ($this->getEntityState($entity) == self::STATE_MANAGED) { $state = $this->getEntityState($entity);
if ($state == self::STATE_MANAGED || $state == self::STATE_NEW) {
if ( ! $class->isInheritanceTypeNone()) { if ( ! $class->isInheritanceTypeNone()) {
$class = $this->_em->getClassMetadata(get_class($entity)); $class = $this->_em->getClassMetadata(get_class($entity));
} }
@ -294,7 +295,7 @@ class Doctrine_ORM_UnitOfWork
$actualData[$name] = $refProp->getValue($entity); $actualData[$name] = $refProp->getValue($entity);
} }
if ( ! isset($this->_originalEntityData[$oid])) { if ($state == self::STATE_NEW) {
$this->_dataChangeSets[$oid] = $actualData; $this->_dataChangeSets[$oid] = $actualData;
} else { } else {
$originalData = $this->_originalEntityData[$oid]; $originalData = $this->_originalEntityData[$oid];
@ -904,7 +905,6 @@ class Doctrine_ORM_UnitOfWork
$class = $this->_em->getClassMetadata(get_class($entity)); $class = $this->_em->getClassMetadata(get_class($entity));
foreach ($class->getAssociationMappings() as $assocMapping) { foreach ($class->getAssociationMappings() as $assocMapping) {
if ( ! $assocMapping->isCascadeSave()) { if ( ! $assocMapping->isCascadeSave()) {
echo "NOT cascade " . $assocMapping->getSourceFieldName();
continue; continue;
} }
$relatedEntities = $class->getReflectionProperty($assocMapping->getSourceFieldName()) $relatedEntities = $class->getReflectionProperty($assocMapping->getSourceFieldName())
@ -1157,6 +1157,18 @@ class Doctrine_ORM_UnitOfWork
{ {
return $this->_entityIdentifiers[spl_object_hash($entity)]; return $this->_entityIdentifiers[spl_object_hash($entity)];
} }
/**
*
*/
public function tryGetById($id, $rootClassName)
{
$idHash = $this->getIdentifierHash((array)$id);
if (isset($this->_identityMap[$rootClassName][$idHash])) {
return $this->_identityMap[$rootClassName][$idHash];
}
return false;
}
} }

View File

@ -0,0 +1,35 @@
<?php
if (!defined('PHPUnit_MAIN_METHOD')) {
define('PHPUnit_MAIN_METHOD', 'Orm_Functional_AllTests::main');
}
require_once 'lib/DoctrineTestInit.php';
// Suites
require_once 'Orm/Functional/Ticket/AllTests.php';
// Tests
require_once 'Orm/Functional/BasicCRUDTest.php';
class Orm_Functional_AllTests
{
public static function main()
{
PHPUnit_TextUI_TestRunner::run(self::suite());
}
public static function suite()
{
$suite = new Doctrine_OrmFunctionalTestSuite('Doctrine Orm Functional');
$suite->addTestSuite('Orm_Functional_BasicCRUDTest');
$suite->addTest(Orm_Functional_Ticket_AllTests::suite());
return $suite;
}
}
if (PHPUnit_MAIN_METHOD == 'Orm_Functional_AllTests::main') {
Orm_Functional_AllTests::main();
}

View File

@ -0,0 +1,38 @@
<?php
require_once 'lib/DoctrineTestInit.php';
/**
* Description of BasicCRUDTest
*
* @author robo
*/
class Orm_Functional_BasicCRUDTest extends Doctrine_OrmFunctionalTestCase {
public function testFoo() {
$em = $this->_getEntityManager();
$exporter = new Doctrine_ORM_Export_ClassExporter($em);
$exporter->exportClasses(array($em->getClassMetadata('CmsUser')));
// Create
$user = new CmsUser;
$user->name = 'romanb';
$em->save($user);
$this->assertTrue(is_numeric($user->id));
$this->assertTrue($em->contains($user));
$user2 = new CmsUser;
$user2->name = 'jwage';
$em->save($user2);
$this->assertTrue(is_numeric($user2->id));
$this->assertTrue($em->contains($user2));
// Read
$user3 = $em->find('CmsUser', $user->id);
$this->assertTrue($user === $user3);
$user4 = $em->find('CmsUser', $user2->id);
$this->assertTrue($user2 === $user4);
}
}

View File

@ -0,0 +1,10 @@
<?php
require_once 'lib/DoctrineTestInit.php';
class Orm_Functional_Ticket_1Test extends Doctrine_OrmTestCase
{
public function testTest()
{
$this->assertEquals(0, 0);
}
}

View File

@ -0,0 +1,30 @@
<?php
if (!defined('PHPUnit_MAIN_METHOD')) {
define('PHPUnit_MAIN_METHOD', 'Orm_Functional_Ticket_AllTests::main');
}
require_once 'lib/DoctrineTestInit.php';
// Tests
require_once 'Orm/Functional/Ticket/1Test.php';
class Orm_Functional_Ticket_AllTests
{
public static function main()
{
PHPUnit_TextUI_TestRunner::run(self::suite());
}
public static function suite()
{
$suite = new Doctrine_TestSuite('Doctrine Orm');
$suite->addTestSuite('Orm_Functional_Ticket_1Test');
return $suite;
}
}
if (PHPUnit_MAIN_METHOD == 'Orm_Functional_Ticket_AllTests::main') {
Ticket_AllTests::main();
}

View File

@ -56,19 +56,18 @@ class Doctrine_OrmFunctionalTestCase extends Doctrine_OrmTestCase
} }
$fixture = self::$_fixtures[$uniqueName]; $fixture = self::$_fixtures[$uniqueName];
$this->_loadedFixtures[] = $fixture['model']; $this->_loadedFixtures[] = $fixture['table'];
$em = $this->sharedFixture['em']; $conn = $this->sharedFixture['conn'];
$classMetadata = $em->getClassMetadata($fixture['model']); $tableName = $fixture['table'];
$tableName = $classMetadata->getTableName();
if ( ! in_array($tableName, self::$_exportedTables)) { if ( ! in_array($tableName, self::$_exportedTables)) {
$em->getConnection()->getSchemaManager()->exportClasses(array($fixture['model'])); $conn->getSchemaManager()->exportClasses(array($fixture['model']));
self::$_exportedTables[] = $tableName; self::$_exportedTables[] = $tableName;
} }
foreach ($fixture['rows'] as $row) { foreach ($fixture['rows'] as $row) {
$em->getConnection()->insert($tableName, $row); $conn->insert($tableName, $row);
} }
} }
@ -100,9 +99,23 @@ class Doctrine_OrmFunctionalTestCase extends Doctrine_OrmTestCase
*/ */
protected function tearDown() protected function tearDown()
{ {
$em = $this->sharedFixture['em']; $conn = $this->sharedFixture['conn'];
foreach (array_reverse($this->_loadedFixtures) as $model) { foreach (array_reverse($this->_loadedFixtures) as $table) {
$conn->exec("DELETE FROM " . $em->getClassMetadata($model)->getTableName()); $conn->exec("DELETE FROM " . $table);
} }
} }
protected function setUp()
{
if ( ! isset($this->sharedFixture['conn'])) {
$this->sharedFixture['conn'] = Doctrine_TestUtil::getConnection();
}
}
protected function _getEntityManager($config = null, $eventManager = null) {
$config = new Doctrine_ORM_Configuration();
$eventManager = new Doctrine_Common_EventManager();
$conn = $this->sharedFixture['conn'];
return Doctrine_ORM_EntityManager::create($conn, 'em', $config, $eventManager);
}
} }

View File

@ -25,6 +25,27 @@ class Doctrine_DatabasePlatformMock extends Doctrine_DBAL_Platforms_AbstractPlat
return $this->_prefersIdentityColumns; return $this->_prefersIdentityColumns;
} }
/** @override */
public function getIntegerTypeDeclarationSql(array $field) {}
/** @override */
public function getBigIntTypeDeclarationSql(array $field) {}
/** @override */
public function getTinyIntTypeDeclarationSql(array $field) {}
/** @override */
public function getSmallIntTypeDeclarationSql(array $field) {}
/** @override */
public function getMediumIntTypeDeclarationSql(array $field) {}
/** @override */
protected function _getCommonIntegerTypeDeclarationSql(array $columnDef) {}
/** @override */
public function getVarcharDeclarationSql(array $field) {}
/* MOCK API */ /* MOCK API */
public function setPrefersIdentityColumns($bool) public function setPrefersIdentityColumns($bool)

View File

@ -5,7 +5,7 @@
class Doctrine_DriverConnectionMock implements Doctrine_DBAL_Driver_Connection class Doctrine_DriverConnectionMock implements Doctrine_DBAL_Driver_Connection
{ {
public function prepare($prepareString) {} public function prepare($prepareString) {}
public function query($queryString) {} public function query() {}
public function quote($input) {} public function quote($input) {}
public function exec($statement) {} public function exec($statement) {}
public function lastInsertId() {} public function lastInsertId() {}

View File

@ -14,11 +14,11 @@ class CmsArticle
*/ */
public $id; public $id;
/** /**
* @DoctrineColumn(type="string", length=255) * @DoctrineColumn(type="varchar", length=255)
*/ */
public $topic; public $topic;
/** /**
* @DoctrineColumn(type="string") * @DoctrineColumn(type="varchar")
*/ */
public $text; public $text;
/** /**

View File

@ -14,11 +14,11 @@ class CmsComment
*/ */
public $id; public $id;
/** /**
* @DoctrineColumn(type="string", length=255) * @DoctrineColumn(type="varchar", length=255)
*/ */
public $topic; public $topic;
/** /**
* @DoctrineColumn(type="string") * @DoctrineColumn(type="varchar")
*/ */
public $text; public $text;
/** /**

View File

@ -6,7 +6,7 @@
class CmsPhonenumber implements Doctrine_ORM_Entity class CmsPhonenumber implements Doctrine_ORM_Entity
{ {
/** /**
* @DoctrineColumn(type="string", length=50) * @DoctrineColumn(type="varchar", length=50)
* @DoctrineId * @DoctrineId
*/ */
public $phonenumber; public $phonenumber;

View File

@ -14,15 +14,15 @@ class CmsUser
*/ */
public $id; public $id;
/** /**
* @DoctrineColumn(type="string", length=50) * @DoctrineColumn(type="varchar", length=50)
*/ */
public $status; public $status;
/** /**
* @DoctrineColumn(type="string", length=255) * @DoctrineColumn(type="varchar", length=255)
*/ */
public $username; public $username;
/** /**
* @DoctrineColumn(type="string", length=255) * @DoctrineColumn(type="varchar", length=255)
*/ */
public $name; public $name;
/** /**

View File

@ -17,7 +17,7 @@ class ForumCategory
*/ */
public $position; public $position;
/** /**
* @DoctrineColumn(type="string", length=255) * @DoctrineColumn(type="varchar", length=255)
*/ */
public $name; public $name;
/** /**

View File

@ -14,7 +14,7 @@ class ForumEntry
*/ */
public $id; public $id;
/** /**
* @DoctrineColumn(type="string", length=50) * @DoctrineColumn(type="varchar", length=50)
*/ */
public $topic; public $topic;
} }

View File

@ -7,7 +7,7 @@
/** /**
* @DoctrineEntity * @DoctrineEntity
* @DoctrineInheritanceType("joined") * @DoctrineInheritanceType("joined")
* @DoctrineDiscriminatorColumn(name="dtype", type="string", length=20) * @DoctrineDiscriminatorColumn(name="dtype", type="varchar", length=20)
* @DoctrineDiscriminatorMap({"user" = "ForumUser", "admin" = "ForumAdministrator"}) * @DoctrineDiscriminatorMap({"user" = "ForumUser", "admin" = "ForumAdministrator"})
* @DoctrineSubclasses({"ForumAdministrator"}) * @DoctrineSubclasses({"ForumAdministrator"})
*/ */
@ -20,7 +20,7 @@ class ForumUser
*/ */
public $id; public $id;
/** /**
* @DoctrineColumn(type="string", length=50) * @DoctrineColumn(type="varchar", length=50)
*/ */
public $username; public $username;
/** /**