Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit816c06b

Browse files
committed
Merge pull requestsymfony#3258 from symfony/expression-language-framework
Final additions: Expression language framework docs
2 parents93e8cd2 +0000250 commit816c06b

File tree

12 files changed

+478
-5
lines changed

12 files changed

+478
-5
lines changed

‎book/routing.rst

Lines changed: 94 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -507,10 +507,11 @@ to the ``{page}`` parameter.
507507
| /blog/my-blog-post| blog| {page} = my-blog-post|
508508
+--------------------+-------+-----------------------+
509509

510-
The answer to the problem is to add route *requirements*. The routes in this
511-
example would work perfectly if the ``/blog/{page}`` path *only* matched
512-
URLs where the ``{page}`` portion is an integer. Fortunately, regular expression
513-
requirements can easily be added for each parameter. For example:
510+
The answer to the problem is to add route *requirements* or route *conditions*
511+
(see:ref:`book-routing-conditions`). The routes in this example would work
512+
perfectly if the ``/blog/{page}`` path *only* matched URLs where the ``{page}``
513+
portion is an integer. Fortunately, regular expression requirements can easily
514+
be added for each parameter. For example:
514515

515516
..configuration-block::
516517

@@ -717,6 +718,95 @@ You can also match on the HTTP *host* of the incoming request. For more
717718
information, see:doc:`/components/routing/hostname_pattern` in the Routing
718719
component documentation.
719720

