diff --git a/CHANGELOG.md b/CHANGELOG.md index ae9c7c76..772d21b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,9 @@ Fifth release candidate. - [#233](https://github.com/zendframework/zend-expressive/pull/233) adds a documentation page detailing projects using and tutorials written on Expressive. +- [#238](https://github.com/zendframework/zend-expressive/pull/238) adds a + cookbook recipe detailing how to handle serving an Expressive application from + a subdirectory of your web root. ### Deprecated diff --git a/doc/book/cookbook/bookdown.json b/doc/book/cookbook/bookdown.json index f524d7ba..b0700370 100644 --- a/doc/book/cookbook/bookdown.json +++ b/doc/book/cookbook/bookdown.json @@ -5,6 +5,7 @@ {"Route-specific middleware pipelines": "route-specific-pipeline.md"}, {"Setting custom 404 page handling": "custom-404-page-handling.md"}, {"Registering custom view helpers when using zend-view": "using-custom-view-helpers.md"}, - {"Using zend-form view helpers": "using-zend-form-view-helpers.md"} + {"Using zend-form view helpers": "using-zend-form-view-helpers.md"}, + {"Using Expressive from a subdirectory": "using-a-base-path.md"} ] } diff --git a/doc/book/cookbook/using-a-base-path.md b/doc/book/cookbook/using-a-base-path.md new file mode 100644 index 00000000..890ca7c5 --- /dev/null +++ b/doc/book/cookbook/using-a-base-path.md @@ -0,0 +1,188 @@ +# How can I tell my application about a base path? + +In some environments, your application may be running in a subdirectory of your +web root. For example: + +``` +var/ +|- www/ +| |- wordpress/ +| |- expressive/ +| | |- public/ +| | | |- index.php +``` + +where `/var/www` is the web root, and your Expressive application is in the +`expressive/` subdirectory. How can you make your application work correctly in +this environment? + +## .htaccess in the application root. + +If you are using Apache, your first step is to add an `.htaccess` file to your +application root, with directives for rewriting to the `public/` directory: + +```ApacheConf +RewriteEngine On +RewriteRule (.*) ./public/$1 +``` + +> ### Using other web servers +> +> If you are using a web-server other than Apache, and know how to do a similar +> rewrite, we'd love to know! Please submit ideas/instructions to +> [our issue tracker](https://github.com/zendframework/zend-expressive/issues)! + +## Use middleware to rewrite the path + +The above step ensures that clients can hit the website. Now we need to ensure +that the application can route to middleware! + +To do this, we will add pre_routing pipeline middleware to intercept the +request, and rewrite the URL accordingly. + +At the time of writing, we have two suggestions: + +- [los/basepath](https://github.com/Lansoweb/basepath) provides the basic + mechanics of rewriting the URL, and has a stable release. +- [mtymek/blast-base-url](https://github.com/mtymek/blast-base-url) provides the + URL rewriting mechanics, as well as utilities for generating URIs that retain + the base path, but does not have a stable release yet. + +### los/basepath + +To use `los/basepath`, install it via Composer, copy the configuration files to +your application, and then edit the configuration. + +To install and copy the configuration: + +```bash +$ composer require los/basepath +$ cp vendor/los/basepath/config/los-basepath.global.php.dist config/autoload/los-basepath.global.php +``` + +We recommend copying the global configuration to a local configuration file as +well; this allows you to have the production settings in your global +configuration, and development settings in a local configuration (which is +excluded from git by default): + +```bash +$ cp config/autoload/los-basepath.global.php config/autoload/los-basepath.local.php +``` + +Then edit one or both, to change the `los_basepath` settings: + +```php +return [ + 'los_basepath' => '', + /* ... */ +]; +``` + +The base path should be the portion of the web root leading up to the +`index.php` of your application. In the above example, this would be +`/expressive`. + +### mtymek/blast-base-url + +To use `mtymek/blast-base-url`, install it via Composer, and register some +configuration. + +To install it: + +```bash +$ composer require "mtymek/blast-base-url:dev-master@dev" +``` + +To configure it, update the file `config/autoload/middleware-pipeline.global.php`, +with the following contents: + +```php +return [ + 'dependencies' => [ + 'factories' => [ + Blast\BaseUrl\BaseUrlMiddleware::class => Blast\BaseUrl\BaseUrlMiddlewareFactory::class, + /* ... */ + ], + /* ... */ + ], + 'middleware_pipeline' => [ + 'pre_routing' => [ + [ 'middleware' => [ Blast\BaseUrl\BaseUrlMiddleware::class ] ], + /* ... */ + ], + /* ... */ + ], +]; +``` + +At this point, the middleware will take care of the rewriting for you. No +configuration is necessary, as it does auto-detection of the base path based on +the request URI and the operating system path to the application. + +The primary advantage of `mtymek/blast-base-url` is in its additional features: + +- it provides an override of `Zend\Expressive\Helper\UrlHelper` that is aware of + the base path, allowing you to create route-based URLs relative to the base + path. +- it provides a new helper, `Blast\BaseUrl\BasePathHelper`, which allows you to + create URLs relative to the base path; this is particularly useful for assets. + +To enable these features, we'll add some configuration to +`config/autoload/dependencies.global.php` file: + +```php +return [ + 'dependencies' => [ + 'invokables' => [ + Blast\BaseUrl\BasePathHelper::class => Blast\BaseUrl\BasePathHelper::class, + /* ... */ + ], + 'factories' => [ + Blast\BaseUrl\UrlHelper::class => Blast\BaseUrl\UrlHelperFactory::class, + /* ... */ + ], + 'aliases' => [ + // alias default UrlHelper with Blast\BaseUrl alternative + Helper\UrlHelper::class => Blast\BaseUrl\UrlHelper::class, + /* ... */ + ], + ], +]; +``` + +Additionally, remove the following from the same file: + +```php + 'factories' => [ + // Remove the following line only: + Helper\UrlHelper::class => Helper\UrlHelperFactory::class, + /* ... */ + ], +``` + +Finally, if you're using zend-view, you can register a new "basePath" helper in +your `config/autoload/templates.global.php`: + +``` +return [ + /* ... */ + 'view_helpers' => [ + 'factories' => [ + 'basePath' => Blast\BaseUrl\BasePathViewHelperFactory::class, + /* ... */ + ], + /* ... */ + ], +]; +``` + +Usage of the `BasePath` helper is as follows: + +```php +// where $basePathHelper is an instance of Blast\BaseUrl\BasePathHelper +// as pulled from your container: +echo $basePathHelper('/icons/favicon.ico'); + +// or, from zend-view's PhpRenderer: +echo $this->basePath('/icons/favicon.ico'); +``` diff --git a/mkdocs.yml b/mkdocs.yml index 2cd36be3..5b0e81aa 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -13,7 +13,8 @@ pages: - { Helpers: [{ Introduction: helpers/intro.md }, { UrlHelper: helpers/url-helper.md }, { ServerUrlHelper: helpers/server-url-helper.md }] } - { Emitters: emitters.md } - { Examples: usage-examples.md } - - { Cookbook: [{ 'Prepending a common path to all routes': cookbook/common-prefix-for-routes.md }, { 'Route-specific middleware pipelines': cookbook/route-specific-pipeline.md }, { 'Setting custom 404 page handling': cookbook/custom-404-page-handling.md }, { 'Registering custom view helpers when using zend-view': cookbook/using-custom-view-helpers.md }, { 'Using zend-form view helpers': cookbook/using-zend-form-view-helpers.md }] } + - { Cookbook: [{ 'Prepending a common path to all routes': cookbook/common-prefix-for-routes.md }, { 'Route-specific middleware pipelines': cookbook/route-specific-pipeline.md }, { 'Setting custom 404 page handling': cookbook/custom-404-page-handling.md }, { 'Registering custom view helpers when using zend-view': cookbook/using-custom-view-helpers.md }, { 'Using zend-form view helpers': cookbook/using-zend-form-view-helpers.md }, { 'Using Expressive from a subdirectory': cookbook/using-a-base-path.md }] } + - { 'Expressive Projects': expressive-projects.md } site_name: zend-expressive site_description: 'zend-expressive: PSR-7 Middleware Microframework' repo_url: 'https://github.com/zendframework/zend-expressive'