Docs for exec pipeline and manifests

- Added manifest logic docs
- More obvious pointers to flushing
- Removed Director page since it duplicated a lot of information already presenting in routing,
which in itself is already duplicated between routing.md and controllers.md.
- Merged Director execution rundown into main exec pipeline docs
- Moved YAML security note from main installation docs to "secure coding", making it less obvious
This commit is contained in:
Ingo Schommer 2014-11-15 16:01:47 +13:00 committed by Cam Findlay
parent e743fedc65
commit 11c1563778
7 changed files with 212 additions and 200 deletions

View File

@ -1,45 +1,27 @@
# Installation
These instructions show you how to install SilverStripe on any web server.
The best way to install from the source code is to use [Composer](composer).
For additional information about installing SilverStripe on specific operation systems, refer to:
* [Installation on a Windows Server](windows-pi)
* [Installation on OSX](mac-osx)
Check out our operating system specific guides for [Linux](linux_unix),
[Windows Server](windows-pi) and [Mac OSX](mac-osx).
## Installation Steps
* [Download](http://silverstripe.org/download) the installer package
* Make sure the webserver has MySQL and PHP support. See [Server Requirements](server-requirements) for more
information.
* Make sure the webserver has MySQL and PHP support. See [Server Requirements](server-requirements) for more information.
* Unpack the installer somewhere into your web-root. Usually the www folder or similar. Most downloads from SilverStripe
are compressed tarballs. To extract these files you can either do them natively (Unix) or with 7-Zip (Windows)
* Visit your sites Domain or IP Address in your web browser.
* Visit your sites domain or IP address in your web browser.
* You will be presented with a form where you enter your MySQL login details and are asked to give your site a 'project
name' and the default login details. Follow the questions and select the *install* button at the bottom of the page.
* After a couple of minutes, your site will be set up. Visit your site and enjoy!
## Issues?
If the above steps don't work for any reason have a read of the [Common Problems](common-problems) section.
## Security notes
### Yaml
For the reasons explained in [security](/topics/security), Yaml files are blocked by default by the .htaccess file
provided by the SilverStripe installer module.
To allow serving yaml files from a specific directory, add code like this to an .htaccess file in that directory
<Files *.yml>
Order allow,deny
Allow from all
</Files>
<div class="notice" markdown="1">
SilverStripe ships with default rewriting rules specific to your web server. Apart from
routing requests to the framework, they also prevent access to sensitive files in the webroot,
for example YAML configuration files. Please refer to the [security](/topics/security) documentation for details.
</div>

View File

@ -78,11 +78,13 @@ Example Forum Documentation:
|`forum/docs/en/04_Some_Topic/00_Getting_Started.md`|Structure is created by use of numbered prefixes. This applies to nested folders and documentations pages, index.md should not have a prefix.|
## PHP Include Paths
## Autoloading
Due to the way `[api:ManifestBuilder]` recursively detects php-files and includes them through PHP5's
*__autoload()*-feature, you don't need to worry about include paths. Feel free to structure your php-code into
subdirectories inside the *code*-directory.
SilverStripe recursively detects classes in PHP files by building up a manifest used for autoloading,
as well as respecting Composer's built-in autoloading for libraries. This means
in most cases, you don't need to worry about include paths or `require()` calls
in your own code - after adding a new class, simply regenerate the manifest
by using a `flush=1` query parameter. See the ["Manifests" documentation](/developer_guides/execution_pipeline/manifests) for details.
## Best Practices

View File

@ -160,7 +160,9 @@ This is useful when you want to provide custom actions for the mapping of `teams
The syntax for the `$url_handlers` array users the same pattern matches as the `YAML` configuration rules.
## API Documentation
## Links
* [api:Controller]
* [api:Director]
* [api:Controller] API documentation
* [api:Director] API documentation
* [Example routes: framework](https://github.com/silverstripe/silverstripe-framework/blob/master/_config/routes.yml)
* [Example routes: cms](https://github.com/silverstripe/silverstripe-cms/blob/master/_config/routes.yml)

View File

@ -1,87 +0,0 @@
# Director
## Introduction
`[api:Director]` is the first step in the "execution pipeline". It parses the
URL, matching it to one of a number of patterns, and determines the controller,
action and any argument to be used. It then runs the controller, which will
finally run the viewer and/or perform processing steps.
## Request processing
The `[api:Director]` is the entry point in Silverstring Framework for processing
a request. You can read through the execution steps in `[api:Director]``::direct()`,
but in short
* File uploads are first analysed to remove potentially harmful uploads (this
will likely change!)
* The `[api:SS_HTTPRequest]` object is created
* The session object is created
* The `[api:Injector]` is first referenced, and asks the registered `[api:RequestProcessor]`
to pre-process the request object. This allows for analysis of the current
request, and allow filtering of parameters etc before any of the core of the
application executes.
* The request is handled and response checked
* The `[api:RequestProcessor]` is called to post-process the request to allow
further filtering before content is sent to the end user
* The response is output
The framework provides the ability to hook into the request both before and
after it is handled to allow developers to bind in their own custom pre- or
post- request logic; see the `[api:RequestFilter]` to see how this can be used
to authenticate the request before the request is handled.
## Routing
You can influence the way URLs are resolved in the following ways
1. Adding rules to `[api:Director]` in `<yourproject>/_config/routes.yml`
2. Adding rules to `[api:Director]` in `<yourproject>/_config.php (deprecated)
3. Adding rules in your extended `[api:Controller]` class via the *$url_handlers*
static variable
See [controller](/topics/controller) for examples and explanations on how the
rules get processed for those methods.
### Routing Rules
SilverStripe comes with certain rules which map a URI to a `[api:Controller]`
class (e.g. *dev/* -> DevelopmentAdmin). These routes are either stored in
a routes.yml configuration file located a `_config` directory or inside a
`_config.php` file (deprecated).
To add your own custom routes for your application create a routes.yml file
in `<yourproject>/_config/routes.yml` with the following format:
:::yaml
---
Name: customroutes
After: framework/routes#coreroutes
---
Director:
rules:
'subscriptions/$Action' : 'SubscriptionController'
The [Controller](/topics/controller) documentation has a wide range of examples
and explanations on how the rules get processed for those methods.
See:
* [framework/_config/routes.yml](https://github.com/silverstripe/silverstripe-framework/blob/master/_config/routes.yml)
* [cms/_config/routes.yml](https://github.com/silverstripe/silverstripe-cms/blob/master/_config/routes.yml)
## Best Practices
* Checking for an Ajax-Request: Use Director::is_ajax() instead of checking
for $_REQUEST['ajax'].
## Links
* See `[api:ModelAsController]` class for details on controller/model-coupling
* See [execution-pipeline](/reference/execution-pipeline) for custom routing
## API Documentation
`[api:Director]`

View File

@ -6,7 +6,6 @@ summary: Allows a class to define it's own flush functionality.
## Introduction
Allows a class to define it's own flush functionality, which is triggered when `flush=1` is requested in the URL.
`[api:FlushRequestFilter]` is run before a request is made, calling `flush()` statically on all
implementors of `[api:Flushable]`.

View File

@ -0,0 +1,83 @@
title: Manifests
summary: Manage caches of file path maps and other expensive information
# Manifests
## Purpose
Manifests help to cache information which is too expensive to generate on each request.
Some manifests generate maps, e.g. class names to filesystem locations.
Others store aggregate information like nested configuration graphs.
## Storage
By default, manifests are stored on the local filesystem through PHP's `serialize()` method.
Combined with PHP opcode caching this provides fast access.
In order to share manifests between servers, or centralise cache management,
other storage adapters are available. These can be configured by a `SS_MANIFESTCACHE` constant,
placed in your `_ss_environment.php`.
* `ManifestCache_File`: The default adapter using PHP's `serialize()`
* `ManifestCache_File_PHP`: Using `var_export()`, which is faster when a PHP opcode cache is installed
* `ManifestCache_APC`: Use PHP's [APC object cache](http://php.net/manual/en/book.apc.php)
You can write your own adapters by implementing the `ManifestCache` interface.
## Traversing the Filesystem
Since manifests usually extract their information from files in the webroot,
they require a powerful traversal tool: `[api:SS_FileFinder]`.
The class provides filtering abilities for files and folders, as well as
callbacks for recursive traversal. Each manifest has its own implementation,
for example `[api:ManifestFileFinder]`, adding more domain specific filtering
like including themes, or excluding testss.
## PHP Class Manifest
The `[api:ClassManifest]` builds a manifest of all classes, interfaces and some
additional items present in a directory, and caches it.
It finds the following information:
* Class and interface names and paths
* All direct and indirect descendants of a class
* All implementors of an interface
* All module configuration files
The gathered information can be accessed through `[api:SS_ClassLoader::instance()]`,
as well as `[api:ClassInfo]`. Some useful commands of the `ClassInfo` API:
* `ClassInfo::subclassesFor($class)`: Returns a list of classes that inherit from the given class
* `ClassInfo::ancestry($class)`: Returns the passed class name along with all its parent class names
* `ClassInfo::implementorsOf($interfaceName)`: Returns all classes implementing the passed in interface
In the absence of a generic module API, it is also the primary way to identify
which modules are installed, through `[api:ClassManifest::getModules()]`.
A module is defined as a toplevel folder in the webroot which contains
either a `_config.php` file, or a `_config/` folder. Modules can be specifically
excluded from manifests by creating a blank `_manifest_exclude` file in the module folder.
By default, the finder implementation will exclude any classes stored in files within
a `tests/` folder, unless tests are executed.
## Template Manifest
The `[api:SS_TemplateManifest]` class builds a manifest of all templates present in a directory,
in both modules and themes. Templates in `tests/` folders are automatically excluded.
The chapter on [template inheritance](../templates/template-inheritance) provides more details
on its operation.
## Config Manifest
The `[api:SS_ConfigManifest]` loads builds a manifest of configuration items,
for both PHP and YAML. It also takes care of ordering and merging configuration fragments.
The chapter on [configuration](/topics/configuration) has more details.
## Flushing
If a `?flush=1` query parameter is added to a URL, a call to `flush()` will be triggered
on any classes that implement the [Flushable](/reference/flushable) interface.
This enables developers to clear [manifest caches](manifests),
for example when adding new templates or PHP classes.
Note that you need to be in [dev mode](/getting_started/environment_management)
or logged-in as an administrator for flushing to take effect.

View File

@ -4,105 +4,136 @@ summary: An overview of the steps involved in delivering a SilverStripe web page
## Introduction
This page documents all the steps from an URL request to the delivered page.
In order to transform a HTTP request or a commandline exeuction into a response,
SilverStripe needs to boot its core and run through several stages of processing.
## .htaccess and RewriteRule
## Request Rewriting
Silverstripe uses **[mod_rewrite](http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html)** to deal with page requests.
So instead of having your normal everyday `index.php` file which tells all, you need to look elsewhere.
The first step in most environments is a rewrite of a request path into parameters passed to a PHP script.
This allows writing friendly URLs instead of linking directly to PHP files.
The implementation depends on your web server, we'll show you the most common one here:
Apache with [mod_rewrite](http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html).
Check our [installation guides](/getting_started/installation) on how other web servers like IIS or nginx handle rewriting.
The basic .htaccess file after installing SilverStripe looks like this:
The standard SilverStripe project ships with a `.htaccess` file in your webroot for this purpose.
By default, requests will be passed through for files existing on the filesystem.
Some access control is in place to deny access to potentially sensitive files in the webroot, such as YAML configuration files.
If no file can be directly matched, control is handed off to `framework/main.php`.
<file>
### SILVERSTRIPE START ###
# Deny access to templates (but allow from localhost)
<Files *.ss>
Order deny,allow
Deny from all
Allow from 127.0.0.1
Order deny,allow
Deny from all
Allow from 127.0.0.1
</Files>
# Deny access to IIS configuration
<Files web.config>
Order deny,allow
Deny from all
</Files>
# Deny access to YAML configuration files which might include sensitive information
<Files ~ "\.ya?ml$">
Order allow,deny
Deny from all
</Files>
# Route errors to static pages automatically generated by SilverStripe
ErrorDocument 404 /assets/error-404.html
ErrorDocument 500 /assets/error-500.html
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^vendor(/|$) - [F,L,NC]
RewriteRule silverstripe-cache(/|$) - [F,L,NC]
RewriteRule composer\.(json|lock) - [F,L,NC]
RewriteCond %{REQUEST_URI} ^(.*)$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* framework/main.php?url=%1 [QSA]
SetEnv HTTP_MOD_REWRITE On
RewriteEngine On
# Deny access to potentially sensitive files and folders
RewriteRule ^vendor(/|$) - [F,L,NC]
RewriteRule silverstripe-cache(/|$) - [F,L,NC]
RewriteRule composer\.(json|lock) - [F,L,NC]
# Process through SilverStripe if no file with the requested name exists.
# Pass through the original path as a query parameter, and retain the existing parameters.
RewriteCond %{REQUEST_URI} ^(.*)$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* framework/main.php?url=%1 [QSA]
# If requesting the main script directly, rewrite to the installer
RewriteCond %{REQUEST_URI} ^(.*)/framework/main.php$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . %1/install.php? [R,L]
</IfModule>
### SILVERSTRIPE END ###
</file>
The `<Files>` section denies direct access to the template files from anywhere but the server itself.
SilverStripe can also operate without this level of rewriting, in which case all dynamic requests go
through an `index.php` script in the webroot.
The `<IfModule>` section enables the rewriting engine. Requests will be rewritten if they meet the following
criteria:
<div class="notice" markdown="1">
Running SilverStripe without web server based rewriting is not recommended since it
can leave sensitive files exposed to public access (the `RewriteRule` conditions from above don't apply).
</div>
* URI doesn't end in .gif, .jpg, .png, .css, or .js
* The requested file doesn't exist on the filesystem
The rewriting engine then calls `framework/main.php` with the REQUEST_FILENAME (%1) as the `url` parameter and also appends the original
QUERY_STRING. **Example:** *"myblog/cakes?page=2"* is rewritten as *"framework/main.php?url=myblog/cakes&page=2"*.
## Boostrap
See the [mod_rewrite documentation](http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html) for more information on how
mod_rewrite works.
All requests go through `framework/main.php`, which sets up the execution environment:
* Tries to locate an `_ss_environment.php`
[configuration file](/getting_started/environment_management) in the webroot,
or the two levels above it (to allow sharing configuration between multiple webroots).
* Sets constants based on the filesystem structure (e.g. `BASE_URL`, `BASE_PATH` and `TEMP_FOLDER`)
* Normalizes the `url` parameter in preparation for handing it off to `Director`
* Connects to a database, based on information stored in the global `$databaseConfig` variable.
The configuration is either defined in your `_config.php`, or through `_ss_environment.php`
* Sets up [error handlers](../debugging/error_handling)
* Optionally continues a [session](../cookies_and_sessions/sessions) if the request already contains a session identifier
* Loads manifests for PHP classes, templates, as well as any [YAML configuration](../configuration).
* Optionally regenerates these manifests (if a ["flush" query parameter](flushable) is set)
* Executes all procedural configuration defined through `_config.php` in all discovered modules
* Loads the Composer PHP class autoloader
* Hands control over to `[api:Director]`
## main.php
While you usually don't need to modify the bootstrap on this level, some deeper customizations like
adding your own manifests or a performance-optimized routing might require it.
An example of this can be found in the ["staticpublisher" module](https://github.com/silverstripe-labs/silverstripe-staticpublisher/blob/master/main.php).
The modules instructs web servers to route through its own `main.php` to determine which requests can be cached
before handing control off to SilverStripe's own `main.php`.
All requests go through `main.php`, which sets up the environment and then hands control over to `Director`.
## Routing and Request Handling
## Director and URL patterns
The `main.php` script relies on `[api:Director]` to work out which [controller](../controllers) should handle this request. It parses the URL, matching it to one of a number of patterns,
and determines the controller, action and any argument to be used ([Routing](../controllers/routing)).
main.php relies on `[api:Director]` to work out which controller should handle this request. `[api:Director]` will instantiate that
controller object and then call `[api:Controller::run()]`.
* Creates a `[api:SS_HTTPRequest]` object containing all request and environment information
* The [session](../cookies_and_sessions/sessions) holds an abstraction of PHP session
* Instantiates a [controller](../Controllers) object
* The `[api:Injector]` is first referenced, and asks the registered
[RequestFilter](../controller/request_filters)
to pre-process the request object (see below)
* The `Controller` executes the actual business logic and populates an `[api:SS_HTTPResponse]`
* The `Controller` can optionally hand off control to further nested controllers
* The `Controller` optionally renders a response body through `SSViewer` [templates](../templates)
* The `[api:RequestProcessor]` is called to post-process the request to allow
further filtering before content is sent to the end user
* The response is output to the client
In general, the URL is build up as follows: `page/action/ID/otherID` - e.g. http://localhost/mypage/addToCart/12.
This will add an object with ID 12 to the cart.
## Request Preprocessing and Postprocessing
When you create a function, you can access the ID like this:
The framework provides the ability to hook into the request both before and
after it is handled to allow binding custom logic. This can be used
to transform or filter request data, instanciate helpers, execute global logic,
or even short-circuit execution (e.g. to enforce custom authentication schemes).
The ["Request Filters" documentation](../controller/request_filters) shows you how.
:::php
public function addToCart ($request) {
$param = $request->allParams();
echo "my ID = " . $param["ID"];
$obj = MyProduct::get()->byID($param["ID"]);
$obj->addNow();
}
## Controllers and actions
`[api:Controller]`s are the building blocks of your application.
**See:** The API documentation for `[api:Controller]`
You can access the following controller-method with /team/signup
:::php
class Team extends DataObject {}
class Team_Controller extends Controller {
private static $allowed_actions = array('signup');
public function signup($id, $otherId) {
return $this->renderWith('MyTemplate');
}
}
## SSViewer template rendering
See [templates](/reference/templates) for information on the SSViewer template system.
## Flush requests
If `?flush=1` is requested in the URL, e.g. http://mysite.com?flush=1, this will trigger a call to `flush()` on
any classes that implement the `Flushable` interface.
See [reference documentation on Flushable](/reference/flushable) for more details.
## Flushing Manifests
If a `?flush=1` query parameter is added to a URL, a call to `flush()` will be triggered
on any classes that implement the [Flushable](/reference/flushable) interface.
This enables developers to clear [manifest caches](manifests),
for example when adding new templates or PHP classes.
Note that you need to be in [dev mode](/getting_started/environment_management)
or logged-in as an administrator for flushing to take effect.
[CHILDREN]