Zend Framework 2でブログを作成する例。パート3.ユーザーとの連携

これは、Zend Framework 2を使用した単純なアプリケーションの開発に関する記事の3番目(最後?)の部分です。 最初の部分ではZendSkeletonApplicationの構造を調べ、2番目の部分では単純なモジュールの開発例示しました。 このパートはユーザーとの作業に専念し、Twigテンプレートエンジンもプロジェクトにねじ込みます。



ユーザーと連携する



前の部分で記述されたコードを使用すると、すべてのWebサイト訪問者のブログ投稿を作成、編集、および削除できます。 このアプローチは、どの作業サイトでも受け入れられないため、アプリケーションのさまざまな機能への登録/承認およびアクセス権の配布の問題を解決するときが来ました。



ZFコモンズ



多くのモジュールが標準タスクを解決するZendフレームワーク用に書かれています;それらは特別なサイトで見つけることができます: modules.zendframework.com 。 標準的な問題を解決するために自分の自転車を開発する代わりに、自分で既製のソリューションを使用/適応する方が適切だと思います(少なくとも既製のソリューションは、自転車の開発を始める前に研究する必要があります)。



多くのモジュール開発者の中で、ZF Commonsチームは際立っています。このチームのメンバーは、このプロジェクトで使用する非常に便利なモジュールを多数開発しています: github.com/ZF-Commons 。 この段階で必要なものをいくつか考えてください。



Zfcbase



