Builder.php 7.3 KB

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