diff --git a/.travis.yml b/.travis.yml index 9afcdfaaff4..73c2a7043f4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,3 +8,8 @@ install: - "pip install -q -r requirements.txt --use-mirrors" script: sphinx-build -nW -b html -d _build/doctrees . _build/html + +branches: + except: + - github-comments + diff --git a/components/http_foundation/introduction.rst b/components/http_foundation/introduction.rst index 4db19238609..e40f1a7a9e5 100644 --- a/components/http_foundation/introduction.rst +++ b/components/http_foundation/introduction.rst @@ -177,7 +177,7 @@ on how this is used in the Symfony2 framework, see :ref:`the Symfony2 book `. Finally, the raw data sent with the request body can be accessed using -:method:`Symfony\\Component\\HttpFoundation\\Request::getContent()`:: +:method:`Symfony\\Component\\HttpFoundation\\Request::getContent`:: $content = $request->getContent(); diff --git a/components/translation/introduction.rst b/components/translation/introduction.rst index 76298499f28..a0deba774b8 100644 --- a/components/translation/introduction.rst +++ b/components/translation/introduction.rst @@ -73,19 +73,19 @@ Loader too. The default loaders are: * :class:`Symfony\\Component\\Translation\\Loader\\CsvFileLoader` - to load catalogs from CSV files. * :class:`Symfony\\Component\\Translation\\Loader\\IcuDatFileLoader` - to load - catalogs form resource bundles. + catalogs from resource bundles. * :class:`Symfony\\Component\\Translation\\Loader\\IcuResFileLoader` - to load - catalogs form resource bundles. + catalogs from resource bundles. * :class:`Symfony\\Component\\Translation\\Loader\\IniFileLoader` - to load - catalogs form ini files. + catalogs from ini files. * :class:`Symfony\\Component\\Translation\\Loader\\MoFileLoader` - to load - catalogs form gettext files. + catalogs from gettext files. * :class:`Symfony\\Component\\Translation\\Loader\\PhpFileLoader` - to load catalogs from PHP files. * :class:`Symfony\\Component\\Translation\\Loader\\PoFileLoader` - to load - catalogs form gettext files. + catalogs from gettext files. * :class:`Symfony\\Component\\Translation\\Loader\\QtFileLoader` - to load - catalogs form QT XML files. + catalogs from QT XML files. * :class:`Symfony\\Component\\Translation\\Loader\\XliffFileLoader` - to load catalogs from Xliff files. * :class:`Symfony\\Component\\Translation\\Loader\\JsonFileLoader` - to load diff --git a/cookbook/configuration/web_server_configuration.rst b/cookbook/configuration/web_server_configuration.rst index 2ea1a976f6b..6bd96876195 100644 --- a/cookbook/configuration/web_server_configuration.rst +++ b/cookbook/configuration/web_server_configuration.rst @@ -11,8 +11,8 @@ front controllers live. For more details, see the :ref:`the-web-directory`. The web directory services as the document root when configuring your web server. In the examples below, this directory is in ``/var/www/project/web/``. -Apache2 -------- +Apache2 with mod_php/PHP-CGI +---------------------------- For advanced Apache configuration options, see the official `Apache`_ documentation. The minimum basics to get your application running under Apache2 @@ -63,6 +63,107 @@ following configuration snippet: Require all granted +Apache2 with PHP-FPM +-------------------- + +To make use of PHP5-FPM with Apache, you first have to ensure that you have +the FastCGI process manager ``php-fpm`` binary and Apache's FastCGI module +installed (for example, on a Debian based system you have to install the +``libapache2-mod-fastcgi`` and ``php5-fpm`` packages). + +PHP-FPM uses so called *pools* to handle incoming FastCGI requests. You can +configure an arbitrary number of pools in the FPM configuration. In a pool +you configure either a TCP socket (IP and port) or a unix domain socket to +listen on. Each pool can also be run under a different UID and GID: + +.. code-block:: ini + + ; a pool called www + [www] + user = www-data + group = www-data + + ; use a unix domain socket + listen = /var/run/php5-fpm.sock + + ; or listen on a TCP socket + listen = 127.0.0.1:9000 + +Using mod_proxy_fcgi with Apache 2.4 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you are running Apache 2.4, you can easily use ``mod_proxy_fcgi`` to pass +incoming requests to PHP-FPM. Configure PHP-FPM to listen on a TCP socket +(``mod_proxy`` currently `does not support unix sockets`_), enable ``mod_proxy`` +and ``mod_proxy_fcgi`` in your Apache configuration and use the ``ProxyPassMatch`` +directive to pass requests for PHP files to PHP FPM: + +.. code-block:: apache + + + ServerName domain.tld + ServerAlias www.domain.tld + + ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/var/www/project/web/$1 + + DocumentRoot /var/www/project/web + + # enable the .htaccess rewrites + AllowOverride All + Require all granted + + + ErrorLog /var/log/apache2/project_error.log + CustomLog /var/log/apache2/project_access.log combined + + +.. caution:: + + When you run your Symfony application on a subpath of your document root, + the regular expression used in ``ProxyPassMatch`` directive must be changed + accordingly: + + .. code-block:: apache + + ProxyPassMatch ^/path-to-app/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/var/www/project/web/$1 + +PHP-FPM with Apache 2.2 +~~~~~~~~~~~~~~~~~~~~~~~ + +On Apache 2.2 or lower, you cannot use ``mod_proxy_fcgi``. You have to use +the `FastCgiExternalServer`_ directive instead. Therefore, your Apache configuration +should look something like this: + +.. code-block:: apache + + + ServerName domain.tld + ServerAlias www.domain.tld + + AddHandler php5-fcgi .php + Action php5-fcgi /php5-fcgi + Alias /php5-fcgi /usr/lib/cgi-bin/php5-fcgi + FastCgiExternalServer /usr/lib/cgi-bin/php5-fcgi -host 127.0.0.1:9000 -pass-header Authorization + + DocumentRoot /var/www/project/web + + # enable the .htaccess rewrites + AllowOverride All + Order allow,deny + Allow from all + + + ErrorLog /var/log/apache2/project_error.log + CustomLog /var/log/apache2/project_access.log combined + + +If you prefer to use a unix socket, you have to use the ``-socket`` option +instead: + +.. code-block:: apache + + FastCgiExternalServer /usr/lib/cgi-bin/php5-fcgi -socket /var/run/php5-fpm.sock -pass-header Authorization + Nginx ----- @@ -110,4 +211,6 @@ are: be sure to include them in the ``location`` block above. .. _`Apache`: http://httpd.apache.org/docs/current/mod/core.html#documentroot +.. _`does not support unix sockets`: https://issues.apache.org/bugzilla/show_bug.cgi?id=54101 +.. _`FastCgiExternalServer`: http://www.fastcgi.com/mod_fastcgi/docs/mod_fastcgi.html#FastCgiExternalServer .. _`Nginx`: http://wiki.nginx.org/Symfony diff --git a/cookbook/console/sending_emails.rst b/cookbook/console/sending_emails.rst index 09b92aca26d..dd2e021cf93 100644 --- a/cookbook/console/sending_emails.rst +++ b/cookbook/console/sending_emails.rst @@ -85,7 +85,7 @@ from the ``router`` service and override its settings:: Using Memory Spooling --------------------- -.. versionadded: 2.3 +.. versionadded:: 2.3 When using Symfony 2.3+ and SwiftmailerBundle 2.3.5+, the memory spool is now handled automatically in the CLI and the code below is not necessary anymore. diff --git a/cookbook/index.rst b/cookbook/index.rst index 7e39fbe9e02..1a088c672dd 100644 --- a/cookbook/index.rst +++ b/cookbook/index.rst @@ -29,6 +29,7 @@ The Cookbook templating/index testing/index validation/index + web_server/index web_services/index workflow/index diff --git a/cookbook/logging/monolog_email.rst b/cookbook/logging/monolog_email.rst index 0446c11598e..e6112fe9b1e 100644 --- a/cookbook/logging/monolog_email.rst +++ b/cookbook/logging/monolog_email.rst @@ -29,7 +29,7 @@ it is broken down. from_email: error@example.com to_email: error@example.com # or list of recipients - # to_email: [developer_1@example.com, developer_2@example.com, ...] + # to_email: [dev1@example.com, dev2@example.com, ...] subject: An Error Occurred! level: debug @@ -82,6 +82,8 @@ it is broken down. 'type' => 'swift_mailer', 'from_email' => 'error@example.com', 'to_email' => 'error@example.com', + // or a list of recipients + // 'to_email' => array('dev1@example.com', 'dev2@example.com', ...), 'subject' => 'An Error Occurred!', 'level' => 'debug', ), diff --git a/cookbook/map.rst.inc b/cookbook/map.rst.inc index 8eed3af02fd..d73382b762c 100644 --- a/cookbook/map.rst.inc +++ b/cookbook/map.rst.inc @@ -202,6 +202,11 @@ * :doc:`/cookbook/validation/custom_constraint` +* :doc:`/cookbook/web_server/index` + + * :doc:`/cookbook/web_server/built_in` + * (configuration) :doc:`/cookbook/configuration/web_server_configuration` + * :doc:`/cookbook/web_services/index` * :doc:`/cookbook/web_services/php_soap_extension` diff --git a/cookbook/security/target_path.rst b/cookbook/security/target_path.rst index 4c9db2541bc..6f7a0536da1 100644 --- a/cookbook/security/target_path.rst +++ b/cookbook/security/target_path.rst @@ -10,9 +10,9 @@ the name of the firewall, defined in ``security.yml``). Upon a successful login, the user is redirected to this path, as to help them continue from the last known page they visited. -On some occasions, this is unexpected. For example when the last request -URI was an HTTP POST against a route which is configured to allow only a POST -method, the user is redirected to this route only to get a 404 error. +In some situations, this is not ideal. For example, when the last request +URI was an XMLHttpRequest which returned a non-HTML or partial HTML response, +the user is redirected back to a page which the browser cannot render. To get around this behavior, you would simply need to extend the ``ExceptionListener`` class and override the default method named ``setTargetPath()``. @@ -56,9 +56,10 @@ Next, create your own ``ExceptionListener``:: { protected function setTargetPath(Request $request) { - // Do not save target path for XHR and non-GET requests + // Do not save target path for XHR requests // You can add any more logic here you want - if ($request->isXmlHttpRequest() || 'GET' !== $request->getMethod()) { + // Note that non-GET requests are already ignored + if ($request->isXmlHttpRequest()) { return; } diff --git a/cookbook/security/voters_data_permission.rst b/cookbook/security/voters_data_permission.rst index 82bea0fe9fe..0c5b134937c 100644 --- a/cookbook/security/voters_data_permission.rst +++ b/cookbook/security/voters_data_permission.rst @@ -61,7 +61,6 @@ edit a particular object. Here's an example implementation: // src/Acme/DemoBundle/Security/Authorization/Voter/PostVoter.php namespace Acme\DemoBundle\Security\Authorization\Voter; - use Symfony\Component\Security\Core\Exception\InvalidArgumentException; use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\User\UserInterface; @@ -100,7 +99,7 @@ edit a particular object. Here's an example implementation: // this isn't a requirement, it's just one easy way for you to // design your voter if(1 !== count($attributes)) { - throw new InvalidArgumentException( + throw new \InvalidArgumentException( 'Only one attribute is allowed for VIEW or EDIT' ); } @@ -108,21 +107,21 @@ edit a particular object. Here's an example implementation: // set the attribute to check against $attribute = $attributes[0]; - // get current logged in user - $user = $token->getUser(); - // check if the given attribute is covered by this voter if (!$this->supportsAttribute($attribute)) { return VoterInterface::ACCESS_ABSTAIN; } + // get current logged in user + $user = $token->getUser(); + // make sure there is a user object (i.e. that the user is logged in) if (!$user instanceof UserInterface) { return VoterInterface::ACCESS_DENIED; } switch($attribute) { - case 'view': + case self::VIEW: // the data object could have for example a method isPrivate() // which checks the Boolean attribute $private if (!$post->isPrivate()) { @@ -130,7 +129,7 @@ edit a particular object. Here's an example implementation: } break; - case 'edit': + case self::EDIT: // we assume that our data object has a method getOwner() to // get the current owner user entity for this data object if ($user->getId() === $post->getOwner()->getId()) { @@ -138,6 +137,8 @@ edit a particular object. Here's an example implementation: } break; } + + return VoterInterface::ACCESS_DENIED; } } diff --git a/cookbook/web_server/built_in.rst b/cookbook/web_server/built_in.rst new file mode 100644 index 00000000000..f7ef8d1f039 --- /dev/null +++ b/cookbook/web_server/built_in.rst @@ -0,0 +1,60 @@ +.. index:: + single: Web Server; Built-in Web Server + +How to Use PHP's built-in Web Server +==================================== + +Since PHP 5.4 the CLI SAPI comes with a `built-in web server`_. It can be used +to run your PHP applications locally during development, for testing or for +application demonstrations. This way, you don't have to bother configuring +a full-featured web server such as +:doc:`Apache or Nginx `. + +.. caution:: + + The built-in web server is meant to be run in a controlled environment. + It is not designed to be used on public networks. + +Starting the Web Server +----------------------- + +Running a Symfony application using PHP's built-in web server is as easy as +executing the ``server:run`` command: + +.. code-block:: bash + + $ php app/console server:run + +This starts a server at ``localhost:8000`` that executes your Symfony application. +The command will wait and will respond to incoming HTTP requests until you +terminate it (this is usually done by pressing Ctrl and C). + +By default, the web server listens on port 8000 on the loopback device. You +can change the socket passing an ip address and a port as a command-line argument: + +.. code-block:: bash + + $ php app/console server:run 192.168.0.1:8080 + +Command Options +--------------- + +The built-in web server expects a "router" script (read about the "router" +script on `php.net`_) as an argument. Symfony already passes such a router +script when the command is executed in the ``prod`` or in the ``dev`` environment. +Use the ``--router`` option in any other environment or to use another router +script: + +.. code-block:: bash + + $ php app/console server:run --env=test --router=app/config/router_test.php + +If your application's document root differs from the standard directory layout, +you have to pass the correct location using the ``--docroot`` option: + +.. code-block:: bash + + $ php app/console server:run --docroot=public_html + +.. _`built-in web server`: http://www.php.net/manual/en/features.commandline.webserver.php +.. _`php.net`: http://php.net/manual/en/features.commandline.webserver.php#example-401 diff --git a/cookbook/web_server/index.rst b/cookbook/web_server/index.rst new file mode 100644 index 00000000000..4b956308fc0 --- /dev/null +++ b/cookbook/web_server/index.rst @@ -0,0 +1,7 @@ +Web Server +========== + +.. toctree:: + :maxdepth: 2 + + built_in diff --git a/quick_tour/the_big_picture.rst b/quick_tour/the_big_picture.rst index 08bc43c77b8..7ecba9e88dd 100644 --- a/quick_tour/the_big_picture.rst +++ b/quick_tour/the_big_picture.rst @@ -73,6 +73,10 @@ to run Symfony: $ php app/console server:run +.. seealso:: + + Read more about the internal server :doc:`in the cookbook `. + If you get the error `There are no commands defined in the "server" namespace.`, then you are probably using PHP 5.3. That's ok! But the built-in web server is only available for PHP 5.4.0 or higher. If you have an older version of PHP or diff --git a/reference/configuration/framework.rst b/reference/configuration/framework.rst index 35d9279c598..1353b62452d 100644 --- a/reference/configuration/framework.rst +++ b/reference/configuration/framework.rst @@ -430,7 +430,7 @@ would be ``/images/logo.png?version=5``. URL rewrite rules could then be used to disregard the version prefix before serving the asset. Alternatively, you could copy assets to the appropriate - version path as part of your deployment process and forgo any URL rewriting. + version path as part of your deployment process and forgot any URL rewriting. The latter option is useful if you would like older asset versions to remain accessible at their original URL.