Yii2を使用した簡単なCRUDアプリケーションの作成

免責事項



このレッスンは、Yii2を理解するのに役立ちます。 現時点では、Yii2は本番の準備ができていません。 作業プロジェクトで使用することはお勧めしません。



始めましょう



今日、Yiiフレームワークの作者はYii2の公開プレビューを発表しました。 Yii1とYii2の間には非常に多くの変更があります。



このチュートリアルでは、Yii2で簡単なブログを作成する方法について説明します。 このプロセスでは、Yii2をダウンロードしてインストールし、基本的なアプリケーションを作成し、データベースに接続して、投稿の作成、更新、読み取り、削除のロジックを説明します。



続行するには、次のものが必要です。





どうぞ!



すでにWebサーバーが構成されていると仮定します。 レッスンでは、次のパスとアドレスを使用します。





また、レッスンの最後に、 yii2.erianna.comで作成するアプリケーションの例を見ることができます。



ダウンロードYii2



リポジトリのクローンを作成するか、アーカイブをダウンロードすることにより、GithubからYii2のコピーを取得できます。



  git clone git@github.com:yiisoft / yii2.git / dir / to / yii2 


どちらか



  wget https://github.com/yiisoft/yii2/archive/master.zip
 master.zip / dir / to / yii2を解凍します 


Yii2を解凍した後、 / dir / to / yii2 / frameworkフォルダーに移動します



  cd / dir / to / yii2 / framework 


次のコマンドを実行して、最初の質問に「はい」と答えることにより、基本的なWebアプリケーションを作成します。



  php yiic.php app / create / var / www / yii2
はい 


これは、Yii 1.xのWebアプリケーション作成チームに相当します。 次に/ var / www / yii2に移動します。 1つのフォルダーと1つのファイルが表示されます。



  $ ls -l
合計8
 -rwxrwxrwx 1ユーザーwww-data 265 5月4日09:30 index.php
 drwxrwsr-x 5ユーザーwww-data 4096 5月4日09:07保護


サイトを開始する前に、index.phpファイルにいくつかの変更を加える必要があります。 私の意見では、いくつかの物議を醸す決定があります。 Yii2の最終リリースの前に修正され、よりインストールしやすくなることを願っています。



index.phpを次のように変更します。



<?php define('YII_DEBUG', true); // Change this to your actual Yii path require '/path/to/yii2/framework/yii.php'; // Change __DIR__ to __FILE__ so we can load our config file $config = require dirname(__FILE__).'/protected/config/main.php'; $config['basePath'] = dirname(__FILE__).'/protected'; $app = new \yii\web\Application($config); $app->run();
      
      





変更点を見てみましょう。



 // Change this to your actual Yii path require '/path/to/yii2/framework/yii.php';
      
      







最初に、framework / yii.phpファイルへのパスを変更する必要があります。 デフォルトでは、同じディレクトリにあると見なされます。 そうかもしれませんが、Yii2への正確なパスを指定する必要があります。



 $config = require dirname(__FILE__).'/protected/config/main.php'; $config['basePath'] = dirname(__FILE__).'/protected';
      
      





次に、 __ DIR__の代わりに__FILE__を使用するように構成ファイルへのパスを更新します。 これは、アプリケーションを開始できるようにするために必要です。



続行する前に、Yii- Namespacesの新しい点に注意することが重要です



 $app = new \yii\web\Application($config);
      
      





名前空間の意味は、異なるコードベース間の衝突を避けるために、コードを論理ユニットにカプセル化することです。 2つのクラスがあり、両方ともFooと呼ばれ、両方にBarメソッドがあるとします。 それらが異なる名前空間にある場合、衝突することなく互いに独立して呼び出すことができます。



 $foo = new \namespace\Foo; $foo2 = new \namespace2\Foo;
      
      





名前空間は、コードの衝突を避ける簡単な方法です。 Yii2はこの原則に基づいて完全に構築されるため、 それらについて読むことをお勧めします。



これで最初のアプリケーションが作成されました! yii2のあるアドレスに移動すると、次のページが表示されます。



c4ca4238a0b923820dcc509a6f75849b.png

初めてのYii2アプリ!



Yii 1.xとは異なり、基本的なYii2アプリケーションはそれほどエキサイティングではありません。 彼にもう少しやることを教えましょう。



