问题
I am reading the documentation for Phalcon attempting to find a method of utilizing the Assets Manager to add CSS or JS files to every single page by default. I have been unsuccessful in finding any method of doing this.
Adding an asset for an entire controller is easily accomplished by doing:
public function initialize() {
$this->assets->addCss('css/global.css');
}
- Is there some way I could add an asset to all controllers by default?
The idea of overwritting the base controller class and then having my controllers extend that instead comes to mind, but that sounds a little sloppy and I would like to avoid that if possible.
Thanks, appreciate the help.
回答1:
So far doing it in the base controller seems to be the best way, though I agree that it does smell a bit sloppy. While it feels that assets like css and js as supposed to be part of the view authority and shouldn't be touched from elsewhere, in real life this is not true. First of all, you configure your views from controllers, you specify what parameters go in there, and you specify individual view-specific assets, etc. There is no reason why you shouldn't provide the global.css
with it in the base controller.
The only thing that I find really sloppy is that there is a independent view and there is an independent asset manager, which in reality must be coupled together and assets you set on particular view must relate to that view only. There are cases when you want to render a view independently of everything else and use it's own assets from the default view, for example render the welcome email template after the registration. With the current implementation this can be achieved only by overwriting a fair amount of logic.
Alternatively you can attach that style directly in your template if you are not minifying them into a single file. You can also try adding an asset directly in your view with assets.addCss('css/global.css')
– this might not work right away if volt does this via helper functions in which case you should implement your own first. This, however, implies adding logic to a view which is never a good thing unless you can't live without it. So, stick with the base controller approach.
Edit: ironically, a day later I discovered a problem with doing this via initialize()
event handler after using it for over a year.
When you forward from one controller to another, the controller where you forwarded also gets initialised. This means that the same asset gets added twice, and if they get concatenated into a single file god knows what's going to happen… This is less of a problem for css (only increased size), but JS is very likely to break, often without any indication. This gets easily fixed with using afterExecuteRoute()
handler in controller with a dispatcher state check:
public function afterExecuteRoute()
{
// If dispatcher hasn't finished dispatching we shouldn't enter.
if (!$this->dispatcher->isFinished()) {
return;
}
$this->assets->addCss('css/global.css');
}
In your inheriting view just override this with this:
public function afterExecuteRoute()
{
parent::afterExecuteRoute();
if (!$this->dispatcher->isFinished()) {
return;
}
$this->assets->addCss('css/custom.css');
}
回答2:
You can also manipulate the assets manager in the DI.
$di->setShared("assets", function() {
$assetManager = new \Phalcon\Assets\Manager();
$assetManager->addJs('/path/to/some/js/file');
return $assetManager;
});
This will make sure the js files are always loaded. You can pass it a configuration to make it dynamic. Just register this somewhere in your index.php before running $app->handle()->getContent();.
来源:https://stackoverflow.com/questions/25841310/is-there-some-way-to-add-an-asset-to-every-single-page-in-phalcon