Phalcon PHPフレームワーク。 注釈を操作する

「Vivo、presto、prestissimo ...」



Phalconについてはまだほとんど資料がありませんが、フレームワークは非常に興味深く、注目に値します。 興味深いPhalconソリューションの1つは、高度な注釈機能です。 パーサーはCで書かれており、非常に高速に動作します。 これにより、設定の一部(ほとんどの場合)を構成ファイルからコードに簡単かつ自然に転送できます。







パートI. Vivo(高速)。



Phalconでのルーティングは、かなり「創造的な」タスクです。

多くの例には、ルートを割り当てるさまざまな方法がたくさんあります。

Habrでは、xmlファイルの使用例さえすり抜けていました...

そして、これは多くのフレームワークがアノテーションを介したルーティングを提供しているときです。

ファルコンはどうですか?

Phalconは、注釈でルーティングが可能であることを文書で控えめかつ静かに示しています。

そのために、Phalconの作成者はCで注釈パーサーを作成しただけです。

初めて!

注釈を含めるには何が必要ですか?

何もありません。

ブートストラップファイルでは、ほんの数行のコードで注釈サービスを実装します。 そしてそれだけです。

... //set routers $di->set('router', function() { $router = new \Phalcon\Mvc\Router\Annotations(false); $router->removeExtraSlashes(true); $router->setUriSource(\Phalcon\Mvc\Router::URI_SOURCE_SERVER_REQUEST_URI); $router->addResource('Index', "/"); $router->notFound([ "controller" => "index", "action" => "page404" ]); return $router; }); ...
      
      





ルート(プレフィックス付きのものを含む)に、コントローラーで直接指定します。

 ... /** * @Post("create") */ public function createAction() { /... } ...
      
      





ルーティング(要求タイプ、パラメーター)については、ドキュメントで詳しく説明しています。



パートII プレスト(可能な限り高速)



注釈のルーティングは、もちろん良いことです。 ただし、プロジェクト内のデータを処理する必要があります。 そして、ここでPhalconの1つの機能に気付くことができます。

データベースを操作するとき、彼は通常3つのクエリを作成します。

最初は、データベース内のテーブルをチェックします。

2番目はテーブルメタデータを取得します。

3番目の直接リクエスト。

私はこれがどれほど正しいのか分かりません、私は議論しません。 しかし、やや不便です。

3つのリクエストは必要ありません。 zashashnikのどこかにテーブルメタデータが必要です。

たとえば、キャッシュ内。

そして、ファルコンも同じ意見を持っています。 したがって、メタデータをキャッシュに保存することをお勧めします。 注釈を使用できます。

再びDI、再びボットストラップ:

 ... //Set a models manager $di->set('modelsManager', new \Phalcon\Mvc\Model\Manager()); //Set the models cache service $di->set('modelsCache', function() { //Cache data for one day by default $frontCache = new \Phalcon\Cache\Frontend\Data([ "lifetime" => 86400 ]); $cache = new \Phalcon\Cache\Backend\Memcache($frontCache, [ "host" => "localhost", "port" => "11211", 'persistent' => TRUE, ]); return $cache; }); $di->set('modelsMetadata', function() { // Create a meta-data manager with APC //$metaData = new \Phalcon\Mvc\Model\MetaData\Apc([ // "lifetime" => 86400, // "prefix" => "general-phsql" //]); $metaData = new \Phalcon\Mvc\Model\MetaData\Memory([ 'prefix' => 'general', ]); $metaData->setStrategy(new StrategyAnnotations()); return $metaData; }); ...
      
      





その後、一度だけ読み取られたメタデータはキャッシュに保存されます。

開発時には、メモリ内のストレージに切り替えることができます。



ここで、原則として、すべて。 繰り返しになりますが、詳細はドキュメントに記載されています。



さて、これらのメカニズムには驚くべきことは何もありません。 非常に高速に動作することを除いて。 Cで作成されたコンポーネントでこれを達成できる限り、迅速に実行できます。つまり、ほとんど認識できません。

しかし、他のフレームワークにもこれらのメカニズムがあります。

私たちは何かおいしい、いくつかの熱意が欲しい...