まず、ファイル/protected/views/layout/main.phpを開き、その内容を置き換えます。



 <?php use yii\helpers\Html as Html; ?> <!doctype html> <html lang="<?php \Yii::$app->language?>"> <head> <meta charset="utf-8" /> <title><?php echo Html::encode(\Yii::$app->name); ?></title> <link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.min.css" rel="stylesheet"> <script src="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/js/bootstrap.min.js"></script> </head> <body> <div class="container"> <div class="navbar navbar-inverse"> <div class="container"> <div class="navbar-inner"> <a class="brand" href="/"><?php echo Html::encode(\Yii::$app->name); ?></a> </div> </div> </div> <div class="content"> <?php echo $content?> </div> </div> </body> </html>
      
      





ページを更新します。 ほら Twitter Bootstrapで改善されていませんか? 繰り返しますが、Yii1とYii2の間で大きな違いはありません。 ビューにコンテンツを表示するための$ content変数がまだあります。 ただし、 Yii :: app()は Yii :: $ app 置き換えられました。 Yii2のすべては名前空間で分けられているため、「生の」クラスを呼び出すだけでなく、名前空間ですべてを参照することを忘れないでください。



それでは、実際のコーディングに取り掛かりましょう!



データベースに接続する



このアプリケーションでは、ブログの投稿を保存する単純なPostsテーブルのみがあります。



データベースにテーブルを作成する


