Builder.php 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. <?php
  2. namespace Illuminate\Database\Schema;
  3. use Closure;
  4. use LogicException;
  5. use RuntimeException;
  6. use Doctrine\DBAL\Types\Type;
  7. use Illuminate\Database\Connection;
  8. class Builder
  9. {
  10. /**
  11. * The database connection instance.
  12. *
  13. * @var \Illuminate\Database\Connection
  14. */
  15. protected $connection;
  16. /**
  17. * The schema grammar instance.
  18. *
  19. * @var \Illuminate\Database\Schema\Grammars\Grammar
  20. */
  21. protected $grammar;
  22. /**
  23. * The Blueprint resolver callback.
  24. *
  25. * @var \Closure
  26. */
  27. protected $resolver;
  28. /**
  29. * The default string length for migrations.
  30. *
  31. * @var int
  32. */
  33. public static $defaultStringLength = 255;
  34. /**
  35. * Create a new database Schema manager.
  36. *
  37. * @param \Illuminate\Database\Connection $connection
  38. * @return void
  39. */
  40. public function __construct(Connection $connection)
  41. {
  42. $this->connection = $connection;
  43. $this->grammar = $connection->getSchemaGrammar();
  44. }
  45. /**
  46. * Set the default string length for migrations.
  47. *
  48. * @param int $length
  49. * @return void
  50. */
  51. public static function defaultStringLength($length)
  52. {
  53. static::$defaultStringLength = $length;
  54. }
  55. /**
  56. * Determine if the given table exists.
  57. *
  58. * @param string $table
  59. * @return bool
  60. */
  61. public function hasTable($table)
  62. {
  63. $table = $this->connection->getTablePrefix().$table;
  64. return count($this->connection->selectFromWriteConnection(
  65. $this->grammar->compileTableExists(), [$table]
  66. )) > 0;
  67. }
  68. /**
  69. * Determine if the given table has a given column.
  70. *
  71. * @param string $table
  72. * @param string $column
  73. * @return bool
  74. */
  75. public function hasColumn($table, $column)
  76. {
  77. return in_array(
  78. strtolower($column), array_map('strtolower', $this->getColumnListing($table))
  79. );
  80. }
  81. /**
  82. * Determine if the given table has given columns.
  83. *
  84. * @param string $table
  85. * @param array $columns
  86. * @return bool
  87. */
  88. public function hasColumns($table, array $columns)
  89. {
  90. $tableColumns = array_map('strtolower', $this->getColumnListing($table));
  91. foreach ($columns as $column) {
  92. if (! in_array(strtolower($column), $tableColumns)) {
  93. return false;
  94. }
  95. }
  96. return true;
  97. }
  98. /**
  99. * Get the data type for the given column name.
  100. *
  101. * @param string $table
  102. * @param string $column
  103. * @return string
  104. */
  105. public function getColumnType($table, $column)
  106. {
  107. $table = $this->connection->getTablePrefix().$table;
  108. return $this->connection->getDoctrineColumn($table, $column)->getType()->getName();
  109. }
  110. /**
  111. * Get the column listing for a given table.
  112. *
  113. * @param string $table
  114. * @return array
  115. */
  116. public function getColumnListing($table)
  117. {
  118. $results = $this->connection->selectFromWriteConnection($this->grammar->compileColumnListing(
  119. $this->connection->getTablePrefix().$table
  120. ));
  121. return $this->connection->getPostProcessor()->processColumnListing($results);
  122. }
  123. /**
  124. * Modify a table on the schema.
  125. *
  126. * @param string $table
  127. * @param \Closure $callback
  128. * @return void
  129. */
  130. public function table($table, Closure $callback)
  131. {
  132. $this->build($this->createBlueprint($table, $callback));
  133. }
  134. /**
  135. * Create a new table on the schema.
  136. *
  137. * @param string $table
  138. * @param \Closure $callback
  139. * @return void
  140. */
  141. public function create($table, Closure $callback)
  142. {
  143. $this->build(tap($this->createBlueprint($table), function ($blueprint) use ($callback) {
  144. $blueprint->create();
  145. $callback($blueprint);
  146. }));
  147. }
  148. /**
  149. * Drop a table from the schema.
  150. *
  151. * @param string $table
  152. * @return void
  153. */
  154. public function drop($table)
  155. {
  156. $this->build(tap($this->createBlueprint($table), function ($blueprint) {
  157. $blueprint->drop();
  158. }));
  159. }
  160. /**
  161. * Drop a table from the schema if it exists.
  162. *
  163. * @param string $table
  164. * @return void
  165. */
  166. public function dropIfExists($table)
  167. {
  168. $this->build(tap($this->createBlueprint($table), function ($blueprint) {
  169. $blueprint->dropIfExists();
  170. }));
  171. }
  172. /**
  173. * Drop all tables from the database.
  174. *
  175. * @return void
  176. *
  177. * @throws \LogicException
  178. */
  179. public function dropAllTables()
  180. {
  181. throw new LogicException('This database driver does not support dropping all tables.');
  182. }
  183. /**
  184. * Drop all views from the database.
  185. *
  186. * @return void
  187. *
  188. * @throws \LogicException
  189. */
  190. public function dropAllViews()
  191. {
  192. throw new LogicException('This database driver does not support dropping all views.');
  193. }
  194. /**
  195. * Drop all types from the database.
  196. *
  197. * @return void
  198. *
  199. * @throws \LogicException
  200. */
  201. public function dropAllTypes()
  202. {
  203. throw new LogicException('This database driver does not support dropping all types.');
  204. }
  205. /**
  206. * Rename a table on the schema.
  207. *
  208. * @param string $from
  209. * @param string $to
  210. * @return void
  211. */
  212. public function rename($from, $to)
  213. {
  214. $this->build(tap($this->createBlueprint($from), function ($blueprint) use ($to) {
  215. $blueprint->rename($to);
  216. }));
  217. }
  218. /**
  219. * Enable foreign key constraints.
  220. *
  221. * @return bool
  222. */
  223. public function enableForeignKeyConstraints()
  224. {
  225. return $this->connection->statement(
  226. $this->grammar->compileEnableForeignKeyConstraints()
  227. );
  228. }
  229. /**
  230. * Disable foreign key constraints.
  231. *
  232. * @return bool
  233. */
  234. public function disableForeignKeyConstraints()
  235. {
  236. return $this->connection->statement(
  237. $this->grammar->compileDisableForeignKeyConstraints()
  238. );
  239. }
  240. /**
  241. * Execute the blueprint to build / modify the table.
  242. *
  243. * @param \Illuminate\Database\Schema\Blueprint $blueprint
  244. * @return void
  245. */
  246. protected function build(Blueprint $blueprint)
  247. {
  248. $blueprint->build($this->connection, $this->grammar);
  249. }
  250. /**
  251. * Create a new command set with a Closure.
  252. *
  253. * @param string $table
  254. * @param \Closure|null $callback
  255. * @return \Illuminate\Database\Schema\Blueprint
  256. */
  257. protected function createBlueprint($table, Closure $callback = null)
  258. {
  259. $prefix = $this->connection->getConfig('prefix_indexes')
  260. ? $this->connection->getConfig('prefix')
  261. : '';
  262. if (isset($this->resolver)) {
  263. return call_user_func($this->resolver, $table, $callback, $prefix);
  264. }
  265. return new Blueprint($table, $callback, $prefix);
  266. }
  267. /**
  268. * Register a custom Doctrine mapping type.
  269. *
  270. * @param string $class
  271. * @param string $name
  272. * @param string $type
  273. * @return void
  274. *
  275. * @throws \Doctrine\DBAL\DBALException
  276. */
  277. public function registerCustomDoctrineType($class, $name, $type)
  278. {
  279. if (! $this->connection->isDoctrineAvailable()) {
  280. throw new RuntimeException(
  281. 'Registering a custom Doctrine type requires Doctrine DBAL (doctrine/dbal).'
  282. );
  283. }
  284. if (! Type::hasType($name)) {
  285. Type::addType($name, $class);
  286. $this->connection
  287. ->getDoctrineSchemaManager()
  288. ->getDatabasePlatform()
  289. ->registerDoctrineTypeMapping($type, $name);
  290. }
  291. }
  292. /**
  293. * Get the database connection instance.
  294. *
  295. * @return \Illuminate\Database\Connection
  296. */
  297. public function getConnection()
  298. {
  299. return $this->connection;
  300. }
  301. /**
  302. * Set the database connection instance.
  303. *
  304. * @param \Illuminate\Database\Connection $connection
  305. * @return $this
  306. */
  307. public function setConnection(Connection $connection)
  308. {
  309. $this->connection = $connection;
  310. return $this;
  311. }
  312. /**
  313. * Set the Schema Blueprint resolver callback.
  314. *
  315. * @param \Closure $resolver
  316. * @return void
  317. */
  318. public function blueprintResolver(Closure $resolver)
  319. {
  320. $this->resolver = $resolver;
  321. }
  322. }