Symfony 2.4の新機能:ExpressionLanguageコンポーネント

Symfony 2.4は、新しいコンポーネントExpressionLanguageを導入します。 コンポーネントは、「式」をコンパイルおよび実行するためのエンジンです。
この言語は、Twigの簡易バージョンです。 式は1行に収まり、通常ブール値を返しますが、これに限定されません。
Twigとは異なり、ExpressionLanguageは2つのモードで動作します。

実行時に変更する必要のないPHPコードに式をコンパイルできるようにするには、演算子を使用し. 明示的であり、1つの可能な動作のみを意味する必要がありますfoo.barオブジェクトのプロパティの場合、 foo['bar']は配列にアクセスし、 foo.getBar()はメソッドを呼び出します。
コンポーネントの使用は可能な限り簡単です。
 use Symfony\Component\ExpressionLanguage\ExpressionLanguage; $language = new ExpressionLanguage(); echo $language->evaluate('1 + 1'); // echo 2 echo $language->compile('1 + 2'); // echo "(1 + 2)" 

式言語は、小枝と同じことをサポートします:数学演算子、文字列、数値、配列、ハッシュ、ブール変数...式は非常に限られたPHPサンドボックスと見なすことができ、外部の影響は不可能であり、コンパイルまたは実行前にすべての変数を宣言する必要があります式。
 $language->evaluate('a.b', array('a' => new stdClass())); $language->compile('a.b', array('a')); 

最後になりましたが、関数を使用して言語を簡単に拡張できます。 Twigの対応物と同じように機能します(詳細についてはregister()メソッドを参照してください)
ユースケースはどうですか? Symfonyで使用される他の多くのコンポーネントにコンポーネントを埋め込みました。


サービスコンテナ


引数をコンテナに渡すことができる場所であればどこでも式を使用できます。
 $c->register('foo', 'Foo')->addArgument(new Expression('bar.getvalue()')); 

コンテナでは、式は、サービスを取得するservice service()parameterの値を取得するparameter 2つの関数によって補完されます。
 service("bar").getValue(parameter("value")) 

XMLの場合:
 <service id="foo" class="Foo"> <argument type="expression">service('bar').getvalue(parameter('value'))</argument> </service> 

PHPダンパーが式をコンパイルするため、実行時にオーバーヘッドはありません。 前の例は、次のPHPコードにコンパイルされます。
 $this->get("bar")->getvalue($this->getParameter("value")) 


アクセス制御規則


アクセスルールの設定は誤解を招く可能性があり、 安全でないアプリケーションにつながる可能性があります
新しいallow_ifディレクティブを使用すると、アプリケーションでアクセスルールを簡単に設定できます。
 access_control: - { path: ^/_internal/secure, allow_if: "'127.0.0.1' == request.getClientIp() or has_role('ROLE_ADMIN')" } 

このルールは、 localhostまたは管理者権限なしでログインするユーザーに対して、 /_internal/secureで始まるパスを制限します。
requesttokenおよびuserは、アクセスできる変数ですis_anonymous()is_authenticated()is_fully_authenticated()is_rememberme()and has_role()は、アクセスルールを設定するときに式で使用できる関数です。

小枝


expression関数を使用して、テンプレートで式を使用することもできます
 {% if is_granted(expression('has_role("FOO")')) %} ... {% endif %} 


SensioFrameworkExtraBundleを使用する場合は、 @ Securityアノテーションを使用して、コントローラーを保護するオプションもあります
 /** * @Route("/post/{id}") * @Security("has_role('ROLE_ADMIN')") */ public function showAction(Post $post) { } 

@ Securityアノテーションは、Symfony 2.4より前にリリースされるバンドルのバージョン3の一部になります

キャッシング


SensioFrameworkExtraBundleの3番目のバージョンでは、@ Cacheアノテーションも使用可能になり、HTTPキャッシングにアクセスできるようになります。 単純な状況で定型コードを何度も書く代わりに:
 /** * @Route("/post/{id}") * @Cache(smaxage="15") */ public function showAction(Request $request, Post $post) { $response = new Response(); $response->setLastModified($post->getUpdated()); if ($response->isNotModified($request)) { return $response; } // ... } 

アノテーションのすべてを構成できます(これはETagでも機能します)。
 /** * @Route("/post/{id}") * @Cache(smaxage="15", lastModified="post.getUpdatedAt()") */ public function showAction(Post $post) { // ... } 

ルーティング


shemeでは、Symfonyは事前定義された変数( infomethodsheme )によってルートを選択できますが、一部はリクエスト( Requestオブジェクト)からの情報に基づいてより複雑なロジックを必要とします
これらの特殊なケースをカバーするには、 conditionディレクティブを使用します。これにより、 requestおよびルーティングcontext変数を使用して任意の式を追加できます。
 hello: path: /hello/{name} condition: "context.getMethod() in ['GET', 'HEAD'] and request.headers.get('User-Agent') =~ '/firefox/i'" 

また、PHPルーティングルールダンパー(URLマッチャー)を使用すると、すべての式がPHPコードにコンパイルされるため、オーバーヘッドはありません。
 // hello if (0 === strpos($pathinfo, '/hello') && preg_match('#^/hello/(?P<name>[^/]++)$#s', $pathinfo, $matches) && (in_array($context->getMethod(), array(0 => "GET", 1 => "HEAD")) && preg_match("/firefox/i", $request->headers->get("User-Agent"))) ) { return $this->mergeDefaults(array_replace($matches, array('_route' => 'hello')), array ()); } 

これらの条件は、URLを生成するときに使用されないことに注意してください。

検証


新しいExpression条件を使用すると、検証に式を使用できます。
 use Symfony\Component\Validator\Constraints as Assert; /** * @Assert\Expression("this.getFoo() == 'fo'", message="Not good!") */ class Obj { public function getFoo() { return 'foo'; } } 

バリデータ式では、 thisは現在の検証オブジェクトを指します。

ビジネスルールエンジン


さらに、フレームワーク自体のコンポーネントを使用する式言語は、ビジネスルールエンジンを作成するための優れた候補です。 その考えは、サイトのウェブマスター(管理者)が、PHPを使用せずに、セキュリティ問題に専念することなく、サイトを柔軟に構成できるということです。
 # Get the special price if user.getGroup() in ['good_customers', 'collaborator'] # Promote article to the homepage when article.commentCount > 100 and article.category not in ["misc"] # Send an alert when product.stock < 15 


これは、Symfony 2.4の新機能を見る最後の投稿です。 数日以内に、最初のプレリリースバージョン(リリース候補)が利用可能になります。

誰もがこのPHPの使用を好むとは思いませんが、私はこのコンポーネントの作成者ではなく、翻訳者であり、記事であり、それが好きかどうかを判断するまでは覚えておいてください(式が小枝に組み込まれた理由は特に印象的でした)。
すべてのコメントと提案はPMでお願いします

Source: https://habr.com/ru/post/J202058/


All Articles