他のZF Commonsモジュールが依存するカーネル( https://github.com/ZF-Commons/ZfcBase )。



Zfcuser



テンプレート( https://github.com/ZF-Commons/ZfcUser )で使用するためのユーザー登録/承認メカニズム、ユーザープロファイル、およびビューヘルパーを実装するモジュール。



ZfcUserDoctrineORM



デフォルトでは、ZfcUserは標準のデータベースメカニズムで動作します。このプロジェクトではDoctrine ORMを使用しているため、ZfcUserDoctrineORMモジュール( https://github.com/ZF-Commons/ZfcUserDoctrineORM )も必要です。



Zfctwig



Twigテンプレートエンジンとの統合のためのモジュール( https://github.com/ZF-Commons/ZfcTwig )。



ビヤウタイズ



ZfCommonsのモジュールに加えて、アクセス権を配布する便利なメカニズムを提供するBjyAuthorizeモジュールを使用します。 モジュールのロジックはシンプルで、他のフレームワーク間で共通です。 このモジュールは、ユーザー、ロール、ガードの概念で動作します。



ユーザーは許可されている場合と許可されていない場合があります。 許可ユーザーは、1つ以上の役割を持つことができます。 このコンテキストでのガードは、さまざまなロールのアクセス権を設定するコントローラー/アクションです。



ユーザー設定の準備



ユーザーエクスペリエンスを設定する前に、Doctrineが使用するユーザーとロールのエンティティを作成する必要があります。 BjyAuthorizeモジュールには、そのようなエンティティの例が含まれており、それらに基づいてMyUserモジュールを作成しました。



モジュールには元のものは含まれていません。そのコードは次のとおりです: github.com/romka/zend-blog-example/tree/master/module/MyUserエンティティ。



その設定( https://github.com/romka/zend-blog-example/blob/master/module/MyUser/config/module.config.php )にのみ注意を払う必要があります

return array( 'doctrine' => array( 'driver' => array( 'zfcuser_entity' => array( 'class' =>'Doctrine\ORM\Mapping\Driver\AnnotationDriver', 'paths' => array(__DIR__ . '/../src/MyUser/Entity') ), 'orm_default' => array( 'drivers' => array( 'MyUser\Entity' => 'zfcuser_entity', ) ) ) ), 'zfcuser' => array( // telling ZfcUser to use our own class 'user_entity_class' => 'MyUser\Entity\User', // telling ZfcUserDoctrineORM to skip the entities it defines 'enable_default_entities' => false, ), 'bjyauthorize' => array( // Using the authentication identity provider, which basically reads the roles from the auth service's identity 'identity_provider' => 'BjyAuthorize\Provider\Identity\AuthenticationIdentityProvider', 'role_providers' => array( // using an object repository (entity repository) to load all roles into our ACL 'BjyAuthorize\Provider\Role\ObjectRepositoryProvider' => array( 'object_manager' => 'doctrine.entity_manager.orm_default', 'role_entity_class' => 'MyUser\Entity\Role', ), ), ), );
      
      





この構成では、zfcuserエンティティをユーザーの操作を担当する独自のものに置き換え、ロールの操作を担当するエンティティをBjyAuthorizeモジュールに示します。



MyUserモジュールをapplication.config.phpに追加してから、コンソールでコマンドを実行する必要があります。

 ./vendor/bin/doctrine-module orm:schema-tool:update --force ./vendor/bin/doctrine-module orm:validate-schema
      
      





1つ目は、データベースのMyUserモジュールによって作成されたエンティティのテーブルを作成することです。2つ目は、最初のコマンドが正しく機能することを確認することです。



最後の準備アクションは、適切なロールを作成するリクエストを実行することです。

 INSERT INTO `role` (`id`, `parent_id`, `roleId`) VALUES (1, NULL, 'guest'), (2, 1, 'user'), (3, 2, 'moderator'), (4, 3, 'administrator');
      
      







ZfcUser、ZfcUserDoctrineORMおよびBjyAuthorizeの構成



まず、Composerの設定で新しいモジュールを登録する必要があります。

 "zf-commons/zfc-base": "v0.1.2", "zf-commons/zfc-user": "dev-master", "zf-commons/zfc-user-doctrine-orm": "dev-master", "doctrine/doctrine-orm-module": "0.7.*", "bjyoungblood/bjy-authorize": "1.4.*"
      
      





update php composer.phar updateを実行し、新しいモジュールをapplication.config.phpに追加します

 'ZfcBase', 'ZfcUser', 'ZfcUserDoctrineORM', 'BjyAuthorize',
      
      





注意! これらのモジュールの一部の設定は、自己記述型モジュールの設定によって上書きされるため、これらのモジュールをリストの一番上に追加する必要があります。



zfcuser.global.php.distファイルをvendor / zf-commons / zfc-user / configディレクトリからconfig / autoloadコピーし 、名前をzfcuser.global.phpに変更する必要があります。 この構成ファイルでは、値を設定する必要があります。

 'table_name' => 'users',
      
      





ユーザーテーブルはデフォルトでユーザーの操作に使用されるためです。



同じディレクトリに、さまざまなロールのアクセス権設定を含む構成ファイルbjyauth.global.phpを作成する必要があります。 このファイルの完全版はgithubで見ることができますgithub.com/romka/zend-blog-example/blob/master/config/autoload/bjyauth.global.php 、その最も興味深い部分は、さまざまなコントローラーへのアクセス権の配布を担当し、以下に与えられます:

 'guards' => array( /* If this guard is specified here (ie it is enabled), it will block * access to all controllers and actions unless they are specified here. * You may omit the 'action' index to allow access to the entire controller */ 'BjyAuthorize\Guard\Controller' => array( array( 'controller' => 'zfcuser', 'action' => array('index', 'login', 'authenticate', 'register'), 'roles' => array('guest'), ), array( 'controller' => 'zfcuser', 'action' => array('logout'), 'roles' => array('user'), ), array('controller' => 'Application\Controller\Index', 'roles' => array()), array( 'controller' => 'MyBlog\Controller\BlogPost', 'action' => array('index', 'view'), 'roles' => array('guest', 'user'), ), array( 'controller' => 'MyBlog\Controller\BlogPost', 'action' => array('add', 'edit', 'delete'), 'roles' => array('administrator'), ), ), ),
      
      





構成から、すべてのユーザーのインデックスへのアクセスとアクションの表示を行い、管理者ロールを持つユーザーのみのアクションを追加/編集/削除することがわかります。 これで、リンク/ブログ/追加をクリックすることで簡単に確認できます-エラー403が返されます。



これで、リンク/ user / registerを使用して登録し、SQLクエリでユーザーに管理者権限を割り当てることができます。

 INSERT INTO user_role_linker (user_id, role_id) VALUES (1, 4);
      
      





(はい、ZfcUserモジュールはユーザーロールを管理するための管理パネルを提供しません)。



開発者ツールバーのページの下部にある承認後、現在のユーザーのロールに関する情報が表示され、追加/編集/削除のアクションが403エラーを返さなくなります。



プロジェクトの現在の状態の顕著な欠点は、ブログ投稿を編集/削除するためのリンクがすべてのユーザーに表示されることです。ただし、匿名の人々にはそのようなアクションを実行する権限がありません。 BjyAuthorizeモジュールにはisAllowed Viewプラグインが含まれているため、問題を簡単に修正できます。 次の行をテンプレートに追加します。

 if ($this->isAllowed('controller/MyBlog\Controller\BlogPost:edit')) { // some code here }
      
      





対応するコントローラー/アクションへのアクセス権の可用性を確認する必要がある場合、これにより、現在のユーザーがアクセスできないテンプレートリンクを表示できなくなります。



同様に、管理者向けのindexAction()アクションでは、公開されたものだけでなく、ブログ投稿の完全なリストを表示できます。

 if ($this->isAllowed('controller/MyBlog\Controller\BlogPost:edit')) { $posts = $objectManager ->getRepository('\MyBlog\Entity\BlogPost') ->findBy(array(), array('created' => 'DESC')); } else { $posts = $objectManager ->getRepository('\MyBlog\Entity\BlogPost') ->findBy(array('state' => 1), array('created' => 'DESC')); }
      
      





現在の形式のプロジェクトは、 github.com / romka / zend-blog-example / tree / configured_userのconfigured_userタグを使用してGithubリポジトリで利用できます。



小枝



私の練習では、いくつかの異なるテンプレートエンジンを使用しましたが、Python Jinja 2は私が作業しなければならなかったテンプレートエンジン中で最も便利だと思います。 Twig PHPテンプレートエンジンは、元々Jinja 2の作者であるArmin Ronacherによって開発され、その後、 Symfonyフレームワークの開発者であるFabien Potencierが彼のサポートと開発を引き継ぎました。



TwigとZend Frameworkに組み込まれているテンプレートエンジンの主な違いの1つは、TwigテンプレートでPHPコードを使用できないことです。代わりに、テンプレートエンジンにはループ、条件ステートメントなどを実装する独自の構文があります。 TwigテンプレートはPHPコードにコンパイルされるため、PHPコードのパフォーマンスが低下することはありません。



テンプレートの継承、マクロ、フィルターシステムなどの機能のおかげです。 Twigテンプレートはコンパクトで読みやすいです。



設置



Twigをインストールするには、標準の手順に従うだけで十分です。composer.jsonに行を追加し、 php composer.phar updateを実行して、モジュールをapplication.config.phpに追加します



次に、このテンプレートエンジンを使用するモジュールに、view_managerセクションの構成ファイルに次の行を追加します。

 'strategies' => array( 'ZfcTwigViewStrategy', ),
      
      





Twigを使用する準備が整います。 さらに、両方のテンプレートエンジン(Twigとデフォルト)を一緒に使用できます。つまり、テンプレートの一部を1つのテンプレートに実装し、一部を別のテンプレートに実装できます。



小枝テンプレート



上記のテンプレートの継承はおおよそ次の内容を持つデフォルトのlayout.twigテンプレート作成できることを意味します。

 <html> <head> <title> {% block title %}Default title{% endblock title %} </title> {% block script %} <script type="text/javascript" src="/js/jquery.min.js"></script> {% endblock script %} </head> <body> <div class="content"> {% block content %}{{ content|raw }}{% endblock content %} </div> <div class="sidebar"> {% block sidebar %}{{ sidebar|raw }}{% endblock sidebar %} </div> </body> </html>
      
      





次に、layout.twigから継承するテンプレートを作成できます。このテンプレートでは、テンプレートの変更された部分のみを再定義します。

 {% extends 'layout/layout.twig' %} {% block script %} {{ parent() }} <script type="text/javascript" src="some-additional-file.js"></script> {% endblock script %} {% block content %} Custom content {% endblock content %}
      
      





デフォルトでは、後継テンプレートでオーバーライドされたブロックが親テンプレートのブロックを置き換えますが、スクリプトブロックの{{parent()}}行に注意してください。その使用は、親テンプレートの同じブロックのコンテンツがこのブロックにロードされることを意味します。



次に、新しいテンプレートエンジンを使用してテンプレートを書き直しましょう。 Zend Skeleton Applicationの標準のlayout.phtmlテンプレートから始めました。これは、ビュー/レイアウトディレクトリgithub.com/romka/zend-blog-example/blob/master/module/MyBlog/view/layout/layoutの MyBlogモジュールで見つけることができます。小枝



たとえば、今では次の代わりにビューヘルパーを使用して、どれだけコンパクトになったかに注意してください。

 <?php echo $this->url('blog', array('action' => 'edit')); ?>
      
      





あなたは電話することができます:

 {{ url('blog', {'action': 'edit'}) }}
      
      





代わりに:

 <?php echo $this->showMessages(); ?>
      
      





シンプル:

 {{ showMessages() }}
      
      





メインテンプレートの処理後、フォームを処理します。 まず、モジュールのビューディレクトリで、 マクロサブディレクトリと次の内容のforms.twigファイルを作成します

 {% macro input(name, value, type, label, size, messages) %} {% if type != 'hidden' %} <div class="form-element-{{ name }}"> {% endif %} {% if label %} {{ label }}: {% endif %} {% if type == 'textarea' %} <textarea name="{{ name }}" size="{{ size|default(20) }}" {% if messages|length > 0 %}class="error"{% endif %}/>{{ value|e }}</textarea> {% elseif type == 'checkbox' %} <input type="{{ type }}" name="{{ name }}" value="1"{% if value == true %} checked="checked"{% endif %} {% if messages|length > 0 %}class="error"{% endif %}/> {% else %} <input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value|e }}" size="{{ size|default(20) }}" {% if messages|length > 0 %}class="error"{% endif %}/> {% endif %} {% if type != 'hidden' %} </div> {% endif %} {% if messages|length > 0 %} <ul> {% for m in messages %} <li>{{ m }}</li> {% endfor %} </ul> {% endif %} {% endmacro %}
      
      





このマクロは、フォームフィールドを表示するために使用されます。 入力ではフィールドのパラメーターを受け取り、出力ではhtmlマークアップを返します。



これで、既存のadd.phtmlテンプレートを削除し、次のコンテンツを持つ新しいadd.twigに置き換えることができます。

 {% extends 'layout/layout.twig' %} {% import 'macros/forms.twig' as forms %} {% block content %} <h1>{{ title }}</h1> <form method="{{ form.attributes.method }}" action="{{ url('blog', {'action': 'add'}) }}"> {% for element in form %} {{ forms.input(element.attributes.name, element.value, element.attributes.type, element.label, 20, element.messages) }} {% endfor %} </form> {% endblock content %}
      
      





同様に、残りのテンプレートを再編集し、不要になったモジュール* .phtmlテンプレートを削除しました: github.com/romka/zend-blog-example/tree/master/module/MyBlog/view/my-blog/blog



おわりに



これで私は終了したいと思います。 ロギング、キャッシング、依存性注入、テストの作成など、多くの重要な点には触れませんでしたが、これらの問題はすべて入門記事の範囲外です。 しかし、初心者がZend Framework 2を学ぶことで、この記事が役に立つ出発点になることを願っています。



私はこの記事の3つのパートすべてを最初のパートの発行前に書いており、テキストの完成時にそれを終了することを計画しました。 コメントを読んだ後、アプリケーションを少し改善することにしました。



これらの変更を準備するには時間がかかります。記事の第4部をすぐに公開したいと思っています。



All Articles