
問題のステートメントとその解決策
まず、ログインのみで管理インターフェイスを介してアプリケーションを更新する必要があることに同意します。その前に、すべてのページのリクエストに503の回答が与えられます。
中間バージョンもキックバックも必要ないため、サイトはすぐに最新バージョンに更新されます。
訪問者にアラートを追加
移行の統合を行ったプロジェクトでは、すべてのコントローラーは基本的なCI_Controllerではなく、データベースを含むコンストラクターにいくつかのユーティリティアクションを含む拡張されたMY_Controllerを継承します。 したがって、ファイル%site_path%/ application / core / MY_Controller.phpについては、数行を追加する必要があります。
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); class MY_Controller extends CI_Controller { protected $db_update = FALSE; // it's TRUE if site's database needs update, FALSE otherwise public function __construct() { parent::__construct(); $is_admin_page = is_a($this, 'Admin'); $this->db_update = $this->migration->get_fs_version()!=$this->migration->get_db_version(); if ($this->db_update) { if (!$is_admin_page) show_error(', ', 503, ', '); else return TRUE; } ### Your super overpowered code goes here.. } }
注:前の記事と同様に、すべてのソースファイルは記事の最後にリストされています。
コード全体は理解できると思いますが、管理ページ( MY_Controllerを継承する管理コントローラー)を除くすべての場所にエラーを表示することに注意してください。 ただし、管理パネルの場合、コンストラクターをこれ以上実行しません。 古い構造を持つデータベースへの呼び出しが含まれる場合があります。 ところで、ご覧のとおり、親コンストラクターのコードは、 デコレーターパターンを実装するコンストラクターで最初に呼び出されます。
管理パネルから更新スクリプトを作成します
私の場合、管理パネル全体が同じ管理コントローラーに含まれていたため、例の簡略化のために同じケースを取り上げます。
この管理コントローラーには、サイトのコンテンツを管理できるさまざまな方法が含まれています。 正直言って、非常に優れたエレガントなソリューションではありません-異なるコントローラー間で配布するか、CodeIgniterのHMVCプラグインを使用することを強くお勧めします(すでにハブでの使用の良い例がありました)
そのため、管理パネルにログインできるようにするタスクがあり、どのページでもデータベースを更新するように提案されました。 このため、magic _remapメソッドはperfectであり、いずれかのコントローラーメソッドにアクセスするときに呼び出され、決定を行い、要求されたメソッドに制御を転送するか
public function _remap($method, $params = array()) { if (!$this->m_user->authorised() && $method != 'index') { header('Location:/admin/'); //If user isn't autorised, redirect him to the login form } if (!$this->db_update || (!$this->m_user->authorised() && $method== 'index') || $method=='logout' || $method=='update_db') { return call_user_func_array(array($this, $method), $params); // Calls requested method if it is ok to do so } else { $this->data['body'] = '<h1>!</h1> <a href="/admin/update_db"> </a>'; // Show update database link $this->load->view('admin/default.phtml', $this->data); } }
ここで、 m_userは管理ユーザーと連携するためのすべてのメソッドを含むモデルです(自分で実装することをお勧めします)。 インデックスメソッドは、ログインしていないユーザーのログインフォームを表示できますが、 ログアウトすると明らかになります。
さらに、そこでデータベースを更新するメソッドを作成します。
public function update_db() { $this->data['body'] = '<h1> </h1>'; if ( ! $this->migration->current()) { show_error($this->migration->error_string()); } $this->load->view('admin/default.phtml', $this->data); }
設定を編集してテストする
最後に、構成を修正することは残っており、プロジェクト用に作成したすべてを活用できます。 これを行うには、 Migrationクラスをスタートアップに追加します。 私の場合、ライブラリを自動初期化する行は次のようになります(ファイル%site_path%/ application / config / autoload.php ):
$autoload['libraries'] = array('database', 'session', 'migration');
また、ファイル%site_path%/ application / config / migration.phpで移行がオンになっているかどうかを確認する必要があります。コードが正しく機能するために必要なデータベースのパスとバージョンが指定されているかどうかを確認します(すべてが前のものとまったく同じです) 記事 ):
$config['migration_enabled'] = TRUE; $config['migration_version'] = 1; $config['migration_path'] = APPPATH . 'migrations/';
最初のバージョンを示したことに注意してください。 これは、 前のチュートリアルで移行を記述したメーリングリスト機能を既に実行していることを意味します。
これで、管理パネルに関係のないサイトのページにアクセスでき、エラーメッセージが表示されるはずです。 データベースのゼロバージョンがあり(最初の初期化中に、 移行ライブラリがデータベースに移行プレートを作成し、そこにバージョン0を示します)、コードの最初のバージョンが構成で指定されます。 管理パネルにアクセスしてログインすると、データベースを更新する提案が表示されます。リンクをクリックすると、すべてのリクエストを手動で完了することなく、新しいアプリケーションが取得されます。
ボーナス-CLI経由でスクリプトを更新
ボーナスとして、 cliを介して更新するスクリプトを作成することを検討してください。これにより、たとえば、フックを使用したバージョン管理システムからサイトにアップロードされた移行を自動化できます。
さいわい、最新バージョンのCodeIgniterには、すぐに使用できるコマンドラインから実行する機能があります。 したがって、 まず 、プライベート変数$ argsを使用してコントローラー%site_path%/ application / controllers / cli.phpを作成します。これには、コントローラーの名前とそのメソッドを除く、スクリプトが呼び出されたすべての引数が含まれます(コンストラクターでそれらを切り取ります):
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); class Cli extends MY_Controller { private $args = array(); // Contains CLI arguments, except controller name and its method public function __construct() { parent::__construct(); if(!$this->input->is_cli_request()) { show_404(); } $this->output->enable_profiler(FALSE); $this->args = array_slice($_SERVER['argv'], 3); } // Other code goes here.. }
ところで、コンストラクター内の場所に注意を払うことをお勧めします。コンストラクターでは、要求がCLI経由で送信されたかどうかがチェックされます。 サイトを通じてサービスメソッドを実行することは望ましくありません。 ご覧のとおり、ここでプロファイラーも無効にしました。 テストサーバーではデフォルトでオンになっていますが、CLIでは明らかに不要です。
最後に、移行のためのメソッドを作成します。
public function migration() { if ( !is_array($this->args) || empty($this->args)) { print ( "Usage: php index.php cli migration [OPTIONS]\n\n" ); print ( "Options are:\n" ); print ( "-l, --last\t\tupdate database to the latest version\n" ); print ( "-c, --current\t\t show current versions of database and code\n" ); exit; } for ( $i=0; $i<count($this->args); $i++ ) { $arg = $this->args[$i]; if ( $arg=="-l" || $arg=="--last" ) { print "Updating your database to the latest version..\n"; if (!$this->migration->current()) { print $this->migration->error_string().'\n'; exit; } else print "Update complete!\n"; } elseif ( $arg=="-c" || $arg=="--current" ) { print 'Current code version is:\t'. $this->migration->get_fs_version().'\n'; print 'Current database version is:\t'.$this->migration->get_db_version().'\n'; } } }
それを呼び出すには、追加の属性なしでコマンドラインで「 php /%index_dir%/index.php cli migration 」と入力するだけで、スクリプトは使用可能なオプションを親切に教えてくれます。 「 php /%index_dir%/index.php cli migration -l 」と入力すると、メソッドはデータベースを更新して結果を表示しようとします。
もちろん、このコードは基本的なものだけを実行する例にすぎませんが、CLIと移行の使用に関する一般的なアイデアを提供します。たとえば、指定されたリビジョンの前にデータベースを更新する-rオプションを追加することは難しくありません簡単な宿題になります)。
おわりに
これで、プロジェクトに統合されたシンプルでありながらデバッグされたデータベース更新メカニズムができました。これにより、とりわけ、現在の更新についてユーザーに警告することができます。 同意します。これは、データベースとコードのバージョンの不整合、またはその他の不備に関連するバグを見つけた場合よりも優れています。 さらに、お気に入りのバージョン管理システムにフックを追加できるようになりました。これにより、新しいバージョンのサイトをアップロードするときにデータベースが自動的に更新されます。
完全なソースでアーカイブをダウンロードする
パートI:データベースの移行-ライブラリとその使用の概要