パートIII。 Prestissimo(さらに高速)。



サイトを設計するときに管理パネルを作成する必要があることは、おそらく秘密ではありません。

そして、これらはフォーム、フォーム、そしてもう一度フォームです。 多くのフォーム。 そして、これは疲れています...

自動化が必要です。

フォームは何で構成されていますか? もちろん、キー要素は入力タグです。

通常、タイプタイプ、長さ、パターン塗りつぶしパターンなどがあります。

そして、これらはすべてフォームごとに指定する必要があります...テーブルの各フィールドについて...

自動化が必要です。 たくさんのコードを書く気はありません。

そして、あらゆるエンティティの普遍的なフォームを記述するため。

そして、ここでも注釈が役立ちます。 再び、パーサーはCにあります。

Phalconは、Phalcon \ Forms \ Formコンポーネントを提供しています。

最も単純なユーザーテーブルを取り上げます。 彼女のモデル:

 <?php namespace Frontend\Model; class Users extends \Phalcon\Mvc\Model { /** * @Primary * @Identity * @Column(type="integer", nullable=false) * @FormOptions(type=hidden) */ public $id; /** * @Column(type="string", nullable=false) * @FormOptions(type=text, length=32) */ public $name; /** * @Column(type="integer", nullable=false) * @FormOptions(type=email) */ public $email; /** * @Column(type="integer", nullable=false) * @FormOptions(type=text, length=9, pattern='[0-9]{9}') */ public $indcode; }
      
      





ここでは、フォームを構築するために必要なオプションを示す独自の注釈を使用します。

はい、特定のケースで使用するために、私たち自身でこのアノテーションを作成しました。

@FormOptionsがあります。 type属性では、入力に必要なフィールドのタイプを示します。

Phalconは、次のタイプのPhalcon \ Forms \ Elementを提供しています。

Phalcon \ Forms \ Element \ Check

Phalcon \ Forms \ Element \ Date

Phalcon \ Forms \ Element \ Email

Phalcon \ Forms \ Element \ File

ファルコン\フォーム\要素\非表示

Phalcon \ Forms \ Element \ Numeric

Phalcon \ Forms \ Element \ Password

Phalcon \ Forms \ Element \ Select

Phalcon \ Forms \ Element \ Submit

Phalcon \ Forms \ Element \ Text

Phalcon \ Forms \ Element \ TextArea

十分すぎるほど。

小さい場合はそのままです...

何らかの方法でPhalconに注釈を認識させる必要があります...

これ以上簡単なことはありません!

bootstrap-注釈パーサーを有効にします。

 ... //Annotations $di->set('annotations', function() { return new \Phalcon\Annotations\Adapter\Memory(); }); ...
      
      





開発中に、メモリアダプタを使用できます。

実稼働環境では、ファイルストレージ、APC、XCacheに切り替えることができます。

次に、任意のエンティティのフォームクラスを作成します。

