* API Implement support for public/ webroot folder * Bugfixes and refactor based on feedback
7.3 KiB
4.1.0
Overview
- Support for public webroot folder
public/
- Better support for cross-platform filesystem path manipulation
Upgrading
Upgrade public/
folder
This release allows the maintenance of a public webroot folder which separates all web-accessible files from protected project files (like the vendor folder and all of your PHP files). This makes your web hosting more secure, and less likely to leak information through accidentally deployed files like a project README. New projects will default to this behaviour. Existing projects (updating from 3.x or 4.0) will continue working as-is, but we strongly recommend switching to the public webroot structure in order to get the security benefits.
This folder name is not configurable, but is turned on by creating this folder, and off by ensuring this folder doesn't exist.
When separating the public webroot from the BASE_PATH it is necessary to move a few files during migration:
- Move
.htaccess
from base topublic/
- Move
index.php
from base topublic/
- Move
assets
folder (including the nestedassets/.protected
folder) intopublic/
. This is the only folder which needs write permissions. - Ensure that the
public/resources
folder exists; If this folder already exists in root, you should delete this, and re-generate it by runningcomposer vendor-expose
in your root path. - Any public assets committed directly to your project intended to be served directly to the
webserver. E.g. move
mysite/javascript/script.js
topublic/javascript/script.js
. You can then useRequirements::css('javascript/script.js');
/<% require css('javascript/script.js') %>
to include this file. - Ensure that the web-root configured for your server of choice points to the public/ folder instead of the base path. E.g. an apache virtualhost configuration would look like:
<VirtualHost *:80>
ServerName mywebsite.com
ServerAlias *.mywebsite.com
VirtualDocumentRoot "/var/www/Sites/mywebsite/public/"
</VirtualHost>
You may also need to add various changes to your code if you reference the BASE_PATH directly:
- You should use
Director::publicFolder()
instead ofDirector::baseFolder()
if referring to the public folder. - You can check if a public folder exists with
Director::publicDir()
Example public/
folder structure
For example, this is an existing folder structure:
/var/www/mysite
├── assets/
│ └── .protected/
├── mysite/
│ ├── code/
│ │ ├── Page.php
│ │ └── PageController.php
│ └── css/
│ └── projectstyle.css
├── resources/ _(auto-generated by vendor-plugin `composer vendor-expose` command)_
│ └── silverstripe/
│ └── blog/
│ └── css/ _(symlink)_
│ └── blog.css
├── themes/
│ └── mytheme/
│ ├── css/
│ │ └── theme.css
│ └── templates/
│ └── BlogPage.ss
├── vendor/
│ └── silverstripe/
│ └── blog/
│ ├── css/ _(exposed in blog composer.json)_
│ │ └── blog.css
│ └── composer.json
├── .htaccess
├── composer.json
├── favicon.ico
├── index.php
└── install.php
After migration the folder structure would look like:
/var/www/mysite
├── mysite/
│ └── code/
│ ├── Page.php
│ └── PageController.php
├── public/
│ ├── assets/
│ │ └── .protected/
│ ├── css/
│ │ └── somestyle.css
│ ├── resources/ _(auto-generated by vendor-plugin `composer vendor-expose` command)_
│ │ ├── themes/
│ │ │ └── mytheme/
│ │ │ └── css/ _(symlink)_
│ │ │ └── theme.css
│ │ └── vendor/
│ │ └── silverstripe/
│ │ └── blog/
│ │ └── css/ _(symlink)_
│ │ └── blog.css
│ ├── .htaccess
│ ├── favicon.ico
│ ├── index.php
│ └── install.php
├── themes/
│ └── mytheme/
│ ├── css/ _(exposed in root composer.json)_
│ │ └── theme.css
│ └── templates/
│ └── BlogPage.ss
├── vendor/
│ └── silverstripe/
│ └── blog/
│ ├── css/ _(exposed in blog composer.json)_
│ │ └── blog.css
│ └── composer.json
└── composer.php
Use new $public
theme set
In addition there is a new helper pseudo-theme that you can configure to expose files in the public/
folder to the themed css / javascript file lookup. For instance, this is how you can prioritise those
files:
---
Name: mytheme
---
SilverStripe\View\SSViewer:
themes:
- '$public'
- 'simple'
- '$default'
This would allow <% require themedCSS('style.css') %>
to find a file comitted to public/css/style.css
.
Note that Requirements
calls will look in both the public
folder (first) and then the base path when
resolving css or javascript files. Any files that aren't in the public folder must be exposed using
the composer.json "expose" mechanism described below.
Expose root project files
If you have files comitted to source control outside of the public
folder, but you need them to be available
to the web server, you can also use the composer.json expose
directive to symlink / copy these to public/resources/
.
composer.json (in project root)
{
"extra": {
"expose": [
"mysite/client"
]
}
}
Then run the composer helper composer vendor-expose
in your project root. This will symlink (or copy)
the mysite/client
directory to public/resources/mysite/client
.
If you are using third party modules which may not have explicit expose
directives,
you can also expose those assets manually by declaring the full path to the directory to expose.
This works the same for silverstripe-module
and silverstripe-vendormodule
types.
{
"extra": {
"expose": [
"vendor/somevendor/somemodule/css",
"anothermodule/css"
]
}
}
For more information on how vendor modules work please see the documentation on the vendor plugin page or the publishing a module documentation.
Path manipulation helpers
The following filesystem helpers have been added in order to better support working with cross-platform path manipulation:
SilverStripe\Core\Convert::slashes()
to convert directory separators to either/
or\
SilverStripe\Core\Path::join()
which will join one or more relative or absolute paths.SilverStripe\Core\Path::normalise()
which will normalise and trim directory separators in a relative or absolute path
For example: normalising Convert::normalise('/some\\dir/')
will convert to /some/dir
.
Setting the second arg to true will also trim leading slashes.
E.g. Convert::normalise('/sub\\dir/', true)
will convert to sub/dir
.
It is preferrable to use these helpers in your code instead of assuming DIRECTORY_SEPARATOR
=== /