カテゴリー: PHP
CodeIgniter3のチュートリアルをリファクタリング(7)
(6)の続きです。
(6)では、ログインフォームのviewを作成しました。
次はデータを受け取ってのログイン処理ですね!
そろそろタイトルを変えたほうがいい気がしてて、モヤモヤしてますがこのままいきます。
ログインのために必要なログインIDとパスワードがPOSTで届きます。
該当するログインユーザーが存在するかチェックをして、存在していたらログインしている情報をSESSIONで維持します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
<?php defined('BASEPATH') OR exit('No direct script access allowed'); application/controllers/Auth.php /** * 認証 * Class Auth */ class Auth extends CI_Controller { /** * ログイン */ public function login() { if($this->input->post()) { $login_id = $this->input->post('login_id') ; $password = $this->input->post('password') ; //$login_idと$passwordが合致するかチェック //合致したらnewsの新規作成画面へリダイレクトする //合致しなければエラーを表示する return ; } //フォームヘルパーとURLヘルパーを使えるようにする $this->load->helper(['form', 'url']); //ログインフォームを表示する $this->load->view('Auth/login') ; } /** * ログアウト */ public function logout() { //ログアウト完了画面 echo 'ログアウト'; } } |
で、どこでこのパスワードをチェックするかですがModeldでやります。
application/models/Auth_model.php
ファイルを作ります。
最初の1文字目は大文字です。
1 2 3 4 5 6 7 8 9 10 |
<?php defined('BASEPATH') OR exit('No direct script access allowed'); /** * Class Auth_model */ class Auth_model extends CI_Model { } |
なんといってもログインするユーザーがいないことにはログインできないよね、
なので今日作る最低限の機能はこの2つ。
(1) ユーザの作成
(2) パスワードのチェック
Modelを作るところから始めるんだけど、unitTestしながらコードを書きたいよね。
なのでまずはModelのテストが書ける状態を作るよ!
まずは、テスト用のデータベースの用意ね。
ci3_tutorial_test という名前のデータベースを用意するよ!
1 2 |
mysql -uci3_user create database ci3_tutorial_test |
データベースの設定をしたのを覚えてるかな?
application/config/database.php
この設定のままテストを実行すると、このデータベース上でテストが実行されてしまうんだ。
結果データが消えたり、増えたりする。
それはちょっとダメだよね?
なのでテスト用のデータベースの設定を用意するよ!
application/config/tests/database.php
testsに関する設定はtestsフォルダの中を見てくれるんだ。
ここにないファイルは、application/config/の中の物を使ってくれる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
$active_group = 'default'; $query_builder = TRUE; $db['default'] = array( 'dsn' => '', 'hostname' => 'localhost', 'username' => 'ci3_user', 'password' => 'CodeIgniter_Love', 'database' => 'ci3_tutorial_test', 'dbdriver' => 'mysqli', 'dbprefix' => '', 'pconnect' => FALSE, 'db_debug' => (ENVIRONMENT !== 'production'), 'cache_on' => FALSE, 'cachedir' => '', 'char_set' => 'utf8', 'dbcollat' => 'utf8_general_ci', 'swap_pre' => '', 'encrypt' => FALSE, 'compress' => FALSE, 'stricton' => FALSE, 'failover' => array(), 'save_queries' => TRUE ); |
次に、0地点のMigrationファイルを作成するよ
application/migrations/00000000000000_start.php
中身は空っぽのこんな感じ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<?php /** * 0地点 * Class Migration_start */ class Migration_start extends CI_Migration { /** * migrationの実行 */ public function up() { } /** * rollbackの実行 */ public function down() { } } |
次にModelの用意ね!
テストファイルも一緒に作るよ
application/models/Auth_model.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<?php defined('BASEPATH') OR exit('No direct script access allowed'); /** * ログインユーザとかログインのチェックしてくれるModel * Class Auth_model */ class Auth_model extends CI_Model { /** * Auth_model constructor. */ public function __construct() { parent::__construct(); } //TODO: ログインチェックを書く //TODO: ユーザの新規作成を書く } |
次はテストファイルね!
application/tests/models/Auth_model_test.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
<?php class Auth_model_test extends TestCase { /** * @var Object */ private $migration; /** * setup */ public function setUp() { //migrationの実行 $this->migration = $this->newLibrary('Migration'); $this->migration->latest(); $this->obj = $this->newModel('Auth_model'); } /** * tearDown */ public function tearDown() { parent::tearDown(); //migrationの実行 $this->migration->version(00000000000000); } //TODO: テスト書くぞー! } |
Auth_model_testのsetUp()では、migrationで0地点、create databaseした直後まで戻り、
テストの実行が終わったらテストを実行する前に最新の状態にするようにしています。
もっと機能が育って、テストに時間がかかるようになったなら違う方法に変えても良いでしょう。
テスト前にトランザクションをセットし、テスト後にrollbackする方法などいろいろな方法があります。
dumpファイルで関連テーブルごとリストアするって手もありますね。
テストを書きながらModelを書いていく環境ができました!
大丈夫だよー。
少しずつすすめて行こうねー!
続きます。
< 随時更新していきます>
CodeIgniter3のチュートリアルをリファクタリング(6)
クリスマスですね!
なんと最終日!!!!!
アドベントカレンダー全部埋まってます。なんという奇跡!
この記事はCodeIgniterアドベントカレンダーのために書きました! 25日目最終日!!!
https://qiita.com/advent-calendar/2017/code_igniter
CodeIgniter3のチュートリアルをリファクタリング(5) では、ログインフォームのviewファイルを用意するところまで終わりましたよ! アドベントカレンダーが終わっても記事はこのまま書き続けてしまおうと思います。はい!
viewファイルを作り始めました。
とりあえず、formを全てHTMLで作ってみましたが、CodeIgnier3にはform helperがあるんですよね!
今日のテーマは、
formをform helperを使って書こう!
です
https://www.codeigniter.com/user_guide/helpers/form_helper.html
form helperを使えるようにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
< ?php defined('BASEPATH') OR exit('No direct script access allowed'); /** * 認証 * Class Auth */ class Auth extends CI_Controller { /** * ログイン */ public function login() { //フォームヘルパーを使えるようにする $this->load->helper('form'); //ログインフォームを表示する $this->load->view('Auth/login') ; } /** * ログアウト */ public function logout() { //ログアウト完了画面 echo 'ログアウト'; } } |
次は実際にviewファイルで使ってみますね。
formタグ部分がhelperになりました。
1 2 3 4 5 6 7 |
< ?php echo form_open('/login'); echo form_input("login_id" , "" , ['class'=>'form-control', 'placeholder'=>'ログインID' ]); echo form_password("password" , "" , ['class'=>'form-control', 'placeholder'=>'パスワード' ]); echo form_submit('login', "ログイン", ['class'=>'btn btn-primary form-control']); echo form_close(); ?> |
この部分の出力されたHTMLはこんな感じになります。
1 2 3 4 5 |
<form action="http://{設置した場所}/login" method="post" accept-charset="utf-8"> <input type="text" name="login_id" value="" class="form-control" placeholder="ログインID" /> <input type="password" name="password" value="" class="form-control" placeholder="パスワード" /> <input type="submit" name="login" value="ログイン" class="btn btn-primary form-control" /> </form> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
<?php defined('BASEPATH') OR exit('No direct script access allowed'); /** * 認証 * Class Auth */ class Auth extends CI_Controller { /** * ログイン */ public function login() { if($this->input->post()) { echo "POSTデータを取得<br>"; echo $this->input->post('login_id') ; return ; } //フォームヘルパーとURLヘルパーを使えるようにする $this->load->helper(['form', 'url']); //ログインフォームを表示する $this->load->view('Auth/login') ; } /** * ログアウト */ public function logout() { //ログアウト完了画面 echo 'ログアウト'; } } |
実際にフォームボタンを押してみましょう。
POSTデータを取得
{実際に入力したログインID}
が表示されました☆
postデータがあれば、$this->input->post(); ではPOSTされた値が配列で取得できます。
フォームと、ログインの情報が送信された場合の出しわけができました。
次に、実際にログインの処理を作っていきましょう
CodeIgniter3のチュートリアルをリファクタリング(5)
クリスマスイブですね!
みなさま今日はケーキの準備は万全ですか?
この記事はCodeIgniterアドベントカレンダーのために書きました! 24日目です!
https://qiita.com/advent-calendar/2017/code_igniter
CodeIgniter3のチュートリアルをリファクタリング(4) ではデータベースの準備まで終わりました。
やっとコードを書いていきますよ!
今日のテーマは
ログイン機能を作りながら、viewファイル使ってみよう!
です
各画面のURLを決めます。
要件定義で書いたIFDAM図を元に、起点となる画面とURL考えます。
(1) ログイン /login
(2) ログアウト /logout
(3) 記事一覧 /news/
(4) 記事詳細 /news/detail/{記事のslug}
(5) 新規投稿フォーム /news/create
(6) トップページ /
ログイン機能 / ログアウト機能
まずはログインログアウト機能を作成します。
ログインしている状態、していない状態について決めます。
(詳細設計ですね)
- ログイン状態の管理はsessionで行います。
- user.idとuser.nameをsession中で保持します。
- この情報がsessionの中にあり、DBにも存在していればログインしている状態とします。
- IDはemailを利用します
- パスワードは暗号化して保存します。
- 暗号化のキーは、configで設定する暗号化キーと、ユーザ別のsaltキーで作成します。
Controllerを作成
application/controller/Auth.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
< ?php defined('BASEPATH') OR exit('No direct script access allowed'); /** * 認証 * Class Auth */ class Auth extends CI_Controller { /** * construct * Auth constructor. */ public function __construct() { parent::__construct(); } /** * ログイン */ public function login() { echo 'ログイン'; } /** * ログアウト */ public function logout() { echo 'ログアウト'; } } |
ルーターの設定
application/config/routes.php
ログイン、ログアウトのURL用意しますね。
1 2 3 4 5 |
$route['login'] = 'auth/login'; $route['logout'] = 'auth/logout'; $route['default_controller'] = 'welcome'; $route['404_override'] = ''; $route['translate_uri_dashes'] = FALSE; |
http://{設置した場所}/login
http://{設置した場所}/logout
それぞれで、login logout の文字は表示されましたね!
次はviewファイルを用意しますよー
画面の用意
まずは、login画面から作っていきましょうか!
viewファイルは、application/viewsフォルダの中に作ります。
機能に分けてviewファイルをフォルダ分けしたほうが後で探しやすいので、Authフォルダを作りその中にlogin用のviewファイルを用意しますね。
application/views/Auth/login.php
表示するHTMLを用意します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
<!doctype html> <html lang="ja"> <head> <title>Hello, world!</title> <!-- Required meta tags --> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <!-- Bootstrap CSS --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" integrity="sha384-PsH8R72JQ3SOdhVi3uxftmaW6Vc51MKb0q5P2rRUpPvrszuE4W1povHYgTpBfshb" crossorigin="anonymous"> </head> <body> <h1>ログイン</h1> <div class="container"> <form> <input type="text" class="form-control" placeholder="ログインID"> <input type="password" class="form-control" placeholder="パスワード"> <button type="submit" class="btn btn-primary form-control">ログイン</button> </form> </div> <!-- Optional JavaScript --> <!-- jQuery first, then Popper.js, then Bootstrap JS --> <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.3/umd/popper.min.js" integrity="sha384-vFJXuSJphROIrBnz7yo7oB41mKfc8JzQZiCq4NCceLEaO4IHwicKwpJf9c9IpFgh" crossorigin="anonymous"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/js/bootstrap.min.js" integrity="sha384-alpBpkh1PFOepccYVYDB4do5UnbKysX5WZXm3XxPqe5iKTfUKjNkCk9SaVuEZflJ" crossorigin="anonymous"></script> </body> </html> |
このHTMLをloginへアクセスがされた場合に表示をしてみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
< ?php defined('BASEPATH') OR exit('No direct script access allowed'); /** * 認証 * Class Auth */ class Auth extends CI_Controller { /** * ログイン */ public function login() { //ログインフォームを表示する $this->load->view('Auth/login') ; } /** * ログアウト */ public function logout() { //ログアウト完了画面 echo 'ログアウト'; } } |
http://{設置したURL}/login
ここまでは表示されたでしょうかね?
(次に続きます)
CodeIgniter3のチュートリアルをリファクタリング(4) データベースの準備
かつて、こんなにも毎日のようにブログをかいた時期ってあったっけかな?と思う@NEKOGETです。コンバンワ。
この記事はCodeIgniterアドベントカレンダーのために書きました! 23日目です!
https://qiita.com/advent-calendar/2017/code_igniter
22日目の記事は bj1024さん の「CodeIgniter3 CLI利用時の引数の挙動」でした!
さて、この記事ですが、タイトルからもわかる通り、CodeIgniter3のチュートリアルをリファクタリング(3) の続編です。
と続いて、今回はデータベースの準備です。
データベースの準備
mysqlへの接続 DBの作成
1 |
$ mysql -uci3_user -p |
パスワードの入力
1 |
CodeIgniter_Love |
(このユーザーとパスワードはansibleで作成設定しています。)
データベースの作成
1 |
mysql> create database ci3_tutorial |
1 2 3 4 5 6 7 8 9 10 11 |
mysql> show databases ; +--------------------+ | Database | +--------------------+ | information_schema | | ci3_tutorial | | mysql | | performance_schema | | test | +--------------------+ 5 rows in set (0.00 sec) |
できました。
configの設定 データベース
application/config/database.phpの設定です。
これはデータベースへの接続情報ですね。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
$active_group = 'default'; $query_builder = TRUE; $db['default'] = array( 'dsn' => '', 'hostname' => 'localhost', 'username' => 'ci3_user', 'password' => 'CodeIgniter_Love', 'database' => 'ci3_tutorial', 'dbdriver' => 'mysqli', 'dbprefix' => '', 'pconnect' => FALSE, 'db_debug' => (ENVIRONMENT !== 'production'), 'cache_on' => FALSE, 'cachedir' => '', 'char_set' => 'utf8', 'dbcollat' => 'utf8_general_ci', 'swap_pre' => '', 'encrypt' => FALSE, 'compress' => FALSE, 'stricton' => FALSE, 'failover' => array(), 'save_queries' => TRUE ); |
CodeIgniter3で使えるデータベースはMySQLだけではありません。
今回は私が使い慣れているからmysqlですが他に使えるデータベースは他にもあります。
config/database.phpには次のように記載がされています。
1 2 3 4 |
['dbdriver'] The database driver. e.g.: mysqli. | Currently supported: | cubrid, ibase, mssql, mysql, mysqli, oci8, | odbc, pdo, postgre, sqlite3, sqlsrv |
ここでは細かい解説は避けますが、情報を追えるようにリンクを貼り付けておきますね。
今回はMySQLでいきます。
- mysqli
- cubrid
- ibase : Firebird/InterBase
- mssql : Microsoft SQL Server
- mysql
- mysqli
- oci8 : Oracle OCI8
- odbc
- pdo
- postgre
- sqlite3
- sqlsrv : PHP 用 Microsoft SQL Server ドライバ
Migration Classの作成
先日の記事「CodeIgniter3 migrationの話をば。」 のおさらいでもあります。
Migration Classを作ります。
application/controllers/Migrate.php
(正直もうこのControllerは先にあってもいいのではないかとさえ思います)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
< ?php class Migrate extends CI_Controller { function __construct() { parent::__construct(); //ターミナルからの実行でなければ処理しない。 if(! $this->input->is_cli_request()) { show_404(); exit; } $this->load->library('migration'); } public function index() { if ($this->migration->latest() === FALSE) { show_error($this->migration->error_string()); } } public function rollback($version) { if ($this->migration->version($version)) { echo "Migration Success.\n"; } else { show_error($this->migration->error_string()); } } } |
Configの設定
application/config/migration.php を編集します。
1 2 3 4 |
$config['migration_enabled'] = TRUE; $config['migration_path'] = APPPATH.'migrations/'; $config['migration_type'] = 'timestamp'; $config['migration_auto_latest'] = true; |
migrationを使用可能にして、
migrationのファイルを保存するフォルダを指定して
migrationのファイルをつくるのにtimestamp使いますを指定します。YYYYMMDDHHIISS フォーマットなので、(e.g. 20171213100537) です。
都度バージョンを指定するのは面倒なので、マイグレーションのバージョンは自動で最新にしといてね設定をtrueに変更です。
Migrationファイルを保存する場所を作る
Migrationファイルを保存する場所を作ります。configに書いた、$config[‘migration_path’] = APPPATH.’migrations/’;がそれですね。
1 |
mkdir application/migrations/ |
準備ができました。
Migration ファイルの作成
手動でファイルを作るのは大変なので、コマンドで空ファイルを作っちゃいましょうか
1 |
$ echo -n > application/migrations/`date '+%Y%m%d%H%M%S'`_add_news.php |
空ファイルができました。
application/migrations/20171222051205_add_news.php
次はこのファイルを編集します。
mysql WorkBenchで作成したSQLがあります。
覚えてますか? CodeIgniter3のチュートリアルをリファクタリング(1) で作ったあれです。設計したからこそこの時点でSQLが存在してるわけですよねー。
1 2 3 4 5 6 7 8 9 10 11 |
CREATE TABLE IF NOT EXISTS `mydb`.`users` ( `id` INT NOT NULL AUTO_INCREMENT, `name` VARCHAR(45) NULL, `email` VARCHAR(45) NULL, `salt` VARCHAR(45) NULL, `password` BINARY(255) NULL, `status` TINYINT(2) NULL, `created_at` DATETIME NULL, `updated_at` DATETIME NULL, PRIMARY KEY (`id`)) ENGINE = InnoDB |
1 2 3 4 5 6 7 8 9 10 11 12 |
CREATE TABLE IF NOT EXISTS `mydb`.`news` ( `id` BIGINT(20) NOT NULL AUTO_INCREMENT, `title` VARCHAR(50) NULL, `slug` VARCHAR(150) NULL, `text` TEXT NULL, `create_user_id` INT(10) NULL, `created_at` DATETIME NULL, `updated_user_id` INT(10) NULL, `updated_at` DATETIME NULL, PRIMARY KEY (`id`), UNIQUE INDEX `slug_uq` (`slug` ASC)) ENGINE = InnoDB |
これを元に作ります。
( しまった…. コメントを付けるのを忘れていました。 )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
< ?php /** * newsテーブルを追加する * Class Migration_add_news */ class Migration_add_news extends CI_Migration { /** * migrationの実行 */ public function up() { $this->load->database(); //usersの作成 $sql = 'CREATE TABLE IF NOT EXISTS `users` ( `id` INT(10) NOT NULL AUTO_INCREMENT, `name` VARCHAR(45) NULL COMMENT "名前", `email` VARCHAR(255) NULL COMMENT "メールアドレス", `salt` VARCHAR(255) BINARY NULL COMMENT "暗号キー", `password` VARCHAR(255) BINARY NULL COMMENT "パスワード", `status` TINYINT(2) NULL COMMENT "状態 0:無効 1:有効", `created_at` DATETIME NULL COMMENT "作成日", `updated_at` DATETIME NULL COMMENT "更新日", PRIMARY KEY (`id`)) ENGINE = InnoDB COMMENT="ユーザー(記事を変更できる人)"; '; $this->db->query($sql); //newsの作成 $sql = 'CREATE TABLE IF NOT EXISTS `news` ( `id` BIGINT(20) NOT NULL AUTO_INCREMENT, `title` VARCHAR(50) NULL COMMENT "タイトル", `slug` VARCHAR(150) NULL COMMENT "slug(URL)", `text` TEXT NULL COMMENT "本文", `create_user_id` INT(10) NULL COMMENT "作成者", `created_at` DATETIME NULL COMMENT "作成日", `updated_user_id` INT(10) NULL COMMENT "最終更新者", `updated_at` DATETIME NULL COMMENT "最終更新日", PRIMARY KEY (`id`), UNIQUE INDEX `slug_uq` (`slug` ASC)) ENGINE = InnoDB COMMENT="ニュース"; '; $this->db->query($sql); } /** * rollbackの実行 * newsテーブルのdrop */ public function down() { //usersの削除 $this->dbforge->drop_table('users'); //newsの削除 $this->dbforge->drop_table('news'); } } |
MySQL WorkBenchで作成した場合にはDB名がcreate文についちゃってますので、削除しました。あとはそのままのSQLを使うことにします。
create table時のコメントはとても重要です。つけておきましょう。
MySQL WorkBenchでコメント付けられます。生成したファイルについてなければつけてから、SQLを再度作成すると良いですね。
最初のmigrateファイルができました。
Migrationの実行
1 |
$ php /var/www/ci3/public/index.php Migrate index |
データベースにテーブルができました。
ロールバックについては今回の記事では省略します。
CodeIgniter3 migrationの話をば。 を参照ください。
データベースの準備ができました。
(5)へ続きます。
CodeIgniter3のチュートリアルをリファクタリング(3)
こんにちわ! NEKOGETです。
この記事はCodeIgniterアドベントカレンダーのために書きました! 21日目です!
https://qiita.com/advent-calendar/2017/code_igniter
20日目の記事は、 アドベントカレンダーの効能 でした!
内容としては、 CodeIgniter3のチュートリアルをリファクタリング(2) の続きになります!
AWS Lightsail は80と22ポートがデェフォルトで開いています。ビルドインサーバーで8000で立ち上げてしまうのもアリですが、今日はhttpdさんに頑張ってもらうことにします。
ソースコードの移動
1 2 3 4 5 |
$ sudo mv ci3 /var/www/ $ sudo rm -irf /var/www/html $ sudo ln -s /var/www/ci3/public /var/www/html $ chmod 755 /var/www/ci3/public $ sudo service httpd restart |
URLを叩いてWelcomeページが見えるか確認してみましょう
表示されました
configの設定
application/config/config.phpの設定
ベースURLの設定をします。今回はチュートリアルなのでipアドレスからのURLで良いでしょう。
1 |
$config['base_url'] = ''; |
起点となるファイルのパスを記載します。
デェフォルトではindex.phpです。
今回はkenjisさんの提供してくれているパッケージでプロジェクトを作ったのですでにmod_writeの設定が.htaccessで設置されていますので、ブランクになっています。
1 |
$config['index_page'] = ''; |
1 2 |
次は言語設定ですね。 デェフォルトは英語です。ここはjapaneseに変えておきましょうか |
1 |
$config['language'] = 'japanese'; |
composerのautoloaderを使うかどうかの設定がありますね。
trueにしておきましょう
1 |
$config['composer_autoload'] = FALSE; |
今回はsessionはfileのままで行こうかと思います。
なのでそのままデェフォルト値で良いでしょう
1 2 3 4 5 6 7 |
$config['sess_driver'] = 'files'; $config['sess_cookie_name'] = 'ci_session'; $config['sess_expiration'] = 7200; $config['sess_save_path'] = NULL; $config['sess_match_ip'] = FALSE; $config['sess_time_to_update'] = 300; $config['sess_regenerate_destroy'] = FALSE; |
unitTest実行用ライブラリの追加
https://github.com/kenjis/ci-phpunit-test
composer installします。
1 2 3 4 |
$ cd /var/www/ci3 $ composer require phpunit/phpunit --dev $ composer require kenjis/ci-phpunit-test --dev $ php vendor/kenjis/ci-phpunit-test/install.php |
testsフォルダへ移動
1 |
cd application/tests |
1 |
../../vendor/phpunit/phpunit/phpunit |
しかし、../../vendor/phpunit/phpunit/phpunit はちょっと遠いね。
1 |
$ ln -s ../../vendor/phpunit/phpunit/phpunit ./ |
1 |
./phpunit |
テストが実行できる状態になりました。
次へ続きます。
CodeIgniter3のチュートリアルをリファクタリング(2)
こんにちわ! NEKOGETです。
この記事はCodeIgniterアドベントカレンダーのために書きました! 17日目です!
https://qiita.com/advent-calendar/2017/code_igniter
16日目の記事は、 CodeIgniter3のチュートリアルをちょっと見てみようかの巻(3)でした。
さて、この記事はCodeIgniter3のチュートリアルをリファクタリング(1) の続きです。
(1)では要件定義をしました。
その続きですね。
頑張っていきましょう!
環境の準備
サーバーの準備
前回は AWS Cloud9で環境を作ったので、今回は AWS Lightsail でいこうと思います。Newsを見せるだけのサイトだもの。VPSで(多分)十分だと思うの。
最近始まったAWSのVPSなサービスですね。
月$5の一番安いやつでいきます。
インスタンスを作成します。
東京リージョンです。
アプリ + OSにすると、便利なWordPressが選択できます。
一瞬、もうWordPressでいいのでは?って思いました。
だってこのままボタン押したら、WordPressが動くんですもの…..
CodeIgniterのチュートリアルなのでOSのみを選択
Amazon Linuxにしてみました。
手持ちのキーを登録もできそうですが、新規作成しました。
sshキーの名前を適当に決めて、作成ボタンをぽちっですねー。
鍵ができました。
鍵二度とDLできないからちゃんとDLします。
ぽちっ。
インスタンスの名前を確認します。
もうめんどくさかったのでそのままの名前で行きました。
で、作成ボタンを押しました。
インスタンスの準備ができて準備中になりました。
動作環境の準備
sshでログイン
PHP入ってるかな?
1 2 |
$ php --version -bash: php: command not found |
1 2 |
$ mysql --version -bash: mysql: command not found |
うん、入ってないね。
やっぱansible用意しようか。
用意しました。
https://github.com/NEKOGET/ci3_aws_lightsail_ansible
(これ、ansible用意するだけでブログ1本にしてよかったんじゃ?って気が少しだけしてるの気のせいでしょうか?…)
中にある、ansible.shを実行するとansibleのインストールが始まります。
1 |
sh ansible.sh |
CodeIgniter3のプロジェクトを作成
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
$ composer create-project kenjis/codeigniter-composer-installer ci3 Installing kenjis/codeigniter-composer-installer (v0.4.7) - Installing kenjis/codeigniter-composer-installer (v0.4.7): Downloading (100%) Created project in ci3 Loading composer repositories with package information Updating dependencies (including require-dev) Package operations: 1 install, 0 updates, 0 removals - Installing codeigniter/framework (3.1.6): Downloading (100%) kenjis/codeigniter-composer-installer suggests installing kenjis/codeigniter-cli (A command-line tool for CodeIgniter 3.0) kenjis/codeigniter-composer-installer suggests installing kenjis/ci-phpunit-test (An easier way to use PHPUnit with CodeIgniter 3.0) kenjis/codeigniter-composer-installer suggests installing kenjis/codeigniter-ss-twig (A Simple and Secure Twig integration for CodeIgniter 3.0) kenjis/codeigniter-composer-installer suggests installing kenjis/codeigniter-doctrine (A simple Doctrine integration for CodeIgniter 3.0) kenjis/codeigniter-composer-installer suggests installing kenjis/codeigniter-deployer (A Deployment Tool for CodeIgniter 3.0) codeigniter/framework suggests installing paragonie/random_compat (Provides better randomness in PHP 5.x) Writing lock file Generating autoload files > Kenjis\CodeIgniter\Installer::postInstall Loading composer repositories with package information Updating dependencies (including require-dev) Package operations: 1 install, 0 updates, 0 removals - Installing mikey179/vfsstream (v1.1.0): Downloading (100%) Writing lock file Generating autoload files ================================================== `public/.htaccess` was installed. If you don't need it, please remove it. If you want to install translations for system messages or some third party libraries, $ cd <codeigniter_project_folder> $ php bin/install.php Above command will show help message. See <https: //github.com/kenjis/codeigniter-composer-installer> for details ================================================== </https:> |
インストールできました!
スタート地点にたちました!
(3)に続きます☆
18日目の記事は、 noldorinfo さんによる不思議なvalidator(filter)順序です!
お楽しみに☆
CodeIgniter3のチュートリアルをリファクタリング(1)
こんにちわ! NEKOGETです。
この記事はCodeIgniterアドベントカレンダーのために書きました! 14日目です!
https://qiita.com/advent-calendar/2017/code_igniter
13日目の記事は、 CodeIgniter3のチュートリアルをちょっと見てみようかの巻(3)でした。
CodeIgniter3のチュートリアルをちょっと見てみようかの巻(3) までのチュートリアルの回を見ていただいたみなさまにはわかると思いますが、チュートリアルすごく雑です。
もう少しだけしっかり作ってみようと思います。
要件定義
要望を想像してみる
このチュートリアルの機能はNews機能です。
- Newsの記事を読んでもらう
- Newsの記事を登録更新する
この2つの機能が主な機能です。
- お店のニュースを表示する機能が欲しいですよねー
- Newsの記事は誰にでも更新できてはいけません。編集者だけが登録編集削除できるようにしたいです。
- 記事のURLを見るだけでタイトルがわかるようにしたいです。
- 記事を書いた日表示できます?
- 一覧は新しい順に表示させたいです
トップページには、新着5件が表示されると嬉しいですねカテゴリー別の一覧が見えると嬉しいです。画像のUPLOADもできると嬉しいです。自動でリサイズも書いた人の名前を自動で出したいですねー
要望はどんどん増えていきますが、予算と時間の関係で、これぐらいの要望が叶うといいですね☆
登場人物は2名
- (1)記事を見る人
- (2)記事を書く人
なるほど2つの視点で機能が必要ですねぇ。
次は動線を確認します
動線の確認
登場人物別にIFDAM図を作ってみましょうか。
(1)記事を見る人
シンプルだねw
(2)記事を書く人
ちょっと大きくなっちゃったんでクリックで大きい画像が見えるようにして見ました。
いわゆる管理機能だねー
仕様の検討
そうだねぇ。
ログインしてなければできることが絞られてる状態になるだけだものね。
新規登録ボタンの表示と新規登録機能はログインできていないと使えないことにしよう。
(2)記事を書く人のIFDAMを元に作ろう
ワイヤーの作成
普段なら、アプリを使って作るんだけど、今日はチュートリアルだしね
手書きで描いちゃおうかな
ログインしたら、新規登録フォームが見えるでいいんじゃないの?
一覧じゃなくて???
修正機能ないのに、一覧をログインして見る必要あるかな?
….なるほど、無いね。
ではそうしてみよう。
IFDAM図を直してみるから一緒に確認してね。
データの設計
MySQLで行くなら MySQL Workbench で、作っちゃえばいいかな?
こんな感じでcreate文をコピーできるの便利だねー
実際に使う予定のサーバに接続して流し込むこともできるし、MySQL Workbench便利だね。
PostgresならPgAdmin4ってアプリがあるよ!
1 2 3 4 5 6 7 8 9 10 |
CREATE TABLE IF NOT EXISTS `mydb`.`users` ( `id` INT NOT NULL AUTO_INCREMENT, `name` VARCHAR(45) NULL, `salt` VARCHAR(45) NULL, `password` BINARY(255) NULL, `status` TINYINT(2) NULL, `created_at` DATETIME NULL, `updated_at` DATETIME NULL, PRIMARY KEY (`id`)) ENGINE = InnoDB |
1 2 3 4 5 6 7 8 9 10 11 12 |
CREATE TABLE IF NOT EXISTS `mydb`.`news` ( `id` BIGINT(20) NOT NULL AUTO_INCREMENT, `title` VARCHAR(50) NULL, `slug` VARCHAR(255) NULL, `text` TEXT NULL, `create_user_id` INT(10) NULL, `created_at` DATETIME NULL, `updated_user_id` INT(10) NULL, `updated_at` DATETIME NULL, PRIMARY KEY (`id`), UNIQUE INDEX `slug_uq` (`slug` ASC)) ENGINE = InnoDB |
次は必要な環境を用意しよう。
(2)へ続きます。
CodeIgniter3のチュートリアルをちょっと見てみようかの巻(3)
こんにちわ! NEKOGETです。
この記事はCodeIgniterアドベントカレンダーのために書きました! 13日目です!
https://qiita.com/advent-calendar/2017/code_igniter
12日目の記事は、CodeIgniter3 migrationの話をば。 でした。
今回は3本目 ニュースを登録する機能を作ろうぜ を見ていくよ!!!
本家ドキュメント: https://www.codeigniter.com/user_guide/tutorial/create_news_items.html
ここで作る機能は、新規登録機能だね!
ルーティングの設定
application/config/routes.php を編集します。
1行目を追加。 news/createにアクセスすると、 NewsController Class の create メソッドが処理をします。
1 2 3 4 5 |
$route['news/create'] = 'news/create'; $route['news/(:any)'] = 'news/view/$1'; $route['news'] = 'news'; $route['(:any)'] = 'pages/view/$1'; $route['default_controller'] = 'pages/view'; |
新規登録フォーム用のViewファイルを作る
application/views/news/create.php を作ろう!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<h2>< ?php echo $title; ?></h2> < ?php echo validation_errors(); ?> < ?php echo form_open('news/create'); ?> <label for="title">Title</label> <input type="input" name="title" /><br /> <label for="text">Text</label> <textarea name="text"></textarea><br /> <input type="submit" name="submit" value="Create news item" /> < ?php echo form_close(); ?> |
チュートリアルに、処理成功画面のviewファイルをつくる行程が抜けているね….
とりあえずsuccessっって出ればいいかな的に用意しとこうか…
ターミナルで実行してね。
1 |
$ echo success > application/views/news/success.php |
新規登録する機能をNews_model Classに追加する
次はModelだね!
チュートリアルのサンプルコードを組み込むとこんな感じ。
次の記事でリファクタリングというか、もうちょっとなんとかしたコードにしてみようと思うよ!
雑い(>_< ) もうちょっとなんとかならんかったのかチュートリアルさん..... orz
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
< ?php /** * Class News_model */ class News_model extends CI_Model { /** * News_model constructor. */ public function __construct() { //データベースへの接続 $this->load->database(); } /** * ニュースの取得 * @param bool $slug * @return mixed */ public function get_news($slug = FALSE) { if ($slug === FALSE) { $query = $this->db->get('news'); return $query->result_array(); } $query = $this->db->get_where('news', array('slug' => $slug)); return $query->row_array(); } /** * ニュースの新規登録 */ public function set_news() { $this->load->helper('url'); $slug = url_title($this->input->post('title'), 'dash', TRUE); $data = array( 'title' => $this->input->post('title'), 'slug' => $slug, 'text' => $this->input->post('text') ); return $this->db->insert('news', $data); } } <h2>News Controllerにcreateメソッドを追加する</h2> チュートリアルのコードを足すとこんな感じになるね <pre> < ?php /** * Class News */ class News extends CI_Controller { /** * News constructor. */ public function __construct() { parent::__construct(); $this->load->model('news_model'); $this->load->helper('url_helper'); } /** * index (一覧ページの表示) */ public function index() { $data = []; $data['news'] = $this->news_model->get_news(); $data['title'] = 'News archive'; $this->load->view('templates/header', $data); $this->load->view('news/index', $data); $this->load->view('templates/footer'); } /** * newsの主催ページの表示 * @param null $slug */ public function view($slug = null) { $data = []; $data['news_item'] = $this->news_model->get_news($slug); if (empty($data['news_item'])) { show_404(); } $data['title'] = $data['news_item']['title']; $this->load->view('templates/header', $data); $this->load->view('news/view', $data); $this->load->view('templates/footer'); } /** * newsの新規登録 */ public function create() { $this->load->helper('form'); $this->load->library('form_validation'); $data['title'] = 'Create a news item'; $this->form_validation->set_rules('title', 'Title', 'required'); $this->form_validation->set_rules('text', 'Text', 'required'); if ($this->form_validation->run() === FALSE) { $this->load->view('templates/header', $data); $this->load->view('news/create'); $this->load->view('templates/footer'); } else { $this->news_model->set_news(); $this->load->view('news/success'); } } } |
http://{アプリケーションのROOT URL}/news/create
実行した結果 success は見えたかな?
http://{アプリケーションのROOT URL}/news
一覧に新規登録した記事が追加されたかな?
さて、ここまでコードを見てて思うわけですが、ちょっとコードが雑い。とっても雑い。
次はチュートリアルのコードのレビューとリファクタリングをしちゃおうと思います。
流石にこのコードはダメです。はい。
CodeIgniter3 migrationの話をば。
こんにちわ! NEKOGETです。
この記事はCodeIgniterアドベントカレンダーのために書きました! 12日目です!
https://qiita.com/advent-calendar/2017/code_igniter
この記事は、CodeIgniter3のチュートリアルをちょっと見てみようかの巻(2)の記事の補足です。
Migrationについて
本家ユーザーガイド :
https://www.codeigniter.com/user_guide/libraries/migration.html
CodeIgniterでもMigrationを使ってテーブル定義の管理をすることができます。
CodeIgniter3のチュートリアルをちょっと見てみようかの巻(2)では、チュートリアルで触れられていないため記載しませんでしたが、使うと便利です。
この機能は2の頃にはすでにあったのですがあまり知られていません。
CodeIgniterがシンプルで、たくさんの機能を実装していないという印象からではないかと思います。
設定
application/config/migration.php の編集
migrationを使用可能にして、
migrationのファイルを保存するフォルダを指定して
migrationのファイルをつくるのにtimestamp使いますを指定します。YYYYMMDDHHIISS フォーマットなので、(e.g. 20171213100537) です。
マイグレーションのバージョンは自動で最新にしといてね設定もfalseになっているのをtrueに変更です。
1 2 3 4 |
$config['migration_enabled'] = TRUE; $config['migration_path'] = APPPATH.'migrations/'; $config['migration_type'] = 'timestamp'; $config['migration_auto_latest'] = true; |
フォルダを作りましょ
1 |
mkdir application/migrations/ |
migrationファイルの作成
1 |
echo -n > application/migrations/`date '+%Y%m%d%H%M%S'`_add_news.php |
ファイルができていることを確認
1 2 3 |
$ ll application/migrations/ total 4 -rw-rw-r-- 1 ec2-user ec2-user 1047 Dec 13 11:35 20171213114048_add_news.php |
これから作るmigrationのバージョンは、 20171213114048 になりました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
< ?php /** * newsテーブルを追加する * Class Migration_add_news */ class Migration_add_news extends CI_Migration { /** * migrationの実行 */ public function up() { $this->dbforge->add_field(array( 'id' => array( 'type' => 'INT', 'constraint' => 11, 'unsigned' => true, 'auto_increment' => true ), 'title' => array( 'type' => 'VARCHAR', 'constraint' => '128', ), 'slug' => array( 'type' => 'VARCHAR', 'constraint' => '128', ), 'text' => array( 'type' => 'TEXT', 'null' => true, ), )); $this->dbforge->add_key('id', true); $this->dbforge->create_table('news'); } /** * collbackの実行 * newsテーブルのdrop */ public function down() { $this->dbforge->drop_table('news'); } } |
ユーザーガイドに従って書くとこんな感じです。
もうすでに皆様もPHP7環境だと思うのでarray()は[]にしちゃっていいと思います。
Migrate Controller Classの作成
application/controllers/Migrate.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
< ?php class Migrate extends CI_Controller { public function index() { $this->load->library('migration'); if ($this->migration->current() === FALSE) { show_error($this->migration->error_string()); } } } |
ドキュメントのサンプルコードはこんな感じで不親切です….。
application/config/migration.php の $config[‘migration_version’] = 0; のところを、実行する最終のバージョン番号を設定せねば動きません….
最新の状態にするのであれば、$this->migration->latest()を使うと良いです。
application/controllers/Migrate.php
1 2 3 4 5 6 7 8 9 10 11 12 |
class Migrate extends CI_Controller { public function index() { $this->load->library('migration'); if ($this->migration->latest() === FALSE) { show_error($this->migration->error_string()); } } } |
migrationの実行と結果/h2>
migrationを実行します。
1
php public/index.php Migrate index
1 |
php public/index.php Migrate index |
実行された結果を見てみます
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
$ mysql -uroot -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 23 Server version: 5.5.57 MySQL Community Server (GPL) Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> use ci3_tutorial ; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> show tables -> ; +------------------------+ | Tables_in_ci3_tutorial | +------------------------+ | migrations | | news | +------------------------+ 2 rows in set (0.00 sec) |
newsテーブルと、migrationsテーブルができています。
1 2 3 4 5 6 7 8 9 10 |
mysql> desc news ; +-------+------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+------------------+------+-----+---------+----------------+ | id | int(11) unsigned | NO | PRI | NULL | auto_increment | | title | varchar(128) | NO | | NULL | | | slug | varchar(128) | NO | | NULL | | | text | text | YES | | NULL | | +-------+------------------+------+-----+---------+----------------+ 4 rows in set (0.00 sec) |
1 2 3 4 5 6 7 |
mysql> select * from migrations ; +----------------+ | version | +----------------+ | 20171213114048 | +----------------+ 1 row in set (0.00 sec) |
Migrate Controllerにロールバックを追加してみる
Migrate Controllerにロールバックを追加しました。
またhttp(s)越しに、外部から叩かれないように、
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
class Migrate extends CI_Controller { function __construct() { parent::__construct(); //ターミナルからの実行でなければ処理しない。 if(! $this->input->is_cli_request()) { show_404(); exit; } $this->load->library('migration'); } public function index() { if ($this->migration->latest() === FALSE) { show_error($this->migration->error_string()); } } public function rollback($version) { if ($this->migration->version($version)) { echo "Migration Success.\n"; } else { show_error($this->migration->error_string()); } } } |
コマンドの実行
1 2 |
$ php public/index.php Migrate rollback 20171213114048 Migration Success. |
20171213114048_add_news.phpの状態に戻ります。
まだ1つのバージョンしかないのでこれしか指定できなかったわけですが、これもやり直したい場合ありますよね?
1 2 3 |
$ php public/index.php Migrate rollback 0 ERROR: An Error Was Encountered |
エラーを吐いてしまいますが、これでnewsテーブルがdropされます。
これはもうちょっとうまい方法が欲しい…..エラーが発生しない方法に寄せたい….ですが今日のところはこれで0地点に戻りますということにします。
やっぱりSQLで書きたいやん?
20171213114048_add_news.php の upメソッドはこんな感じになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
/** * migrationの実行 */ public function up() { $this->load->database(); $sql = 'CREATE TABLE news ( id int(11) NOT NULL AUTO_INCREMENT COMMENT "id", title varchar(128) NOT NULL COMMENT "タイトル", slug varchar(128) NOT NULL COMMENT "slug", text text NOT NULL COMMENT "本文", PRIMARY KEY (id), KEY slug (slug)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT "news" ; '; $this->db->query($sql); } |
migrationはsqlそのままで行きたいかどうかは好みが別れるかと思います。
MySQLを使っての設計と実装の場合、mysqlWorkBenchを使う場合も多いでしょうし、そうするとツールからcreate table文は自動抽出でしょうし、sqlの方が便利だと思うんだよねー。
さてと、チュートリアルに戻りましょうか!!!