フォームクラス
 <?php use Phalcon\Forms\Form, \Phalcon\Forms\Element\Submit as Submit; class EntityForm extends Form { public $fields = []; private $classprefix = '\\Phalcon\\Forms\\Element\\'; public $action; /** * @param object $model, action */ public function initialize($model, $action) { $this->action = $action; //      $object = $model; $this->setEntity($object); //   $attributes = $this->modelsMetadata->getAttributes($object); //     $metadata = $this->annotations->get($object); //   @FormOptions foreach ( $attributes as $attribute ) { $this->fields[$attribute] = $metadata ->getPropertiesAnnotations()[$attribute] ->get('FormOptions') ->getArguments(); } //       foreach ($this->fields as $field => $type) { $fieldtype = array_shift($type); //  type       $fieldclass = $this->classprefix.$fieldtype; $this->add(new $fieldclass($field, $type)); // label     if ( $fieldtype !== 'hidden') { $this->get($field)->setLabel($this->get($field)->getName()); } } //    $this->add(new Submit('submit',[ 'value' => 'Send', ])); } public function renderform() { echo $this->tag->form([ $this->action, 'id' => 'actorform', ]); //fill form tags foreach ($this as $element) { // collect messages $messages = $this->getMessagesFor($element->getName()); if (count($messages)) { // each element render echo '<div class="messages">'; foreach ($messages as $message) { echo $message; } echo '</div>'; } echo '<div>'; echo '<label for="', $element->getName(), '">', $element->getLabel(), '</label>'; echo $element; echo '</div>'; } echo $this->tag->endForm(); } }
      
      







ここでは、EntityFormクラスを初期化するときに、渡されたオブジェクトとその注釈のメタデータを読み取ります。

その後、必要なすべてのフィールドをフォームに導入します。

renderform関数は、ブラウザにフォームを表示するだけです。



コントローラーに戻って、フォーム出力アクションを作成しましょう。

 ... /** * @Get("form") */ public function formAction() { $myform = new EntityForm(new Users(), 'create'); $this->view->setVars([ 'myform' => $myform, ]); } ...
      
      





および受信者:

 ... /** * @Post("create") */ public function createAction() { echo '<pre>'; var_dump($_POST); echo '</pre>'; } ...
      
      





フォームを表示するために、出力テンプレート(Volt)にのみ残ります。

{{ myform.renderform() }}





以上です。

もちろん、CSRF保護、データ検証、およびストレージをフォームクラスに追加する必要があります。

しかし、この記事の目的は、Phalconでアノテーションを使用することのシンプルさと使いやすさを示すことです。

これらの機能は、強力で高速なPhalconPHPアノテーションパーサーのおかげで提供されています。

そして、Phalconの使用を開始すると、非常に高速であることを認識します。

「Hello、world!」の出力だけでなく

Phalconのスピードと使いやすさは本当に素晴らしいです。

index.php
 <?php use Phalcon\Mvc\View\Engine\Volt; use Phalcon\Mvc\Model\MetaData\Strategy\Annotations as StrategyAnnotations; try { //Register an autoloader $loader = new \Phalcon\Loader(); $loader->registerDirs([ '../app/controllers/', '../app/models/', '../app/forms/' ]); $loader->registerNamespaces([ 'Frontend\\Model' => __DIR__.'/../app/models/', ]); $loader->register(); //Create a DI $di = new \Phalcon\DI\FactoryDefault(); //Set a models manager $di->set('modelsManager', new \Phalcon\Mvc\Model\Manager()); //Set the models cache service $di->set('modelsCache', function() { //Cache data for one day by default $frontCache = new \Phalcon\Cache\Frontend\Data([ "lifetime" => 86400 ]); $cache = new \Phalcon\Cache\Backend\Memcache($frontCache, [ "host" => "localhost", "port" => "11211", 'persistent' => TRUE, ]); return $cache; }); $di->set('modelsMetadata', function() { // Create a meta-data manager with APC //$metaData = new \Phalcon\Mvc\Model\MetaData\Apc([ // "lifetime" => 86400, // "prefix" => "general-phsql" //]); $metaData = new \Phalcon\Mvc\Model\MetaData\Memory([ 'prefix' => 'general', ]); $metaData->setStrategy(new StrategyAnnotations()); return $metaData; }); //SQL profiler $di->set('profiler', function(){ return new \Phalcon\Db\Profiler(); }, true); //set database connection $di->set('db', function() use ($di) { $eventsManager = new \Phalcon\Events\Manager(); //Get a shared instance of the DbProfiler $profiler = $di->getProfiler(); //Listen all the database events $eventsManager->attach('db', function($event, $connection) use ($profiler) { if ($event->getType() == 'beforeQuery') { $profiler->startProfile($connection->getSQLStatement()); } if ($event->getType() == 'afterQuery') { $profiler->stopProfile(); } }); $connection = new \Phalcon\Db\Adapter\Pdo\Mysql([ "host" => "localhost", "username" => "root", "password" => "12345", "dbname" => "general" ]); //Assign the eventsManager to the db adapter instance $connection->setEventsManager($eventsManager); return $connection; }); //Register Volt as a service $di->set('voltService', function($view, $di) { $volt = new Volt($view, $di); $volt->setOptions([ "compiledPath" => "../app/cache/", ]); return $volt; }); //Setting up the view component $di->set('view', function(){ $view = new \Phalcon\Mvc\View(); $view->setViewsDir('../app/views/'); $view->registerEngines([ ".volt" => 'voltService' ]); return $view; }); //Create Form manager $di->set('forms', function() { $forms = new \Phalcon\Forms\Manager(); return $forms; }); $di->set('session', function() use($di) { $session = new Phalcon\Session\Adapter\Files(); $session->setoptions([ 'uniqueId' => 'privatRsc', ]); $session->start(); return $session; }); //set routers $di->set('router', function() { $router = new \Phalcon\Mvc\Router\Annotations(false); $router->removeExtraSlashes(true); $router->setUriSource(\Phalcon\Mvc\Router::URI_SOURCE_SERVER_REQUEST_URI); $router->addResource('Index', "/"); $router->notFound([ "controller" => "index", "action" => "page404" ]); return $router; }); //Annotations $di->set('annotations', function() { return new \Phalcon\Annotations\Adapter\Memory(); }); //Handle the request $application = new \Phalcon\Mvc\Application($di); echo $application->handle()->getContent(); } catch(\Phalcon\Exception $e) { echo "PhalconException: ", $e->getMessage(); }
      
      







IndexController.php
 <?php use \Frontend\Model\Users as Users; /** * @RoutePrefix("/") **/ class IndexController extends \Phalcon\Mvc\Controller { /** * @Get("") */ public function indexAction() { echo <h3>Index Action</h3>; } /** * @Get("form") */ public function formAction() { $myform = new EntityForm(new Users(), 'create'); $this->view->setVars([ 'myform' => $myform, ]); } /** * @Post("create") */ public function createAction() { echo '<pre>'; var_dump($_POST); echo '</pre>'; } /** * @Get("page404") */ public function page404Action() { echo '404 - route not found'; } }
      
      







EntityForm.php
 <?php use Phalcon\Forms\Form, \Phalcon\Forms\Element\Submit as Submit; class EntityForm extends Form { public $fields = []; private $classprefix = '\\Phalcon\\Forms\\Element\\'; public $action; /** * @param object $model, action */ public function initialize($model, $action) { $this->action = $action; //Set fields options from annotations $object = $model; $this->setEntity($object); $attributes = $this->modelsMetadata->getAttributes($object); $metadata = $this->annotations->get($object); foreach ( $attributes as $attribute ) { $this->fields[$attribute] = $metadata ->getPropertiesAnnotations()[$attribute] ->get('FormOptions') ->getArguments(); } foreach ($this->fields as $field => $type) { $fieldtype = array_shift($type); $fieldclass = $this->classprefix.$fieldtype; $this->add(new $fieldclass($field, $type)); if ( $fieldtype !== 'hidden') { $this->get($field)->setLabel($this->get($field)->getName()); } } $this->add(new Submit('submit',[ 'value' => 'Send', ])); } public function renderform() { echo $this->tag->form([ $this->action, 'id' => 'actorform', ]); //fill form tags foreach ($this as $element) { // collect messages $messages = $this->getMessagesFor($element->getName()); if (count($messages)) { // each element render echo '<div class="messages">'; foreach ($messages as $message) { echo $message; } echo '</div>'; } echo '<div>'; echo '<label for="', $element->getName(), '">', $element->getLabel(), '</label>'; echo $element; echo '</div>'; } echo $this->tag->endForm(); } }
      
      







Users.php
 <?php namespace Frontend\Model; class Users extends \Phalcon\Mvc\Model { /** * @Primary * @Identity * @Column(type="integer", nullable=false) * @FormOptions(type=hidden) */ public $id; /** * @Column(type="string", nullable=false) * @FormOptions(type=text, length=32) */ public $name; /** * @Column(type="integer", nullable=false) * @FormOptions(type=email) */ public $email; /** * @Column(type="integer", nullable=false) * @FormOptions(type=text, length=9, pattern='[0-9]{9}') */ public $indcode; }
      
      







form.volt
 <h2>Test form in Volt</h2> <hr> {{ myform.renderform() }} <hr>
      
      






All Articles