721+
.. _book-routing-conditions:
722+
723+
Completely Customized Route Matching with Conditions
724+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
725+
726+
..versionadded::2.4
727+
Route conditions were introduced in Symfony 2.4.
728+
729+
As you've seen, a route can be made to match only certain routing wildcards
730+
(via regular expressions), HTTP methods, or host names. But the routing system
731+
can be extended to have an almost infinite flexibility using ``conditions``:
732+
733+
..configuration-block::
734+
735+
..code-block::yaml
736+
737+
contact:
738+
path:/contact
739+
defaults:{ _controller: AcmeDemoBundle:Main:contact }
740+
condition:"context.getMethod() in ['GET', 'HEAD'] and request.headers.get('User-Agent') matches '/firefox/i'"
741+
742+
..code-block::xml
743+
744+
<?xml version="1.0" encoding="UTF-8" ?>
745+
<routesxmlns="http://symfony.com/schema/routing"
746+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
747+
xsi:schemaLocation="http://symfony.com/schema/routing
748+
http://symfony.com/schema/routing/routing-1.0.xsd">
749+
750+
<routeid="contact"
751+
path="/contact"
752+
condition="context.getMethod() in ['GET', 'HEAD'] and request.headers.get('User-Agent') matches '/firefox/i'"
753+
>
754+
<defaultkey="_controller">AcmeDemoBundle:Main:contact</default>
755+
</route>
756+
</routes>
757+
758+
..code-block::php
759+
760+
use Symfony\Component\Routing\RouteCollection;
761+
use Symfony\Component\Routing\Route;
762+
763+
$collection = new RouteCollection();
764+
$collection->add('contact', new Route(
765+
'/contact', array(
766+
'_controller' => 'AcmeDemoBundle:Main:contact',
767+
),
768+
array(),
769+
array(),
770+
'',
771+
array(),
772+
array(),
773+
'context.getMethod() in ["GET", "HEAD"] and request.headers.get("User-Agent") matches "/firefox/i"'
774+
));
775+
776+
return $collection;
777+
778+
The ``condition`` is an expression, and you can learn more about its syntax
779+
here::doc:`/components/expression_language/syntax`. With this, the route
780+
won't match unless the HTTP method is either GET or HEAD *and* if the ``User-Agent``
781+
header matches ``firefox``.
782+
783+
You can do any complex logic you need in the expression by leveraging two
784+
variables that are passed into the expression:
785+
786+
* ``context``: An instance of:class:`Symfony\\Component\\Routing\\RequestContext`,
787+
which holds the most fundamental information about the route being matched;
788+
* ``request``: The Symfony:class:`Symfony\\Component\\HttpFoundation\\Request``
789+
object (see:ref:`component-http-foundation-request`).
790+
791+
..caution::
792+
793+
Conditions are *not* taken into account when generating a URL.
794+
795+
..sidebar::Expressions are Compiled to PHP
796+
797+
Behind the scenes, expressions are compiled down to raw PHP. Our example
798+
would generate the following PHP in the cache directory::
799+
800+
if (rtrim($pathinfo, '/contact') === '' && (
801+
in_array($context->getMethod(), array(0 => "GET", 1 => "HEAD"))
802+
&& preg_match("/firefox/i", $request->headers->get("User-Agent"))
803+
)) {
804+
// ...
805+
}
806+
807+
Because of this, using the ``condition`` key causes no extra overhead
808+
beyond the time it takes for the underlying PHP to execute.
809+
720810
..index::
721811
single: Routing; Advanced example
722812
single: Routing; _format parameter

‎book/security.rst

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -864,6 +864,8 @@ options:
864864
(internally, an:class:`Symfony\\Component\\Security\\Core\\Exception\\AccessDeniedException`
865865
is thrown);
866866

867+
* ``allow_if`` If the expression returns false, then access is denied;
868+
867869
* ``requires_channel`` If the incoming request's channel (e.g. ``http``)
868870
does not match this value (e.g. ``https``), the user will be redirected
869871
(e.g. redirected from ``http`` to ``https``, or vice versa).
@@ -951,6 +953,58 @@ address):
951953

952954
* The second access rule is not examined as the first rule matched.
953955

956+
.. _book-security-allow-if:
957+
958+
Securing by an Expression
959+
~~~~~~~~~~~~~~~~~~~~~~~~~
960+
961+
..versionadded::2.4
962+
The ``allow_if`` functionality was introduced in Symfony 2.4.
963+
964+
Once an ``access_control`` entry is matched, you can deny access via the
965+
``roles`` key or use more complex logic with an expression in the ``allow_if``
966+
key:
967+
968+
..configuration-block::
969+
970+
..code-block::yaml
971+
972+
# app/config/security.yml
973+
security:
974+
# ...
975+
access_control:
976+
-
977+
path:^/_internal/secure
978+
allow_if:"'127.0.0.1' == request.getClientIp() or has_role('ROLE_ADMIN')"
979+
980+
..code-block::xml
981+
982+
<access-control>
983+
<rulepath="^/_internal/secure"
984+
allow-if="'127.0.0.1' == request.getClientIp() or has_role('ROLE_ADMIN')" />
985+
</access-control>
986+
987+
..code-block::php
988+
989+
'access_control' => array(
990+
array(
991+
'path' => '^/_internal/secure',
992+
'allow_if' => '"127.0.0.1" == request.getClientIp() or has_role("ROLE_ADMIN")',
993+
),
994+
),
995+
996+
In this case, when the user tries to access any URL starting with ``/_internal/secure``,
997+
they will only be granted access if the IP address is ``127.0.0.1`` or if
998+
the user has the ``ROLE_ADMIN`` role.
999+
1000+
Inside the expression, you have access to a number of different variables
1001+
and functions including ``request``, which is the Symfony
1002+
:class:`Symfony\\Component\\HttpFoundation\\Request` object (see
1003+
:ref:`component-http-foundation-request`).
1004+
1005+
For a list of the other functions and variables, see
1006+
:ref:`functions and variables<book-security-expression-variables>`.
1007+
9541008
.. _book-security-securing-channel:
9551009

9561010
Securing by Channel
@@ -1656,6 +1710,8 @@ doesn't need to be defined anywhere - you can just start using it.
16561710
Symfony2. If you define your own roles with a dedicated ``Role`` class
16571711
(more advanced), don't use the ``ROLE_`` prefix.
16581712

1713+
.. _book-security-role-hierarchy:
1714+
16591715
Hierarchical Roles
16601716
~~~~~~~~~~~~~~~~~~
16611717

@@ -1834,6 +1890,33 @@ the built-in helper function:
18341890
idea to have a main firewall that covers all URLs (as has been shown
18351891
in this chapter).
18361892

1893+
.. _book-security-template-expression:
1894+
1895+
..versionadded::2.4
1896+
The ``expression`` functionality was introduced in Symfony 2.4.
1897+
1898+
You can also use expressions inside your templates:
1899+
1900+
..configuration-block::
1901+
1902+
..code-block::html+jinja
1903+
1904+
{% if is_granted(expression(
1905+
'"ROLE_ADMIN" in roles or (user and user.isSuperAdmin())'
1906+
)) %}
1907+
<a href="...">Delete</a>
1908+
{% endif %}
1909+
1910+
..code-block::html+php
1911+
1912+
<?php if ($view['security']->isGranted(new Expression(
1913+
'"ROLE_ADMIN" in roles or (user and user.isSuperAdmin())'
1914+
))): ?>
1915+
<a href="...">Delete</a>
1916+
<?php endif; ?>
1917+
1918+
For more details on expressions and security, see:ref:`book-security-expressions`.
1919+
18371920
Access Control in Controllers
18381921
-----------------------------
18391922

@@ -1856,6 +1939,91 @@ method of the security context::
18561939
A firewall must be active or an exception will be thrown when the ``isGranted``
18571940
method is called. See the note above about templates for more details.
18581941

1942+
.. _book-security-expressions:
1943+
1944+
Complex Access Controls with Expressions
1945+
----------------------------------------
1946+
1947+
..versionadded::2.4
1948+
The expression functionality was introduced in Symfony 2.4.
1949+
1950+
In addition to a role like ``ROLE_ADMIN``, the ``isGranted`` method also
1951+
accepts an:class:`Symfony\\Component\\ExpressionLanguage\\Expression` object::
1952+
1953+
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
1954+
use Symfony\Component\ExpressionLanguage\Expression;
1955+
// ...
1956+
1957+
public function indexAction()
1958+
{
1959+
if (!$this->get('security.context')->isGranted(new Expression(
1960+
'"ROLE_ADMIN" in roles or (user and user.isSuperAdmin())'
1961+
))) {
1962+
throw new AccessDeniedException();
1963+
}
1964+
1965+
// ...
1966+
}
1967+
1968+
In this example, if the current user has ``ROLE_ADMIN`` or if the current
1969+
user object's ``isSuperAdmin()`` method returns ``true``, then access will
1970+
be granted (note: your User object may not have an ``isSuperAdmin`` method,
1971+
that method is invented for this example).
1972+
1973+
This uses an expression and you can learn more about the expression language
1974+
syntax, see:doc:`/components/expression_language/syntax`.
1975+
1976+
.. _book-security-expression-variables:
1977+
1978+
Inside the expression, you have access to a number of variables:
1979+
1980+
* ``user`` The user object (or the string ``anon`` if you're not authenticated);
1981+
* ``roles`` The array of roles the user has, including from the
1982+
:ref:`role hierarchy<book-security-role-hierarchy>` but not including
1983+
the ``IS_AUTHENTICATED_*`` attributes (see the functions below);
1984+
* ``object``: The object (if any) that's passed as the second argument to
1985+
``isGranted`` ;
1986+
* ``token`` The token object;
1987+
* ``trust_resolver``: The:class:`Symfony\\Component\\Security\\Core\\Authentication\\AuthenticationTrustResolverInterface`,
1988+
object: you'll probably use the ``is_*`` functions below instead.
1989+
1990+
Additionally, you have access to a number of functions inside the expression:
1991+
1992+
* ``is_authenticated``: Returns ``true`` if the user is authenticated via "remember-me"
1993+
or authenticated "fully" - i.e. returns true if the user is "logged in";
1994+
* ``is_anonymous``: Equal to using ``IS_AUTHENTICATED_ANONYMOUSLY`` with
1995+
the ``isGranted`` function;
1996+
* ``is_remember_me``: Similar, but not equal to ``IS_AUTHENTICATED_REMEMBERED``,
1997+
see below;
1998+
* ``is_fully_authenticated``: Similar, but not equal to ``IS_AUTHENTICATED_FULLY``,
1999+
see below;
2000+
* ``has_role``: Checks to see if the user has the given role - equivalent
2001+
to an expression like ``'ROLE_ADMIN' in roles``.
2002+
2003+
..sidebar::``is_remember_me`` is different than checking ``IS_AUTHENTICATED_REMEMBERED``
2004+
2005+
The ``is_remember_me`` and ``is_authenticated_fully`` functions are *similar*
2006+
to using ``IS_AUTHENTICATED_REMEMBERED`` and ``IS_AUTHENTICATED_FULLY``
2007+
with the ``isGranted`` function - but they are **not** the same. The
2008+
following shows the difference::
2009+
2010+
use Symfony\Component\ExpressionLanguage\Expression;
2011+
// ...
2012+
2013+
$sc = $this->get('security.context');
2014+
$access1 = $sc->isGranted('IS_AUTHENTICATED_REMEMBERED');
2015+
2016+
$access2 = $sc->isGranted(new Expression(
2017+
'is_remember_me() or is_fully_authenticated()'
2018+
));
2019+
2020+
Here, ``$access1`` and ``$access2`` will be the same value. Unlike the
2021+
behavior of ``IS_AUTHENTICATED_REMEMBERED`` and ``IS_AUTHENTICATED_FULLY``,
2022+
the ``is_remember_me`` function *only* returns true if the user is authenticated
2023+
via a remember-me cookie and ``is_fully_authenticated`` *only* returns
2024+
true if the user has actually logged in during this session (i.e. is
2025+
full-fledged).
2026+
18592027
Impersonating a User
18602028
--------------------
18612029

‎book/service_container.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,8 @@ service needs the ``my_mailer`` service in order to function. When you define
627627
this dependency in the service container, the container takes care of all
628628
the work of instantiating the classes.
629629

630+
.. _book-services-expressions:
631+
630632
Using the Expression Language
631633
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
632634

‎components/expression_language/introduction.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
Single: Components; Expression Language
44

55
The ExpressionLanguage Component
6-
=================================
6+
================================
77

88
The ExpressionLanguage component provides an engine that can compile and
99
evaluate expressions. An expression is a one-liner that returns a value
@@ -32,6 +32,8 @@ component is a perfect candidate for the foundation of a *business rule engine*.
3232
The idea is to let the webmaster of a website configure things in a dynamic
3333
way without using PHP and without introducing security problems:
3434

35+
.. _component-expression-language-examples:
36+
3537
..code-block::text
3638
3739
# Get the special price if

‎cookbook/expression/expressions.rst

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
..index::
2+
single: Expressions in the Framework
3+
4+
How to use Expressions in Security, Routing, Services, and Validation
5+
=====================================================================
6+
7+
..versionadded::2.4
8+
The expression functionality was introduced in Symfony 2.4.
9+
10+
In Symfony 2.4, a powerful:doc:`ExpressionLanguage</components/expression_language/introduction>`
11+
component was added to Symfony. This allows us to add highly customized
12+
logic inside configuration.
13+
14+
The Symfony Framework leverages expressions out of the box in the following
15+
ways:
16+
17+
*:ref:`Configuring services<book-services-expressions>`;
18+
*:ref:`Route matching conditions<book-routing-conditions>`;
19+
*:ref:`Checking security<book-security-expressions>` and
20+
:ref:`access controls with allow_if<book-security-allow-if>`;
21+
*:doc:`Validation</reference/constraints/Expression>`.
22+
23+
For more information about how to create and work with expressions, see
24+
:doc:`/components/expression_language/syntax`.

‎cookbook/expression/index.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Expressions
2+
===========
3+
4+
..toctree::
5+
:maxdepth:2
6+
7+
expressions

‎cookbook/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ The Cookbook
1515
doctrine/index
1616
email/index
1717
event_dispatcher/index
18+
expression/index
1819
form/index
1920
logging/index
2021
profiler/index

‎cookbook/map.rst.inc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@
7878
* :doc:`/cookbook/event_dispatcher/method_behavior`
7979
* (service container) :doc:`/cookbook/service_container/event_listener`
8080

81+
* :doc:`/cookbook/expression/index`
82+
83+
* :doc:`/cookbook/expression/expressions`
84+
8185
* :doc:`/cookbook/form/index`
8286

8387
* :doc:`/cookbook/form/form_customization`

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp