/src/Illuminate/Database/Schema/Blueprint.php

https://bitbucket.org/mikebosire/framework · PHP · 644 lines · 251 code · 73 blank · 320 comment · 9 complexity · 925ee2d86d13825a1a6de952d7055ccb MD5 · raw file

  1. <?php namespace Illuminate\Database\Schema;
  2. use Closure;
  3. use Illuminate\Support\Fluent;
  4. use Illuminate\Database\Connection;
  5. use Illuminate\Database\Schema\Grammars\Grammar;
  6. class Blueprint {
  7. /**
  8. * The table the blueprint describes.
  9. *
  10. * @var string
  11. */
  12. protected $table;
  13. /**
  14. * The columns that should be added to the table.
  15. *
  16. * @var array
  17. */
  18. protected $columns = array();
  19. /**
  20. * The commands that should be run for the table.
  21. *
  22. * @var array
  23. */
  24. protected $commands = array();
  25. /**
  26. * Create a new schema blueprint.
  27. *
  28. * @param string $table
  29. * @param Closure $callback
  30. * @return void
  31. */
  32. public function __construct($table, Closure $callback = null)
  33. {
  34. $this->table = $table;
  35. if ( ! is_null($callback)) $callback($this);
  36. }
  37. /**
  38. * Execute the blueprint against the database.
  39. *
  40. * @param \Illuminate\Database\Connection $connection
  41. * @param \Illuminate\Database\Schema\Grammars\Grammar $grammar
  42. * @return void
  43. */
  44. public function build(Connection $connection, Grammar $grammar)
  45. {
  46. foreach ($this->toSql($connection, $grammar) as $statement)
  47. {
  48. $connection->statement($statement);
  49. }
  50. }
  51. /**
  52. * Get the raw SQL statements for the blueprint.
  53. *
  54. * @param \Illuminate\Database\Connection $connection
  55. * @param \Illuminate\Database\Schema\Grammars\Grammar $grammar
  56. * @return array
  57. */
  58. public function toSql(Connection $connection, Grammar $grammar)
  59. {
  60. $this->addImpliedCommands();
  61. $statements = array();
  62. // Each type of command has a corresponding compiler function on the schema
  63. // grammar which is used to build the necessary SQL statements to build
  64. // the blueprint element, so we'll just call that compilers function.
  65. foreach ($this->commands as $command)
  66. {
  67. $method = 'compile'.ucfirst($command->name);
  68. if (method_exists($grammar, $method))
  69. {
  70. if ( ! is_null($sql = $grammar->$method($this, $command, $connection)))
  71. {
  72. $statements = array_merge($statements, (array) $sql);
  73. }
  74. }
  75. }
  76. return $statements;
  77. }
  78. /**
  79. * Add the commands that are implied by the blueprint.
  80. *
  81. * @return void
  82. */
  83. protected function addImpliedCommands()
  84. {
  85. if (count($this->columns) > 0 and ! $this->creating())
  86. {
  87. array_unshift($this->commands, $this->createCommand('add'));
  88. }
  89. $this->addFluentIndexes();
  90. }
  91. /**
  92. * Add the index commands fluently specified on columns.
  93. *
  94. * @return void
  95. */
  96. protected function addFluentIndexes()
  97. {
  98. foreach ($this->columns as $column)
  99. {
  100. foreach (array('primary', 'unique', 'index') as $index)
  101. {
  102. // If the index has been specified on the given column, but is simply
  103. // equal to "true" (boolean), no name has been specified for this
  104. // index, so we will simply call the index methods without one.
  105. if ($column->$index === true)
  106. {
  107. $this->$index($column->name);
  108. continue 2;
  109. }
  110. // If the index has been specified on the column and it is something
  111. // other than boolean true, we will assume a name was provided on
  112. // the index specification, and pass in the name to the method.
  113. elseif (isset($column->$index))
  114. {
  115. $this->$index($column->name, $column->$index);
  116. continue 2;
  117. }
  118. }
  119. }
  120. }
  121. /**
  122. * Determine if the blueprint has a create command.
  123. *
  124. * @return bool
  125. */
  126. protected function creating()
  127. {
  128. foreach ($this->commands as $command)
  129. {
  130. if ($command->name == 'create') return true;
  131. }
  132. return false;
  133. }
  134. /**
  135. * Indicate that the table needs to be created.
  136. *
  137. * @return \Illuminate\Support\Fluent
  138. */
  139. public function create()
  140. {
  141. return $this->addCommand('create');
  142. }
  143. /**
  144. * Indicate that the table should be dropped.
  145. *
  146. * @return \Illuminate\Support\Fluent
  147. */
  148. public function drop()
  149. {
  150. return $this->addCommand('drop');
  151. }
  152. /**
  153. * Indicate that the table should be dropped if it exists.
  154. *
  155. * @return \Illuminate\Support\Fluent
  156. */
  157. public function dropIfExists()
  158. {
  159. return $this->addCommand('dropIfExists');
  160. }
  161. /**
  162. * Indicate that the given columns should be dropped.
  163. *
  164. * @param string|array $columns
  165. * @return \Illuminate\Support\Fluent
  166. */
  167. public function dropColumn($columns)
  168. {
  169. $columns = (array) $columns;
  170. return $this->addCommand('dropColumn', compact('columns'));
  171. }
  172. /**
  173. * Indicate that the given columns should be dropped.
  174. *
  175. * @param dynamic
  176. * @return \Illuminate\Support\Fluent
  177. */
  178. public function dropColumns()
  179. {
  180. return $this->dropColumn(func_get_args());
  181. }
  182. /**
  183. * Indicate that the given primary key should be dropped.
  184. *
  185. * @param string|array $index
  186. * @return \Illuminate\Support\Fluent
  187. */
  188. public function dropPrimary($index = null)
  189. {
  190. return $this->dropIndexCommand('dropPrimary', $index);
  191. }
  192. /**
  193. * Indicate that the given unique key should be dropped.
  194. *
  195. * @param string|array $index
  196. * @return \Illuminate\Support\Fluent
  197. */
  198. public function dropUnique($index)
  199. {
  200. return $this->dropIndexCommand('dropUnique', $index);
  201. }
  202. /**
  203. * Indicate that the given index should be dropped.
  204. *
  205. * @param string|array $index
  206. * @return \Illuminate\Support\Fluent
  207. */
  208. public function dropIndex($index)
  209. {
  210. return $this->dropIndexCommand('dropIndex', $index);
  211. }
  212. /**
  213. * Indicate that the given foreign key should be dropped.
  214. *
  215. * @param string $index
  216. * @return \Illuminate\Support\Fluent
  217. */
  218. public function dropForeign($index)
  219. {
  220. return $this->dropIndexCommand('dropForeign', $index);
  221. }
  222. /**
  223. * Indicate that the timestamp columns should be dropped.
  224. *
  225. * @return void
  226. */
  227. public function dropTimestamps()
  228. {
  229. $this->dropColumns('created_at', 'updated_at');
  230. }
  231. /**
  232. * Rename the table to a given name.
  233. *
  234. * @param string $to
  235. * @return \Illuminate\Support\Fluent
  236. */
  237. public function rename($to)
  238. {
  239. return $this->addCommand('rename', compact('to'));
  240. }
  241. /**
  242. * Specify the primary key(s) for the table.
  243. *
  244. * @param string|array $columns
  245. * @param string $name
  246. * @return \Illuminate\Support\Fluent
  247. */
  248. public function primary($columns, $name = null)
  249. {
  250. return $this->indexCommand('primary', $columns, $name);
  251. }
  252. /**
  253. * Specify a unique index for the table.
  254. *
  255. * @param string|array $columns
  256. * @param string $name
  257. * @return \Illuminate\Support\Fluent
  258. */
  259. public function unique($columns, $name = null)
  260. {
  261. return $this->indexCommand('unique', $columns, $name);
  262. }
  263. /**
  264. * Specify an index for the table.
  265. *
  266. * @param string|array $columns
  267. * @param string $name
  268. * @return \Illuminate\Support\Fluent
  269. */
  270. public function index($columns, $name = null)
  271. {
  272. return $this->indexCommand('index', $columns, $name);
  273. }
  274. /**
  275. * Specify a foreign key for the table.
  276. *
  277. * @param string|array $columns
  278. * @param string $name
  279. * @return \Illuminate\Support\Fluent
  280. */
  281. public function foreign($columns, $name = null)
  282. {
  283. return $this->indexCommand('foreign', $columns, $name);
  284. }
  285. /**
  286. * Create a new auto-incrementing column on the table.
  287. *
  288. * @param string $column
  289. * @return \Illuminate\Support\Fluent
  290. */
  291. public function increments($column)
  292. {
  293. return $this->unsignedInteger($column, true);
  294. }
  295. /**
  296. * Create a new string column on the table.
  297. *
  298. * @param string $column
  299. * @param int $length
  300. * @return \Illuminate\Support\Fluent
  301. */
  302. public function string($column, $length = 255)
  303. {
  304. return $this->addColumn('string', $column, compact('length'));
  305. }
  306. /**
  307. * Create a new text column on the table.
  308. *
  309. * @param string $column
  310. * @return \Illuminate\Support\Fluent
  311. */
  312. public function text($column)
  313. {
  314. return $this->addColumn('text', $column);
  315. }
  316. /**
  317. * Create a new integer column on the table.
  318. *
  319. * @param string $column
  320. * @param bool $autoIncrement
  321. * @param bool $unsigned
  322. * @return \Illuminate\Support\Fluent
  323. */
  324. public function integer($column, $autoIncrement = false, $unsigned = false)
  325. {
  326. return $this->addColumn('integer', $column, compact('autoIncrement', 'unsigned'));
  327. }
  328. /**
  329. * Create a new tiny integer column on the table.
  330. *
  331. * @param string $column
  332. * @return \Illuminate\Support\Fluent
  333. */
  334. public function tinyInteger($column)
  335. {
  336. return $this->addColumn('tinyInteger', $column);
  337. }
  338. /**
  339. * Create a new unsigned integer column on the table.
  340. *
  341. * @param string $column
  342. * @param bool $autoIncrement
  343. * @param bool $unsigned
  344. * @return \Illuminate\Support\Fluent
  345. */
  346. public function unsignedInteger($column, $autoIncrement = false)
  347. {
  348. return $this->integer($column, $autoIncrement, true);
  349. }
  350. /**
  351. * Create a new float column on the table.
  352. *
  353. * @param string $column
  354. * @param int $total
  355. * @param int $places
  356. * @return \Illuminate\Support\Fluent
  357. */
  358. public function float($column, $total = 8, $places = 2)
  359. {
  360. return $this->addColumn('float', $column, compact('total', 'places'));
  361. }
  362. /**
  363. * Create a new decimal column on the table.
  364. *
  365. * @param string $column
  366. * @param int $total
  367. * @param int $places
  368. * @return \Illuminate\Support\Fluent
  369. */
  370. public function decimal($column, $total = 8, $places = 2)
  371. {
  372. return $this->addColumn('decimal', $column, compact('total', 'places'));
  373. }
  374. /**
  375. * Create a new boolean column on the table.
  376. *
  377. * @param string $column
  378. * @return \Illuminate\Support\Fluent
  379. */
  380. public function boolean($column)
  381. {
  382. return $this->addColumn('boolean', $column);
  383. }
  384. /**
  385. * Create a new enum column on the table.
  386. *
  387. * @param string $column
  388. * @param array $allowed
  389. * @return \Illuminate\Support\Fluent
  390. */
  391. public function enum($column, array $allowed)
  392. {
  393. return $this->addColumn('enum', $column, compact('allowed'));
  394. }
  395. /**
  396. * Create a new date column on the table.
  397. *
  398. * @param string $column
  399. * @return \Illuminate\Support\Fluent
  400. */
  401. public function date($column)
  402. {
  403. return $this->addColumn('date', $column);
  404. }
  405. /**
  406. * Create a new date-time column on the table.
  407. *
  408. * @param string $column
  409. * @return \Illuminate\Support\Fluent
  410. */
  411. public function dateTime($column)
  412. {
  413. return $this->addColumn('dateTime', $column);
  414. }
  415. /**
  416. * Create a new time column on the table.
  417. *
  418. * @param string $column
  419. * @return \Illuminate\Support\Fluent
  420. */
  421. public function time($column)
  422. {
  423. return $this->addColumn('time', $column);
  424. }
  425. /**
  426. * Create a new timestamp column on the table.
  427. *
  428. * @param string $column
  429. * @return \Illuminate\Support\Fluent
  430. */
  431. public function timestamp($column)
  432. {
  433. return $this->addColumn('timestamp', $column);
  434. }
  435. /**
  436. * Add creation and update timestamps to the table.
  437. *
  438. * @return void
  439. */
  440. public function timestamps()
  441. {
  442. $this->timestamp('created_at');
  443. $this->timestamp('updated_at');
  444. }
  445. /**
  446. * Create a new binary column on the table.
  447. *
  448. * @param string $column
  449. * @return \Illuminate\Support\Fluent
  450. */
  451. public function binary($column)
  452. {
  453. return $this->addColumn('binary', $column);
  454. }
  455. /**
  456. * Create a new drop index command on the blueprint.
  457. *
  458. * @param string $type
  459. * @param string|array $index
  460. * @return \Illuminate\Support\Fluent
  461. */
  462. protected function dropIndexCommand($type, $index)
  463. {
  464. $columns = array();
  465. // If the given "index" is actually an array of columns, the developer means
  466. // to drop an index merely by specifying the columns involved without the
  467. // conventional name, so we will built the index name from the columns.
  468. if (is_array($index))
  469. {
  470. $columns = $index;
  471. $index = null;
  472. }
  473. return $this->indexCommand($type, $columns, $index);
  474. }
  475. /**
  476. * Add a new index command to the blueprint.
  477. *
  478. * @param string $type
  479. * @param string|array $columns
  480. * @param string $index
  481. * @return \Illuminate\Support\Fluent
  482. */
  483. protected function indexCommand($type, $columns, $index)
  484. {
  485. $columns = (array) $columns;
  486. // If no name was specified for this index, we will create one using a basic
  487. // convention of the table name, followed by the columns, followed by an
  488. // index type, such as primary or index, which makes the index unique.
  489. if (is_null($index))
  490. {
  491. $index = $this->createIndexName($type, $columns);
  492. }
  493. return $this->addCommand($type, compact('index', 'columns'));
  494. }
  495. /**
  496. * Create a default index name for the table.
  497. *
  498. * @param string $type
  499. * @param array $columns
  500. * @return string
  501. */
  502. protected function createIndexName($type, array $columns)
  503. {
  504. $table = str_replace(array('-', '.'), '_', $this->table);
  505. return strtolower($table.'_'.implode('_', $columns).'_'.$type);
  506. }
  507. /**
  508. * Add a new column to the blueprint.
  509. *
  510. * @param string $type
  511. * @param string $name
  512. * @param array $parameters
  513. * @return \Illuminate\Support\Fluent
  514. */
  515. protected function addColumn($type, $name, array $parameters = array())
  516. {
  517. $attributes = array_merge(compact('type', 'name'), $parameters);
  518. $this->columns[] = $column = new Fluent($attributes);
  519. return $column;
  520. }
  521. /**
  522. * Add a new command to the blueprint.
  523. *
  524. * @param string $name
  525. * @param array $parameters
  526. * @return \Illuminate\Support\Fluent
  527. */
  528. protected function addCommand($name, array $parameters = array())
  529. {
  530. $this->commands[] = $command = $this->createCommand($name, $parameters);
  531. return $command;
  532. }
  533. /**
  534. * Create a new Fluent command.
  535. *
  536. * @param string $name
  537. * @param array $parameters
  538. * @return \Illuminate\Support\Fluent
  539. */
  540. protected function createCommand($name, array $parameters = array())
  541. {
  542. return new Fluent(array_merge(compact('name'), $parameters));
  543. }
  544. /**
  545. * Get the table the blueprint describes.
  546. *
  547. * @return string
  548. */
  549. public function getTable()
  550. {
  551. return $this->table;
  552. }
  553. /**
  554. * Get the columns that should be added.
  555. *
  556. * @return array
  557. */
  558. public function getColumns()
  559. {
  560. return $this->columns;
  561. }
  562. /**
  563. * Get the commands on the blueprint.
  564. *
  565. * @return array
  566. */
  567. public function getCommands()
  568. {
  569. return $this->commands;
  570. }
  571. }