TableMap.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713
  1. <?php
  2. /**
  3. * This file is part of the Propel package.
  4. * For the full copyright and license information, please view the LICENSE
  5. * file that was distributed with this source code.
  6. *
  7. * @license MIT License
  8. */
  9. /**
  10. * TableMap is used to model a table in a database.
  11. *
  12. * GENERAL NOTE
  13. * ------------
  14. * The propel.map classes are abstract building-block classes for modeling
  15. * the database at runtime. These classes are similar (a lite version) to the
  16. * propel.engine.database.model classes, which are build-time modeling classes.
  17. * These classes in themselves do not do any database metadata lookups.
  18. *
  19. * @author Hans Lellelid <hans@xmpl.org> (Propel)
  20. * @author John D. McNally <jmcnally@collab.net> (Torque)
  21. * @author Daniel Rall <dlr@finemaltcoding.com> (Torque)
  22. * @version $Revision: 1612 $
  23. * @package propel.runtime.map
  24. */
  25. class TableMap
  26. {
  27. /**
  28. * Columns in the table
  29. * @var array TableMap[]
  30. */
  31. protected $columns = array();
  32. /**
  33. * Columns in the table, using table phpName as key
  34. * @var array TableMap[]
  35. */
  36. protected $columnsByPhpName = array();
  37. // The database this table belongs to
  38. protected $dbMap;
  39. // The name of the table
  40. protected $tableName;
  41. // The PHP name of the table
  42. protected $phpName;
  43. // The Classname for this table
  44. protected $classname;
  45. // The Package for this table
  46. protected $package;
  47. // Whether to use an id generator for pkey
  48. protected $useIdGenerator;
  49. // Whether the table uses single table inheritance
  50. protected $isSingleTableInheritance = false;
  51. // The primary key columns in the table
  52. protected $primaryKeys = array();
  53. // The foreign key columns in the table
  54. protected $foreignKeys = array();
  55. // The relationships in the table
  56. protected $relations = array();
  57. // Relations are lazy loaded. This property tells if the relations are loaded or not
  58. protected $relationsBuilt = false;
  59. // Object to store information that is needed if the for generating primary keys
  60. protected $pkInfo;
  61. /**
  62. * Construct a new TableMap.
  63. *
  64. */
  65. public function __construct($name = null, $dbMap = null)
  66. {
  67. if (null !== $name) {
  68. $this->setName($name);
  69. }
  70. if (null !== $dbMap) {
  71. $this->setDatabaseMap($dbMap);
  72. }
  73. $this->initialize();
  74. }
  75. /**
  76. * Initialize the TableMap to build columns, relations, etc
  77. * This method should be overridden by descendents
  78. */
  79. public function initialize()
  80. {
  81. }
  82. /**
  83. * Set the DatabaseMap containing this TableMap.
  84. *
  85. * @param DatabaseMap $dbMap A DatabaseMap.
  86. */
  87. public function setDatabaseMap(DatabaseMap $dbMap)
  88. {
  89. $this->dbMap = $dbMap;
  90. }
  91. /**
  92. * Get the DatabaseMap containing this TableMap.
  93. *
  94. * @return DatabaseMap A DatabaseMap.
  95. */
  96. public function getDatabaseMap()
  97. {
  98. return $this->dbMap;
  99. }
  100. /**
  101. * Set the name of the Table.
  102. *
  103. * @param string $name The name of the table.
  104. */
  105. public function setName($name)
  106. {
  107. $this->tableName = $name;
  108. }
  109. /**
  110. * Get the name of the Table.
  111. *
  112. * @return string A String with the name of the table.
  113. */
  114. public function getName()
  115. {
  116. return $this->tableName;
  117. }
  118. /**
  119. * Set the PHP name of the Table.
  120. *
  121. * @param string $phpName The PHP Name for this table
  122. */
  123. public function setPhpName($phpName)
  124. {
  125. $this->phpName = $phpName;
  126. }
  127. /**
  128. * Get the PHP name of the Table.
  129. *
  130. * @return string A String with the name of the table.
  131. */
  132. public function getPhpName()
  133. {
  134. return $this->phpName;
  135. }
  136. /**
  137. * Set the Classname of the Table. Could be useful for calling
  138. * Peer and Object methods dynamically.
  139. * @param string $classname The Classname
  140. */
  141. public function setClassname($classname)
  142. {
  143. $this->classname = $classname;
  144. }
  145. /**
  146. * Get the Classname of the Propel Class belonging to this table.
  147. * @return string
  148. */
  149. public function getClassname()
  150. {
  151. return $this->classname;
  152. }
  153. /**
  154. * Get the Peer Classname of the Propel Class belonging to this table.
  155. * @return string
  156. */
  157. public function getPeerClassname()
  158. {
  159. return constant($this->classname . '::PEER');
  160. }
  161. /**
  162. * Set the Package of the Table
  163. *
  164. * @param string $package The Package
  165. */
  166. public function setPackage($package)
  167. {
  168. $this->package = $package;
  169. }
  170. /**
  171. * Get the Package of the table.
  172. * @return string
  173. */
  174. public function getPackage()
  175. {
  176. return $this->package;
  177. }
  178. /**
  179. * Set whether or not to use Id generator for primary key.
  180. * @param boolean $bit
  181. */
  182. public function setUseIdGenerator($bit)
  183. {
  184. $this->useIdGenerator = $bit;
  185. }
  186. /**
  187. * Whether to use Id generator for primary key.
  188. * @return boolean
  189. */
  190. public function isUseIdGenerator()
  191. {
  192. return $this->useIdGenerator;
  193. }
  194. /**
  195. * Set whether or not to this table uses single table inheritance
  196. * @param boolean $bit
  197. */
  198. public function setSingleTableInheritance($bit)
  199. {
  200. $this->isSingleTableInheritance = $bit;
  201. }
  202. /**
  203. * Whether this table uses single table inheritance
  204. * @return boolean
  205. */
  206. public function isSingleTableInheritance()
  207. {
  208. return $this->isSingleTableInheritance;
  209. }
  210. /**
  211. * Sets the pk information needed to generate a key
  212. *
  213. * @param $pkInfo information needed to generate a key
  214. */
  215. public function setPrimaryKeyMethodInfo($pkInfo)
  216. {
  217. $this->pkInfo = $pkInfo;
  218. }
  219. /**
  220. * Get the information used to generate a primary key
  221. *
  222. * @return An Object.
  223. */
  224. public function getPrimaryKeyMethodInfo()
  225. {
  226. return $this->pkInfo;
  227. }
  228. /**
  229. * Add a column to the table.
  230. *
  231. * @param string name A String with the column name.
  232. * @param string $type A string specifying the Propel type.
  233. * @param boolean $isNotNull Whether column does not allow NULL values.
  234. * @param int $size An int specifying the size.
  235. * @param boolean $pk True if column is a primary key.
  236. * @param string $fkTable A String with the foreign key table name.
  237. * @param $fkColumn A String with the foreign key column name.
  238. * @param string $defaultValue The default value for this column.
  239. * @return ColumnMap The newly created column.
  240. */
  241. public function addColumn($name, $phpName, $type, $isNotNull = false, $size = null, $defaultValue = null, $pk = false, $fkTable = null, $fkColumn = null)
  242. {
  243. $col = new ColumnMap($name, $this);
  244. $col->setType($type);
  245. $col->setSize($size);
  246. $col->setPhpName($phpName);
  247. $col->setNotNull($isNotNull);
  248. $col->setDefaultValue($defaultValue);
  249. if ($pk) {
  250. $col->setPrimaryKey(true);
  251. $this->primaryKeys[$name] = $col;
  252. }
  253. if ($fkTable && $fkColumn) {
  254. $col->setForeignKey($fkTable, $fkColumn);
  255. $this->foreignKeys[$name] = $col;
  256. }
  257. $this->columns[$name] = $col;
  258. $this->columnsByPhpName[$phpName] = $col;
  259. return $col;
  260. }
  261. /**
  262. * Add a pre-created column to this table. It will replace any
  263. * existing column.
  264. *
  265. * @param ColumnMap $cmap A ColumnMap.
  266. * @return ColumnMap The added column map.
  267. */
  268. public function addConfiguredColumn($cmap)
  269. {
  270. $this->columns[ $cmap->getColumnName() ] = $cmap;
  271. return $cmap;
  272. }
  273. /**
  274. * Does this table contain the specified column?
  275. *
  276. * @param mixed $name name of the column or ColumnMap instance
  277. * @param boolean $normalize Normalize the column name (if column name not like FIRST_NAME)
  278. * @return boolean True if the table contains the column.
  279. */
  280. public function hasColumn($name, $normalize = true)
  281. {
  282. if ($name instanceof ColumnMap) {
  283. $name = $name->getColumnName();
  284. } else if($normalize) {
  285. $name = ColumnMap::normalizeName($name);
  286. }
  287. return isset($this->columns[$name]);
  288. }
  289. /**
  290. * Get a ColumnMap for the table.
  291. *
  292. * @param string $name A String with the name of the table.
  293. * @param boolean $normalize Normalize the column name (if column name not like FIRST_NAME)
  294. * @return ColumnMap A ColumnMap.
  295. * @throws PropelException if the column is undefined
  296. */
  297. public function getColumn($name, $normalize = true)
  298. {
  299. if ($normalize) {
  300. $name = ColumnMap::normalizeName($name);
  301. }
  302. if (!$this->hasColumn($name, false)) {
  303. throw new PropelException("Cannot fetch ColumnMap for undefined column: " . $name);
  304. }
  305. return $this->columns[$name];
  306. }
  307. /**
  308. * Does this table contain the specified column?
  309. *
  310. * @param mixed $phpName name of the column
  311. * @return boolean True if the table contains the column.
  312. */
  313. public function hasColumnByPhpName($phpName)
  314. {
  315. return isset($this->columnsByPhpName[$phpName]);
  316. }
  317. /**
  318. * Get a ColumnMap for the table.
  319. *
  320. * @param string $phpName A String with the name of the table.
  321. * @return ColumnMap A ColumnMap.
  322. * @throws PropelException if the column is undefined
  323. */
  324. public function getColumnByPhpName($phpName)
  325. {
  326. if (!isset($this->columnsByPhpName[$phpName])) {
  327. throw new PropelException("Cannot fetch ColumnMap for undefined column phpName: " . $phpName);
  328. }
  329. return $this->columnsByPhpName[$phpName];
  330. }
  331. /**
  332. * Get a ColumnMap[] of the columns in this table.
  333. *
  334. * @return array A ColumnMap[].
  335. */
  336. public function getColumns()
  337. {
  338. return $this->columns;
  339. }
  340. /**
  341. * Add a primary key column to this Table.
  342. *
  343. * @param string $columnName A String with the column name.
  344. * @param string $type A string specifying the Propel type.
  345. * @param boolean $isNotNull Whether column does not allow NULL values.
  346. * @param $size An int specifying the size.
  347. * @return ColumnMap Newly added PrimaryKey column.
  348. */
  349. public function addPrimaryKey($columnName, $phpName, $type, $isNotNull = false, $size = null, $defaultValue = null)
  350. {
  351. return $this->addColumn($columnName, $phpName, $type, $isNotNull, $size, $defaultValue, true, null, null);
  352. }
  353. /**
  354. * Add a foreign key column to the table.
  355. *
  356. * @param string $columnName A String with the column name.
  357. * @param string $type A string specifying the Propel type.
  358. * @param string $fkTable A String with the foreign key table name.
  359. * @param string $fkColumn A String with the foreign key column name.
  360. * @param boolean $isNotNull Whether column does not allow NULL values.
  361. * @param int $size An int specifying the size.
  362. * @param string $defaultValue The default value for this column.
  363. * @return ColumnMap Newly added ForeignKey column.
  364. */
  365. public function addForeignKey($columnName, $phpName, $type, $fkTable, $fkColumn, $isNotNull = false, $size = 0, $defaultValue = null)
  366. {
  367. return $this->addColumn($columnName, $phpName, $type, $isNotNull, $size, $defaultValue, false, $fkTable, $fkColumn);
  368. }
  369. /**
  370. * Add a foreign primary key column to the table.
  371. *
  372. * @param string $columnName A String with the column name.
  373. * @param string $type A string specifying the Propel type.
  374. * @param string $fkTable A String with the foreign key table name.
  375. * @param string $fkColumn A String with the foreign key column name.
  376. * @param boolean $isNotNull Whether column does not allow NULL values.
  377. * @param int $size An int specifying the size.
  378. * @param string $defaultValue The default value for this column.
  379. * @return ColumnMap Newly created foreign pkey column.
  380. */
  381. public function addForeignPrimaryKey($columnName, $phpName, $type, $fkTable, $fkColumn, $isNotNull = false, $size = 0, $defaultValue = null)
  382. {
  383. return $this->addColumn($columnName, $phpName, $type, $isNotNull, $size, $defaultValue, true, $fkTable, $fkColumn);
  384. }
  385. /**
  386. * Returns array of ColumnMap objects that make up the primary key for this table
  387. *
  388. * @return array ColumnMap[]
  389. */
  390. public function getPrimaryKeys()
  391. {
  392. return $this->primaryKeys;
  393. }
  394. /**
  395. * Returns array of ColumnMap objects that are foreign keys for this table
  396. *
  397. * @return array ColumnMap[]
  398. */
  399. public function getForeignKeys()
  400. {
  401. return $this->foreignKeys;
  402. }
  403. /**
  404. * Add a validator to a table's column
  405. *
  406. * @param string $columnName The name of the validator's column
  407. * @param string $name The rule name of this validator
  408. * @param string $classname The dot-path name of class to use (e.g. myapp.propel.MyValidator)
  409. * @param string $value
  410. * @param string $message The error message which is returned on invalid values
  411. * @return void
  412. */
  413. public function addValidator($columnName, $name, $classname, $value, $message)
  414. {
  415. if (false !== ($pos = strpos($columnName, '.'))) {
  416. $columnName = substr($columnName, $pos + 1);
  417. }
  418. $col = $this->getColumn($columnName);
  419. if ($col !== null) {
  420. $validator = new ValidatorMap($col);
  421. $validator->setName($name);
  422. $validator->setClass($classname);
  423. $validator->setValue($value);
  424. $validator->setMessage($message);
  425. $col->addValidator($validator);
  426. }
  427. }
  428. /**
  429. * Build relations
  430. * Relations are lazy loaded for performance reasons
  431. * This method should be overridden by descendents
  432. */
  433. public function buildRelations()
  434. {
  435. }
  436. /**
  437. * Adds a RelationMap to the table
  438. *
  439. * @param string $name The relation name
  440. * @param string $tablePhpName The related table name
  441. * @param integer $type The relation type (either RelationMap::MANY_TO_ONE, RelationMap::ONE_TO_MANY, or RelationMAp::ONE_TO_ONE)
  442. * @param array $columnMapping An associative array mapping column names (local => foreign)
  443. * @return RelationMap the built RelationMap object
  444. */
  445. public function addRelation($name, $tablePhpName, $type, $columnMapping = array(), $onDelete = null, $onUpdate = null)
  446. {
  447. // note: using phpName for the second table allows the use of DatabaseMap::getTableByPhpName()
  448. // and this method autoloads the TableMap if the table isn't loaded yet
  449. $relation = new RelationMap($name);
  450. $relation->setType($type);
  451. $relation->setOnUpdate($onUpdate);
  452. $relation->setOnDelete($onDelete);
  453. // set tables
  454. if ($type == RelationMap::MANY_TO_ONE) {
  455. $relation->setLocalTable($this);
  456. $relation->setForeignTable($this->dbMap->getTableByPhpName($tablePhpName));
  457. } else {
  458. $relation->setLocalTable($this->dbMap->getTableByPhpName($tablePhpName));
  459. $relation->setForeignTable($this);
  460. $columnMapping = array_flip($columnMapping);
  461. }
  462. // set columns
  463. foreach ($columnMapping as $local => $foreign) {
  464. $relation->addColumnMapping(
  465. $relation->getLocalTable()->getColumn($local),
  466. $relation->getForeignTable()->getColumn($foreign)
  467. );
  468. }
  469. $this->relations[$name] = $relation;
  470. return $relation;
  471. }
  472. /**
  473. * Gets a RelationMap of the table by relation name
  474. * This method will build the relations if they are not built yet
  475. *
  476. * @param String $name The relation name
  477. * @return boolean true if the relation exists
  478. */
  479. public function hasRelation($name)
  480. {
  481. return array_key_exists($name, $this->getRelations());
  482. }
  483. /**
  484. * Gets a RelationMap of the table by relation name
  485. * This method will build the relations if they are not built yet
  486. *
  487. * @param String $name The relation name
  488. * @return RelationMap The relation object
  489. * @throws PropelException When called on an inexistent relation
  490. */
  491. public function getRelation($name)
  492. {
  493. if (!array_key_exists($name, $this->getRelations()))
  494. {
  495. throw new PropelException('Calling getRelation() on an unknown relation, ' . $name);
  496. }
  497. return $this->relations[$name];
  498. }
  499. /**
  500. * Gets the RelationMap objects of the table
  501. * This method will build the relations if they are not built yet
  502. *
  503. * @return Array list of RelationMap objects
  504. */
  505. public function getRelations()
  506. {
  507. if(!$this->relationsBuilt)
  508. {
  509. $this->buildRelations();
  510. $this->relationsBuilt = true;
  511. }
  512. return $this->relations;
  513. }
  514. /**
  515. *
  516. * Gets the list of behaviors registered for this table
  517. *
  518. * @return array
  519. */
  520. public function getBehaviors()
  521. {
  522. return array();
  523. }
  524. // Deprecated methods and attributres, to be removed
  525. /**
  526. * Does this table contain the specified column?
  527. *
  528. * @deprecated Use hasColumn instead
  529. * @param mixed $name name of the column or ColumnMap instance
  530. * @param boolean $normalize Normalize the column name (if column name not like FIRST_NAME)
  531. * @return boolean True if the table contains the column.
  532. */
  533. public function containsColumn($name, $normalize = true)
  534. {
  535. return $this->hasColumn($name, $normalize);
  536. }
  537. /**
  538. * Normalizes the column name, removing table prefix and uppercasing.
  539. * article.first_name becomes FIRST_NAME
  540. *
  541. * @deprecated Use ColumnMap::normalizeColumName() instead
  542. * @param string $name
  543. * @return string Normalized column name.
  544. */
  545. protected function normalizeColName($name)
  546. {
  547. return ColumnMap::normalizeName($name);
  548. }
  549. /**
  550. * Returns array of ColumnMap objects that make up the primary key for this table.
  551. *
  552. * @deprecated Use getPrimaryKeys instead
  553. * @return array ColumnMap[]
  554. */
  555. public function getPrimaryKeyColumns()
  556. {
  557. return array_values($this->primaryKeys);
  558. }
  559. //---Utility methods for doing intelligent lookup of table names
  560. /**
  561. * The prefix on the table name.
  562. * @deprecated Not used anywhere in Propel
  563. */
  564. private $prefix;
  565. /**
  566. * Get table prefix name.
  567. *
  568. * @deprecated Not used anywhere in Propel
  569. * @return string A String with the prefix.
  570. */
  571. public function getPrefix()
  572. {
  573. return $this->prefix;
  574. }
  575. /**
  576. * Set table prefix name.
  577. *
  578. * @deprecated Not used anywhere in Propel
  579. * @param string $prefix The prefix for the table name (ie: SCARAB for
  580. * SCARAB_PROJECT).
  581. * @return void
  582. */
  583. public function setPrefix($prefix)
  584. {
  585. $this->prefix = $prefix;
  586. }
  587. /**
  588. * Tell me if i have PREFIX in my string.
  589. *
  590. * @deprecated Not used anywhere in Propel
  591. * @param data A String.
  592. * @return boolean True if prefix is contained in data.
  593. */
  594. protected function hasPrefix($data)
  595. {
  596. return (strpos($data, $this->prefix) === 0);
  597. }
  598. /**
  599. * Removes the PREFIX if found
  600. *
  601. * @deprecated Not used anywhere in Propel
  602. * @param string $data A String.
  603. * @return string A String with data, but with prefix removed.
  604. */
  605. protected function removePrefix($data)
  606. {
  607. return $this->hasPrefix($data) ? substr($data, strlen($this->prefix)) : $data;
  608. }
  609. /**
  610. * Removes the PREFIX, removes the underscores and makes
  611. * first letter caps.
  612. *
  613. * SCARAB_FOO_BAR becomes FooBar.
  614. *
  615. * @deprecated Not used anywhere in Propel. At buildtime, use Column::generatePhpName() for that purpose
  616. * @param data A String.
  617. * @return string A String with data processed.
  618. */
  619. public final function removeUnderScores($data)
  620. {
  621. $out = '';
  622. $tmp = $this->removePrefix($data);
  623. $tok = strtok($tmp, '_');
  624. while ($tok) {
  625. $out .= ucfirst($tok);
  626. $tok = strtok('_');
  627. }
  628. return $out;
  629. }
  630. /**
  631. * Makes the first letter caps and the rest lowercase.
  632. *
  633. * @deprecated Not used anywhere in Propel.
  634. * @param string $data A String.
  635. * @return string A String with data processed.
  636. */
  637. private function firstLetterCaps($data)
  638. {
  639. return(ucfirst(strtolower($data)));
  640. }
  641. }