MySQLにログインし、yii2という名前のユーザーとデータベースを作成します。 次に、次のクエリを実行して構造を更新します。



 DROP TABLE IF EXISTS `posts`; CREATE TABLE IF NOT EXISTS `posts` ( `id` int(11) NOT NULL, `title` varchar(255) NOT NULL, `content` text NOT NULL, `created` datetime NOT NULL, `updated` datetime NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1; ALTER TABLE `posts` ADD PRIMARY KEY(`id`); INSERT INTO `yii2`.`posts` (`id`, `title`, `content`, `created`, `updated`) VALUES ('1', 'Example Title', 'New Post', NOW(), NOW());
      
      





設定を更新


/ var / www / yii2 / protected /フォルダーに移動し、お気に入りのエディターでconfig.phpファイルを開きます。 すべての内容をこれで置き換えます:



 <?php return array( 'id' => 'webapp', 'name' => 'My Web Application', 'components' => array( // uncomment the following to use a MySQL database 'db' => array( 'class' => 'yii\db\Connection', 'dsn' => 'mysql:host=localhost;dbname=yii2', 'username' => 'yii2', 'password' => '<password>', ), 'cache' => array( 'class' => 'yii\caching\DummyCache', ), ), );
      
      





Yiiに精通している場合、Yii1が生成したこれらの巨大な設定に比べて大幅改善が見られます。 構造は同じままですが、データベースに接続するために必要なことはそれだけです。



投稿モデルを作成する


保護されたフォルダーに新しいモデルフォルダーを作成し、次のコードを使用してその中にPost.phpファイルを作成します。



 <?php namespace app\models; class Post extends \yii\db\ActiveRecord { /** * Returns the static model of the specified AR class. * @param string $className active record class name. * @return Comments the static model class */ public static function model($className=__CLASS__) { return parent::model($className); } /** * @return string the associated database table name */ public static function tableName() { return 'posts'; } /** * @return array primary key of the table **/ public static function primaryKey() { return array('id'); } /** * @return array customized attribute labels (name=>label) */ public function attributeLabels() { return array( 'id' => 'ID', 'title' => 'Title', 'content' => 'Content', 'created' => 'Created', 'updated' => 'Updated', ); } }
      
      





Yii1に精通している場合、ActiveRecordで(少なくともこの例では)変更されている唯一のことは、 primaryKeyおよびtableName関数が静的メソッドになったことです。 他のすべては基本的に同じままです。 ほとんどの場合、ActiveRecordは変更されていません。



クラスの最も重要な部分は、 app \ models名前空間を含めることです。 これはYiiにこのファイルをどのように参照できるかを伝えます。



クラス名を単純に呼び出すことができるYii1とは異なり、Yii2は異なるタイプのファイルスタートアップを使用するため、使用するものを正確に指定する必要があります。 これにより、開発が多少遅くなる場合があります(CHtmlを呼び出すだけでなく、常に\ yii \ framework \ web \ Htmlを含めることを忘れないようにするのは面倒です)。いくつかのクラス。 少なくとも理論的には。



クラッド!



Postモデルを名前空間に配置したら、CRUDアプリケーションの作成を開始できます。



すべて見る


開始するには、すべてを表示できるようにインデックスアクションを更新しましょう。 メインページにすべてのメッセージが表示されるのが大好きなので、これから始めましょう。 controllers / SiteController.phpファイルを開き、以下に示すようにインデックスアクションを更新します。



 public function actionIndex() { $post = new Post; $data = $post->find()->all(); echo $this->render('index', array( 'data' => $data )); }
      
      





いくつか注意点があります。 まず、 ::モデル()->消えました。 ActiveRecordのデータとモデルは、直接メソッド呼び出しで利用できるようになりました。 たとえば、$ post-> find()-> all()。 私は個人的にPost :: model()-> findAll()が大好きであるという事実にもかかわらず、データにアクセスする新しい方法はより標準的で読みやすいように見えます。



次に、findAllはfind()-> all()に置き換えられました。 すべての検索メソッドは、find()またはfindBySql()から取得されます。



第三に、$ this-> render()は行の先頭でエコーを要求するようになりました。 個人的に、私はこれが嫌いです。 これはCakePHP に非常に似ており、私の意見では冗長です。 この変更の背後にある考え方は、ユーザーに表示したいすべてのものをエコー経由で送信する必要があるということです。そうでなければ、さらなるアクションのために変数に配置するだけです。 変数にレンダリングする古い方法(パラメーターをレンダリングメソッドに渡す)を好みますが、おそらくこれに慣れるでしょう。



次に、ページを更新します...



名前空間に精通しているなら、おそらくPostモデルを含めなかった理由を尋ねるでしょう。 慣れていない場合は、エラーを受け取ったことに驚くかもしれません。 その理由は簡単です。 _Yii2の名前空間を覚えておく必要があります_。 使用したいものはすべて、これが以前に行われていない場合、明確に示される必要があります。



SiteControllerファイルの先頭に次の行を追加します。 次に、ページを更新します。



 use app\models\Post;
      
      





次に、マークアップを追加して投稿を表示します。 保護されたファイル/ views / site / index.phpを開き、その内容を次のものに置き換えます。



 <?php use yii\helpers\Html; ?> <?php echo Html::a('Create New Post', array('site/create'), array('class' => 'btn btn-primary pull-right')); ?> <div class="clearfix"></div> <hr /> <table class="table table-striped table-hover"> <tr> <td>#</td> <td>Title</td> <td>Created</td> <td>Updated</td> <td>Options</td> </tr> <?php foreach ($data as $post): ?> <tr> <td> <?php echo Html::a($post->id, array('site/read', 'id'=>$post->id)); ?> </td> <td><?php echo Html::a($post->title, array('site/read', 'id'=>$post->id)); ?></td> <td><?php echo $post->created; ?></td> <td><?php echo $post->updated; ?></td> <td> <?php echo Html::a(NULL, array('site/update', 'id'=>$post->id), array('class'=>'icon icon-edit')); ?> <?php echo Html::a(NULL, array('site/delete', 'id'=>$post->id), array('class'=>'icon icon-trash')); ?> </td> </tr> <?php endforeach; ?> </table>
      
      





うーん、見た目が違うよね? CHtml :: link()はなくなり、代わりにHtmlヘルパーが表示されます。 幸いなことに、CHtml :: linkとHtml :: aの構造は変わりません。 したがって、パラメータを入力するだけです。



読む


読むのは簡単なので、理解しましょう。 次の定義でSiteControllerに新しいメソッドを作成します。



 public function actionRead($id=NULL) { echo 'HelloWorld'; }
      
      





次に進みますか?R =サイト/読み取り&ID = 1。 画面にHelloWorldが表示されます。 ほら いいね これは、メソッドが呼び出されたことを意味します。 それを更新して、データベースのデータを表示します。



まず、投稿が見つからない場合にHttpExceptionをスローできるように、SiteControllerにHttpExceptionを追加しましょう。



 use \yii\base\HttpException;
      
      





読み取りアクションを補完する



 public function actionRead($id=NULL) { if ($id === NULL) throw new HttpException(404, 'Not Found'); $post = Post::find($id); if ($post === NULL) throw new HttpException(404, 'Document Does Not Exist'); echo $this->render('read', array( 'post' => $post )); }
      
      





明確にするために、HttpExceptionは基本的にCHttpExceptionです。 データベースで指定されたIDの投稿をリクエストして表示するだけです。 投稿が見つからなかった場合、またはIDが指定されなかった場合、HttpExceptionをスローします。



次に、 保護された新しいファイル/ views / site / read.phpを作成し、次のコードを追加して投稿を表示する必要があります。



 <?php use yii\helpers\Html; ?> <div class="pull-right btn-group"> <?php echo Html::a('Update', array('site/update', 'id' => $post->id), array('class' => 'btn btn-primary')); ?> <?php echo Html::a('Delete', array('site/delete', 'id' => $post->id), array('class' => 'btn btn-danger')); ?> </div> <h1><?php echo $post->title; ?></h1> <p><?php echo $post->content; ?></p> <hr /> <time>Created On: <?php echo $post->created; ?></time><br /> <time>Updated On: <?php echo $post->updated; ?></time>
      
      





次に、メインページで[投稿の例]をクリックします。 出来上がり! ブログの投稿を表示できるようになりました!



削除する


投稿の削除も同様に簡単なので、私たちがそれらの世話をします。 次のコードを使用して新しいメソッドを作成します。



 public function actionDelete($id=NULL) { }
      
      





この方法では、もう少し複雑な構文が必要です。 投稿を正常に削除した後、ユーザーをメインページにリダイレクトする必要があります。 始めましょう。



まず、方法を説明します



 public function actionDelete($id=NULL) { if ($id === NULL) { Yii::$app->session->setFlash('PostDeletedError'); Yii::$app->getResponse()->redirect(array('site/index')); } $post = Post::find($id); if ($post === NULL) { Yii::$app->session->setFlash('PostDeletedError'); Yii::$app->getResponse()->redirect(array('site/index')); } $post->delete(); Yii::$app->session->setFlash('PostDeleted'); Yii::$app->getResponse()->redirect(array('site/index')); }
      
      





Yii2に関するいくつかのコメント。 最初に、リダイレクトは$ this-> redirect()の代わりにYii :: $ app-> getResponse-> redirect()を使用して行われます。 このソリューションは、コードを整理するという意味では理にかなっていますが、印刷に時間がかかります! また、これにより、$アプリに混雑感が生じます。 同時に、メソッドの定義は同じままです。



第二に、setFlashはapp()の代わりに$ appで利用できるようになりました。 これで慣れるはずです。 =)



これで削除は完了です。 protected / views / site / index.phpに戻り、送信された通知をキャッチしましょう。



最初のhrタグの後にこれを追加してください



 <?php if(Yii::$app->session->hasFlash('PostDeletedError')): ?> <div class="alert alert-error"> There was an error deleting your post! </div> <?php endif; ?> <?php if(Yii::$app->session->hasFlash('PostDeleted')): ?> <div class="alert alert-success"> Your post has successfully been deleted! </div> <?php endif; ?>
      
      





「サンプル投稿」を削除してみてください。 とても簡単ですね。 これでYii :: $ appのアイデアを理解できましたか?



作成する


それでは、楽しいブロードキャストに移り、ブログに新しいエントリを作成しましょう。 作成するにはいくつかのことを行う必要があります。 最初に、ActiveFormを使用してフォームを操作します。 次に、$ _POSTのデータをキャッチして検証する必要があります。 そして最後に、データをデータベースに保存する必要があります。 始めましょう。



まず、フォームのビューを作成しましょう。 ファイルprotected / views / site / create.phpを作成します。 ウィジェットを使用するため、アプリケーションのルートに「assets」フォルダーを作成し、Webサーバーで書き込み可能にする必要があります。 Chmod 755は通常、この問題を解決します。 次に、メソッド定義をSiteControllerに追加します。



 public function actionCreate() { $model = new Post; if (isset($_POST['Post'])) { $model->title = $_POST['Post']['title']; $model->content = $_POST['Post']['content']; if ($model->save()) Yii::$app->response->redirect(array('site/read', 'id' => $model->id)); } echo $this->render('create', array( 'model' => $model )); }
      
      





Yii1とほぼ同じように見えます。 しかし、まだいくつかの違いがあります。 まず、Controllerには「populate」メソッド($ this-> populate($ ds、$ model))があり、理論的にはすべてのこの不法占拠者をisset($ _ POST)で節約できるはずです。 新しい投稿を作成するためのコードは次のようになります。



 if ($this->populate($_POST, $model)) { //Then do something }
      
      





残念ながら、最新バージョンで動作させることができませんでした。 私のモデルのデータは変更されていません。 次に、$ model-> attributes = $ _POST ['Post']が機能しませんでした。 ActiveRecordは少し湿っているように見えるので、今のところは手でデータを入力する必要があります。



最後に、別の障害に遭遇しました-一意のIDでデータベースに保存します。 したがって、これも手動で行う必要があります。 誰かがこれを解決する方法を見つけたら-コメントを残してください。



Postモデルを更新して、一意の主キーが機能するようにします。 ファイルの最後に次のコードを追加してください:



 public function beforeSave($insert) { if ($this->isNewRecord) { $command = static::getDb()->createCommand("select max(id) as id from posts")->queryAll(); $this->id = $command[0]['id'] + 1; } return parent::beforeSave($insert); }
      
      





彼が行うことは、新しいレコードが作成されているかどうかを確認することだけです。作成されている場合は、データベースから最大IDを取得し、それをインクリメントしてIDとして使用します。



いくつかの異なる組み合わせを試しました(NULL、0、_ $ model-> idですが、何らかの理由でActiveRecordは優れた0のIDでモデルを保持することを拒否しました。これが機能しない理由はわかりません)。



実際、著者は単にidフィールドにAUTO_INCREMENTを指定するのを忘れていました。しかし、私はこの部分を不注意の少しのレッスンとして残すことにしました。



私たちはそれを理解し、今度はビューを作成します。



 <?php use yii\helpers\Html; ?> <?php $form = $this->beginWidget('yii\widgets\ActiveForm', array( 'options' => array('class' => 'form-horizontal'), )); ?> <?php echo $form->field($model, 'title')->textInput(array('class' => 'span8')); ?> <?php echo $form->field($model, 'content')->textArea(array('class' => 'span8')); ?> <div class="form-actions"> <?php echo Html::submitButton('Submit', null, null, array('class' => 'btn btn-primary')); ?> </div> <?php $this->endWidget(); ?>
      
      





以上で、モデルを保存できます。 しかし、何かがおかしいですね。 たとえば、作成および更新時間が0である理由は何ですか? 空のフォームを送信するとどうなりますか?



続行する前に、これら2つのエラーを修正しましょう。 Postモデルを開き、次のメソッドを追加します。



 public function rules() { return array( array('title, content', 'required'), ); }
      
      





このメソッドは、タイトルとコンテンツフィールドを必須にします。 モデルを保存しようとすると、これらのフィールドのいずれかが空の場合、エラーが発生します。 また、ブートストラップを使用しているため、エラーが正確に何であるかを簡単に確認できます。 試してみてください!



次に、正しい時間を自動的に設定する必要があります。



まず、モデルの上部に別の使用ラインを追加します



 use \yii\db\Expression;
      
      





次に、beforeSaveメソッドを更新してプロセスを自動化します。



ifブロック($ this-> isNewRecord)内に次の行を追加します。



 $this->created = new Expression('NOW()');
      
      





親を返す前に:: beforeSave($ insert)追加:



 $this->updated = new Expression('NOW()');
      
      





その結果、メソッドは次のようになります。



 public function beforeSave($insert) { if ($this->isNewRecord) { $this->created = new Expression('NOW()'); $command = static::getDb()->createCommand("select max(id) as id from posts")->queryAll(); $this->id = $command[0]['id'] + 1; } $this->updated = new Expression('NOW()'); return parent::beforeSave($insert); }
      
      





もう一度保存してみましょう。 これで、モデルはタイトルフィールドとコンテンツフィールドを検証し、作成時間と更新時間も自動的に入力します。 更新に移りましょう。



更新する


更新アクションは作成とほぼ同じです。 唯一の違いは、使用するモデルの定義方法です。



作成アクションでは、次のことを行いました。



 $model = new Post;
      
      





更新アクションでは、これを実行しましょう。



 $model = Post::find($id);
      
      





何かが見つからないときに例外をスローするのが好きなので、私のアクションはエラーチェックを行います。 それらを追加すると、コードは次のようになります。



 public function actionUpdate($id=NULL) { if ($id === NULL) throw new HttpException(404, 'Not Found'); $model = Post::find($id); if ($model === NULL) throw new HttpException(404, 'Document Does Not Exist'); if (isset($_POST['Post'])) { $model->title = $_POST['Post']['title']; $model->content = $_POST['Post']['content']; if ($model->save()) Yii::$app->response->redirect(array('site/read', 'id' => $model->id)); } echo $this->render('create', array( 'model' => $model )); }
      
      





何か面白いことに気づきましたか? ビューはまったく同じであるため、ビューを使用して作成します。 かっこいい?



結論



だから、やった。 数時間で、Yii2の完全な無知から単純なCRUDアプリケーションに移行しました。 この知識を使用して、ユーザーサポート、認証、データベース内の追加テーブル、さらに強力な機能を追加することにより、アプリケーションを簡単に拡張できます。



Yii2はYii 1.x に非常に似ていますが、使用方法を学ぶ必要がある多くの変更があります。 Yii2はまだ十分に文書化されていないため、Githubのソースコードに基づいてこの記事を書いただけです。 フレームワークのコードは非常によく文書化されています。 また、メソッドはYii1に非常に似ているため、必要なものを簡単に見つけることができました。



発見したように、修正が必要な問題がいくつかあります(ActiveRecordのドキュメントを改善するか、問題を修正することにより)。



参照資料



Githubソースコード

デモ

ソース記事



All Articles