Firebird DBMSを使用したPHP Webアプリケーションの例(後でリンクが作成されます)を作成するとき、MVCアーキテクチャモデルを使用して開発用のフレームワークを選択するという疑問が生じました。 PHPのフレームワークの選択は非常に大きいですが、最も便利で、シンプルで、簡単に拡張できるのはLaravelのようです。 ただし、このフレームワークはすぐに使用できるDBMS Firebirdをサポートしていません。 LaravelはPDOドライバーを使用してデータベースを操作します。 Firebird用のPDOドライバーがあるので、LaravelをFirebirdである程度の努力で動作させることが可能だと思いました。
Laravelは、MVCアーキテクチャモデル(Eng。Model View Controller-model-view-controller)を使用した開発用に設計された無料のオープンソースWebフレームワークです。 Laravelは、Webアプリケーションを構築するための便利で簡単に拡張可能なフレームワークです。 Laravelフレームワークは、デフォルトで4つのDBMS、MySQL、Postgres、SQLite、MS SQL Serverをサポートしています。 この記事では、別のFirebird DBMSを追加する方法を説明します。
FirebirdConnection接続クラス
Illuminate \ Database \ Connectors \ ConnectionFactoryファクトリを使用してデータベースに接続するたびに、Illuminate \ Database \ ConnectionInterfaceインターフェイスを実装するDBMSのタイプに応じて特定の接続インスタンスが作成されます。 さらに、ファクトリーはコネクターを作成します。コネクターは、構成パラメーターに基づいて接続文字列を形成し、PDO接続デザイナーに渡します。 コネクタはcreateConnectorメソッドで作成されます。 Firebirdのコネクタを作成できるように、少し変更します。
public function createConnector(array $config) { if (! isset($config['driver'])) { throw new InvalidArgumentException('A driver must be specified.'); } if ($this->container->bound($key = "db.connector.{$config['driver']}")) { return $this->container->make($key); } switch ($config['driver']) { case 'mysql': return new MySqlConnector; case 'pgsql': return new PostgresConnector; case 'sqlite': return new SQLiteConnector; case 'sqlsrv': return new SqlServerConnector; case 'firebird':
Illuminate \ Database \ Connectors \ FirebirdConnectorコネクタクラス自体は、後ほど定義します。 それまでの間、Illuminate \ Database \ ConnectionInterfaceインターフェイスを実装する接続を作成するように設計されたcreateConnectionメソッドを変更します。
protected function createConnection($driver, $connection, $database, $prefix = '', array $config = []) { if ($this->container->bound($key = "db.connection.{$driver}")) { return $this->container->make($key, [$connection, $database, $prefix, $config]); } switch ($driver) { case 'mysql': return new MySqlConnection($connection, $database, $prefix, $config); case 'pgsql': return new PostgresConnection($connection, $database, $prefix, $config); case 'sqlite': return new SQLiteConnection($connection, $database, $prefix, $config); case 'sqlsrv': return new SqlServerConnection($connection, $database, $prefix, $config); case 'firebird':
次に、Firebirdのコネクタの作成に移りましょう-Illuminate \ Database \ Connectors \ FirebirdConnectorクラス。 Postgres用のコネクタなど、既存のコネクタをベースとして使用し、Firebird用にリメイクできます。
まず、
ドキュメントに記載されている文字列の形式に従って、接続文字列を形成する方法を変更し
ます 。
protected function getDsn(array $config) { $dsn = "firebird:dbname="; if (isset($config['host'])) { $dsn .= $config['host']; } if (isset($config['port'])) { $dsn .= "/" . $config['port']; } $dsn .= ":" . $config['database']; if (isset($config['charset'])) { $dsn .= ";charset=" . $config['charset']; } if (isset($config['role'])) { $dsn .= ";role=" . $config['role']; } return $dsn; }
この場合、PDO接続を作成するメソッドは簡素化されます。
public function connect(array $config) { $dsn = $this->getDsn($config); $options = $this->getOptions($config);
Laravelで使用されるさまざまなDBMSの接続自体は、Illuminate \ Database \ Connectionクラスを継承します。 Laravel、特にORM Eloquentで使用されるデータベースを操作するためのすべての可能性をそれ自体でカプセル化するのは、このクラスです。 後続のクラス(DBMSの各タイプ)には、DMLクエリを構築するときに必要な文法記述と、DDLクエリ(移行で使用)の文法インスタンスを持つクラスのインスタンスを返すメソッドが実装され、スキーマ名をテーブルに追加します。 このクラスは次のようになります。
namespace Illuminate\Database; use Illuminate\Database\Query\Processors\FirebirdProcessor; use Doctrine\DBAL\Driver\PDOFirebird\Driver as DoctrineDriver; use Illuminate\Database\Query\Grammars\FirebirdGrammar as QueryGrammar; use Illuminate\Database\Schema\Grammars\FirebirdGrammar as SchemaGrammar; class FirebirdConnection extends Connection { protected function getDefaultQueryGrammar() { return $this->withTablePrefix(new QueryGrammar); } protected function getDefaultSchemaGrammar() { return $this->withTablePrefix(new SchemaGrammar); } protected function getDefaultPostProcessor() { return new FirebirdProcessor; } protected function getDoctrineDriver() { return new DoctrineDriver; } }
Doctrineドライバーのインスタンスを返すメソッドは正式に必要であるため、紹介しますが、Doctrineを使用する(Eloquentのみで)という目標はなかったため、実装しませんでした。 ご希望の場合は、自分で行うことができます。
Illuminate \ Database \ Query \ Processors \ FirebirdProcessorポストプロセッサは、クエリ結果の追加処理を目的としています。特に、INSERTリクエストからレコード識別子を抽出するのに役立ちます。 その実装の定義は、Illuminate \ Database \ Query \ Processors \ PostgresProcessorから完全にコピーされます。
DMLクエリを構築するための文法クラス
次に、最も興味深く重要なもの、つまりDMLクエリを構築するための文法の説明に目を向けます。 Laravelクエリビルダ用に記述された式を、DBMSで使用されるSQL言語の方言に変換するのは、このクラスです。 特定の構成が1つのDBMSで何をするかを知っていれば、Firebird用にこの構成を簡単に作成できます。 実際、SQL言語のDML部分はかなり標準的なものであり、少なくともLaravelを使用して構築できるクエリに関しては、さまざまなDBMSに対して大きな違いはありません。
DMLクエリ文法は、Illuminate \ Database \ Query \ Grammars \ Grammarクラスを継承します。 保護された$ selectComponentsプロパティは、クエリが\ Illuminate \ Database \ Query \ Builderビルダーによって組み立てられるSELECTクエリの部分をリストします。 compileComponentsメソッドでは、これらの部分はバイパスされ、それぞれについて、要求部分の名前とコンパイルプレフィックスで構成される名前でメソッドが呼び出されます。
protected function compileComponents(Builder $query) { $sql = []; foreach ($this->selectComponents as $component) {
この事実を知って、何をどこで修正するかが明らかになります。 次に、Illuminate \ Database \ Query \ Grammars \ Grammarクラスの子孫を作成して、Firebirdの文法を定義します-Illuminate \ Database \ Query \ Grammars \ FirebirdGrammar。 Firebirdの主な特徴を定義します。
単純なINSERTクエリの主な違いは、RETURNING句を使用して追加したばかりの行を返す機能です。 Laravelでは、これは追加したばかりの文字列の識別子を返すために使用されます。 ただし、MySQLにはこの機能がないため、compileInsertGetIdメソッドはDBMSごとに異なって見えます。 Firebirdは、Postgres DBMSと同様にRETURNING句をサポートしているため、このメソッドはPostgresの文法から取得できます。 次のようになります。
public function compileInsertGetId(Builder $query, $values, $sequence) { if (is_null($sequence)) { $sequence = 'id'; } return $this->compileInsert($query, $values) . ' returning ' . $this->wrap($sequence); }
おそらく、SELECTクエリの最も重要な違いは、クエリによって返されるレコードの数の制限です。これは、ページナビゲーションでよく使用されます。 たとえば、次の式:
DB::table('goods')->orderBy('name')->skip(10)->take(20)->get();
さまざまなDBMSで、SQLの見方が大きく異なります。 MySQLでは、次のようになります。
SELECT * FROM goods ORDER BY name LIMIT 10, 20
このようなPostgresでは:
SELECT * FROM goods ORDER BY name LIMIT 20 OFFSET 10
Firebirdには3つのオプションがあります。 バージョン1.5以降:
SELECT FIRST(10) SKIP(20) * FROM goods ORDER BY name
バージョン2.0以降、別の構造が追加されます。
SELECT * FROM goods ORDER BY name ROWS 21, 30
バージョン3.0以降、SQL-2011標準の構造が追加されました。
SELECT * FROM color ORDER BY name OFFSET 20 ROWS FETCH FIRST 10 ROWS ONLY
もちろん、最も便利で正しいオプションは標準のものですが、LaravelでFirebird 2.5と3.0の両方をサポートしたかったので、2番目のオプションを選択します。 この場合、compileLimitメソッドとcompileOffsetメソッドは次のようになります。
protected function compileLimit(Builder $query, $limit) { if ($query->offset) { $first = (int) $query->offset + 1; return 'rows ' . (int) $first; } else { return 'rows ' . (int) $limit; } } protected function compileOffset(Builder $query, $offset) { if ($query->limit) { if ($offset) { $end = (int) $query->limit + (int) $offset; return 'to ' . $end; } else { return ''; } } else { $begin = (int) $offset + 1; return 'rows ' . $begin . ' to 2147483647'; } }
クエリを区別する次のことは、日付の一部を抽出することです。これは、dateBasedWhereメソッドを使用して行われます。 Firebirdはこれに標準のEXTRACT関数を使用します。 これを念頭に置いて、メソッドは次のようになります。
protected function dateBasedWhere($type, Builder $query, $where) { $value = $this->parameter($where['value']); return 'extract(' . $type . ' from ' . $this->wrap($where['column']) . ') ' . $where['operator'] . ' ' . $value; }
それだけです。すべての主要な特徴的な機能が考慮されています。 完全に実装されたクラスIlluminate \ Database \ Query \ Grammars \ FirebirdGrammarは、記事に添付されているソースコードにあります。
DDLクエリを構築するための文法クラス
次に、データベーススキーマの構築に使用される、より複雑な文法に目を向けます。 この文法は、いわゆる移行(Laravelの観点から)に使用されます。 データ型から自動インクリメントフィールドまで、さまざまなDBMSにはさらに多くの違いがあります。 さらに、ここでは、テーブルまたは列の存在を判断するために、ここでいくつかのシステムテーブルに対するクエリを書き換える必要があります。
文法DDLクエリは、クラスIlluminate \ Database \ Schema \ Grammars \ Grammarを継承します。 独自の文法Illuminate \データベース\スキーマ\文法\ FirebirdGrammarを作成します。 保護されたプロパティ$修飾子は、テーブルフィールド修飾子をリストします。配列にリストされた修飾子ごとに、modifyで始まり、修飾子の名前が続くメソッドが必要です。 これらのメソッドは、MySQLの文法と類似していますが、Firebirdの仕様を考慮に入れて作成しています。
列修飾子のサポート class FirebirdGrammar extends Grammar { protected $modifiers = ['Charset', 'Collate', 'Increment', 'Nullable', 'Default']; protected $serials = ['bigInteger', 'integer', 'mediumInteger', 'smallInteger', 'tinyInteger'];
$ serials配列は、Increment修飾子(自動インクリメント列)が使用可能なタイプ(Laravelで使用可能)をリストします。 Laravelで利用可能なタイプは個別に検討する必要があります。 Laravelで利用可能なタイプは、移行
ドキュメントの「利用可能な列タイプ」にリストされています。 Laravelで使用可能なタイプを文法内の特定のDBMSのデータタイプに変換するには、typeという単語で始まり、その後にタイプ名が続くメソッドが使用されます。
データ型のサポート protected function typeChar(Fluent $column) { return "char({$column->length})"; } protected function typeString(Fluent $column) { return "varchar({$column->length})"; } protected function typeText(Fluent $column) { return 'BLOB SUB_TYPE TEXT'; } protected function typeMediumText(Fluent $column) { return 'BLOB SUB_TYPE TEXT'; } protected function typeLongText(Fluent $column) { return 'BLOB SUB_TYPE TEXT'; } protected function typeInteger(Fluent $column) { return $column->autoIncrement ? 'INTEGER GENERATED BY DEFAULT AS IDENTITY' : 'INTEGER'; } protected function typeBigInteger(Fluent $column) { return $column->autoIncrement ? 'BIGINT GENERATED BY DEFAULT AS IDENTITY' : 'BIGINT'; } protected function typeMediumInteger(Fluent $column) { return $column->autoIncrement ? 'INTEGER GENERATED BY DEFAULT AS IDENTITY' : 'INTEGER'; } protected function typeTinyInteger(Fluent $column) { return $column->autoIncrement ? 'SMALLINT GENERATED BY DEFAULT AS IDENTITY' : 'SMALLINT'; } protected function typeSmallInteger(Fluent $column) { return $column->autoIncrement ? 'SMALLINT GENERATED BY DEFAULT AS IDENTITY' : 'SMALLINT'; } protected function typeFloat(Fluent $column) { return $this->typeDouble($column); } protected function typeDouble(Fluent $column) { return 'double precision'; } protected function typeDecimal(Fluent $column) { return "decimal({$column->total}, {$column->places})"; } protected function typeBoolean(Fluent $column) { return 'boolean'; } protected function typeEnum(Fluent $column) { $allowed = array_map(function ($a) { return "'" . $a . "'"; }, $column->allowed); return "varchar(255) check (\"{$column->name}\" in (" . implode(', ', $allowed) . '))'; } protected function typeJson(Fluent $column) { return 'varchar(8191)'; } protected function typeJsonb(Fluent $column) { return 'varchar(8191)'; } protected function typeDate(Fluent $column) { return 'date'; } protected function typeDateTime(Fluent $column) { return 'timestamp'; } protected function typeDateTimeTz(Fluent $column) { return 'timestamp'; } protected function typeTime(Fluent $column) { return 'time'; } protected function typeTimeTz(Fluent $column) { return 'time'; } protected function typeTimestamp(Fluent $column) { if ($column->useCurrent) { return 'timestamp default CURRENT_TIMESTAMP'; } return 'timestamp'; } protected function typeTimestampTz(Fluent $column) { if ($column->useCurrent) { return 'timestamp default CURRENT_TIMESTAMP'; } return 'timestamp'; } protected function typeBinary(Fluent $column) { return 'varchar(8191) CHARACTER SET OCTETS'; } protected function typeUuid(Fluent $column) { return 'char(36)'; } protected function typeIpAddress(Fluent $column) { return 'varchar(45)'; } protected function typeMacAddress(Fluent $column) { return 'varchar(17)'; }
自動インクリメント列に関する注意 ID列は、Firebird 3.0以降で使用できます。 バージョン3.0より前では、ジェネレーターとBEFORE INSERTトリガーが同様の機能に使用されていました。 例:
CREATE TABLE USERS ( ID INTEGER GENERATED BY DEFAULT AS IDENTITY, … ); 同様の機能は次のように取得できます。
CREATE TABLE USERS ( ID INTEGER, … ); CREATE SEQUENCE SEQ_USERS; CREATE TRIGGER TR_USERS_BI FOR USERS ACTIVE BEFORE INSERT AS BEGIN IF (NEW.ID IS NULL) THEN NEW.ID = NEXT VALUE FOR SEQ_USERS; END Laravelの移行では、テーブル以外のスキーマオブジェクトはサポートされていません。 つまり シーケンスの作成と変更、さらにトリガーはサポートされていません。 ただし、シーケンスは、PostgresやMS SQL(2012年以降)など、かなり多数のDBMSの機能の一部です。 Laravel移行にシーケンスサポートを追加する方法については、この記事の後半で説明します。
|
次に、クエリが返す2つのメソッドを追加して、テーブルとテーブル内の列の存在を確認します。
public function compileTableExists() { return 'select * from RDB$RELATIONS where RDB$RELATION_NAME = ?'; } public function compileColumnExists($table) { return "select TRIM(RDB\$FIELD_NAME) AS \"column_name\" from RDB\$RELATION_FIELDS where RDB\$RELATION_NAME = '$table'"; }
compileCreateメソッドを追加して、CREATE TABLEステートメントを作成します。 同じ方法を使用して、一時的なGTTテーブルを作成します。 非常に奇妙ですが、Postgres DBMSの場合でも、1つのタイプのGTTのみが作成されます-ON COMMIT DELETE ROWSですが、両方のタイプのGTTのサポートを一度に実装します。
public function compileCreate(Blueprint $blueprint, Fluent $command) { $columns = implode(', ', $this->getColumns($blueprint)); $sql = $blueprint->temporary ? 'create temporary' : 'create'; $sql .= ' table ' . $this->wrapTable($blueprint) . " ($columns)"; if ($blueprint->temporary) { if ($blueprint->preserve) { $sql .= ' ON COMMIT DELETE ROWS'; } else { $sql .= ' ON COMMIT PRESERVE ROWS'; } } return $sql; }
Illuminate \ Database \ Schema \ Blueprintクラスには$ preserveプロパティが含まれていないため、追加する方法とインストールする方法を追加しましょう。 Blueprintクラスは、クエリまたはクエリセットを生成して、テーブルメタデータの作成、変更、削除をサポートするように設計されています。
class Blueprint {
Illuminate \ Database \ Schema \ Grammars \ FirebirdGrammar文法クラスに戻ります。 メソッドを追加して、テーブル削除演算子を作成します。
public function compileDrop(Blueprint $blueprint, Fluent $command) { return 'drop table ' . $this->wrapTable($blueprint); }
Laravelには、テーブルが存在する場合にのみテーブルを削除しようとする別の方法があります。 これは、SQL DROP TABLE IF EXISTSステートメントを使用して行われます。 Firebirdには同様の機能を持つ演算子はありませんが、匿名ブロック(EXECUTE BLOCK + EXECUTE STATEMENT)を使用してエミュレートできます。
public function compileDropIfExists(Blueprint $blueprint, Fluent $command) { $sql = 'EXECUTE BLOCK' . "\n"; $sql .= 'AS' . "\n"; $sql .= 'BEGIN' . "\n"; $sql .= " IF (EXISTS(select * from RDB\$RELATIONS where RDB\$RELATION_NAME = '" . $blueprint->getTable() . "')) THEN" . "\n"; $sql .= " EXECUTE STATEMENT 'DROP TABLE " . $this->wrapTable($blueprint) . "';" . "\n"; $sql .= 'END'; return $sql; }
次に、列、制約、およびインデックスを追加および削除するメソッドを追加します。
列、制約、およびインデックスを追加および削除する方法 public function compileAdd(Blueprint $blueprint, Fluent $command) { $table = $this->wrapTable($blueprint); $columns = $this->prefixArray('add column', $this->getColumns($blueprint)); return 'alter table ' . $table . ' ' . implode(', ', $columns); } public function compilePrimary(Blueprint $blueprint, Fluent $command) { $columns = $this->columnize($command->columns); return 'alter table ' . $this->wrapTable($blueprint) . " add primary key ({$columns})"; } public function compileUnique(Blueprint $blueprint, Fluent $command) { $table = $this->wrapTable($blueprint); $index = $this->wrap($command->index); $columns = $this->columnize($command->columns); return "alter table $table add constraint {$index} unique ($columns)"; } public function compileIndex(Blueprint $blueprint, Fluent $command) { $columns = $this->columnize($command->columns); $index = $this->wrap($command->index); return "create index {$index} on " . $this->wrapTable($blueprint) . " ({$columns})"; } public function compileDropColumn(Blueprint $blueprint, Fluent $command) { $columns = $this->prefixArray('drop column', $this->wrapArray($command->columns)); $table = $this->wrapTable($blueprint); return 'alter table ' . $table . ' ' . implode(', ', $columns); } public function compileDropPrimary(Blueprint $blueprint, Fluent $command) { $table = $blueprint->getTable(); $index = $this->wrap("{$table}_pkey"); return 'alter table ' . $this->wrapTable($blueprint) . " drop constraint {$index}"; } public function compileDropUnique(Blueprint $blueprint, Fluent $command) { $table = $this->wrapTable($blueprint); $index = $this->wrap($command->index); return "alter table {$table} drop constraint {$index}"; } public function compileDropIndex(Blueprint $blueprint, Fluent $command) { $index = $this->wrap($command->index); return "drop index {$index}"; } public function compileDropForeign(Blueprint $blueprint, Fluent $command) { $table = $this->wrapTable($blueprint); $index = $this->wrap($command->index); return "alter table {$table} drop constraint {$index}"; }
次の内容の移行を作成して実行することにより、クラスのパフォーマンスをテストできます。 use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateUsersTable extends Migration { public function up() { Schema::create('users', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->string('email')->unique(); $table->string('password'); $table->rememberToken(); $table->timestamps(); }); } public function down() { Schema::drop('users'); } }
コマンドで開始した結果: php artisan migrate
次のDDLを使用してテーブルが作成されます。 CREATE TABLE "users" ( "id" INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, "name" VARCHAR(255) NOT NULL, "email" VARCHAR(255) NOT NULL, "password" VARCHAR(255) NOT NULL, "remember_token" VARCHAR(100), "created_at" TIMESTAMP, "updated_at" TIMESTAMP ); ALTER TABLE "users" ADD CONSTRAINT "users_email_unique" UNIQUE ("email");
次のコマンドを使用して、移行をロールバックできます。 php artisan migrate:reset
シーケンスサポートの追加
テーブルメタデータの作成、変更、削除をサポートするクエリまたはクエリセットを生成するように設計されたBlueprintクラスと同様に、シーケンスの同じアクションをサポートするSequenceBlueprintクラスを作成します。このクラスは非常に単純です。全体を説明するのではなく、同様のブループリントクラスとの主な違いのみを説明します。Firebirdのシーケンスには、次の属性があります。シーケンス名、初期値、および増分。NEXTVALUE FORステートメントで使用されます。最後の属性は、バージョン3.0以降で使用可能です。したがって、クラスには次のプロパティが含まれます。 protected $sequence; protected $start_with = 0; protected $increment = 1; protected $restart = false;
値を取得してこれらのプロパティを設定する方法は基本的なため、ここでは説明しません。ALTER SEQUENCEステートメントでRESTART句を生成するときに使用される再起動メソッドのみを提供します。 public function restart($startWith = null) { $this->restart = true; $this->start_with = $startWith; }
ブループリントクラスと同様に、作成またはドロップが指定されていない場合、alter sequenceコマンドが実行されます。 protected function creating() { foreach ($this->commands as $command) { if ($command->name == 'createSequence') { return true; } } return false; } protected function dropping() { foreach ($this->commands as $command) { if ($command->name == 'dropSequence') { return true; } if ($command->name == 'dropSequenceIfExists') { return true; } } return false; } protected function addImpliedCommands() { if (($this->restart || ($this->increment !== 1)) && ! $this->creating() && ! $this->dropping()) { array_unshift($this->commands, $this->createCommand('alterSequence')); } } public function toSql(Connection $connection, Grammar $grammar) { $this->addImpliedCommands(); $statements = [];
Illuminate \ Database \ Schema \ SequenceBlueprintクラスの完全なコードは、記事に添付されているソースコードにあります。今度は、Illuminate \ Database \ Schema \ Grammars \ FirebirdGrammar文法クラスに戻り、{CREATE | ALTER | DROP}シーケンス。オペレーターサポート{CREATE | ALTER | ドロップ}シーケンス public function compileCreateSequence(SequenceBlueprint $blueprint, Fluent $command) { $sql = 'create sequence '; $sql .= $this->wrapSequence($blueprint); if ($blueprint->getInitialValue() !== 0) { $sql .= ' start with ' . $blueprint->getInitialValue(); } if ($blueprint->getIncrement() !== 1) { $sql .= ' increment by ' . $blueprint->getIncrement(); } return $sql; } public function compileAlterSequence(SequenceBlueprint $blueprint, Fluent $command) { $sql = 'alter sequence '; $sql .= $this->wrapSequence($blueprint); if ($blueprint->isRestart()) { $sql .= ' restart'; if ($blueprint->getInitialValue() !== null) { $sql .= ' with ' . $blueprint->getInitialValue(); } } if ($blueprint->getIncrement() !== 1) { $sql .= ' increment by ' . $blueprint->getIncrement(); } return $sql; } public function compileDropSequence(SequenceBlueprint $blueprint, Fluent $command) { return 'drop sequence ' . $this->wrapSequence($blueprint); } public function compileDropSequenceIfExists(SequenceBlueprint $blueprint, Fluent $command) { $sql = 'EXECUTE BLOCK' . "\n"; $sql .= 'AS' . "\n"; $sql .= 'BEGIN' . "\n"; $sql .= " IF (EXISTS(select * from RDB\$GENERATORS where RDB\$GENERATOR_NAME = '" . $blueprint->getSequence() . "')) THEN" . "\n"; $sql .= " EXECUTE STATEMENT 'DROP SEQUENCE " . $this->wrapSequence($blueprint) . "';" . "\n"; $sql .= 'END'; return $sql; } public function wrapSequence($sequence) { if ($sequence instanceof SequenceBlueprint) { $sequence = $sequence->getSequence(); } if ($this->isExpression($sequence)) { return $this->getValue($sequence); } return $this->wrap($this->tablePrefix . $sequence, true); }
さて、Laravel移行でのシーケンスサポートの追加は完了しました。それがどのように機能するかを見てみましょう。このため、先ほどの移行を少し変更します。シーケンス上のDDLをテストするための移行 class CreateUsersTable extends Migration { public function up() {
さらに進んで、BEFORE INSERTトリガーとシーケンス(ジェネレーター)の作成をサポートして、Firebird 2.5以前で自動インクリメントフィールドをサポートできます。ただし、ほとんどの場合、シーケンスの次の値を取得してINSERT要求に渡すだけで十分です。おわりに
上記の変更は、Laravelフレームワークを使用してFirebird DBMSを使用してWebアプリケーションを開発するのに十分です。もちろん、これをパッケージとして設計し、それを接続して機能を拡張するといいでしょう。これは他のLaravelモジュールで行われます。次の記事では、LaravelとFirebird DBMSを使用して小さなアプリケーションを作成する方法について説明します。 FirebirdをLaravelフレームワークに統合することに興味がある場合、またはエラーを見つけた場合は、個人的な返信を書いてください。 Laravel for Firebirdサポート用に変更されたファイルは、ここからダウンロードできます。