What's the point of Yii's AssetManager? - php

I can't find much information about Yii's AssetManager for the management of JS and CSS files. My question here is what is the point of using the AssetManager? I'm not sure what value it adds to my development process, in fact, it seems like it complicates my code... every time I change my scripts or css code, I have to go in and delete my assets folder to make sure I have the latest versions.
Seems it is much simpler to just put all Javascript files under /webroot/js/ and just use the tags to load the files instead of going through the trouble of AssetManager. Plus, Yii's registerCoreScript function always places script tags inside the header tag, instead of placing them at the bottom of the code, near the closing body tag, as recommended by YSlow.
I think there must be a gap in my understanding of Yii's AssetManager. Anybody have any ideas why using the AssetManager is better than hard-coding the script tags inside the PHP code? I'm a bit confused...
Thanks!

I'm sure someone can answer this better than myself, but basically it's so that your source JS and CSS files can remain in your Protected folder.
This is a little more secure for one thing, but the main benefit to me is that you can compress and minify and otherwise process your assets with the asset publishing system, and it makes it easier to host your JS and CSS on a CDN since it's separate from your codebase.
Also, here's an official response from qiang (the guy who wrote Yii) about this.

The main benefit of Yii's asset manager is that it allows you to structure your components in a self-contained manner.
A tale of a widget
Consider a component that is a UI widget. Let's assume the distribution includes a couple of assets along with the component implementation, for example these files:
SuperWidget.php
superwidget.css
superwidget.js
image_for_css.png
Consider how you would incorporate this widget into your application if the asset manager did not exist. Typical steps might include:
Copy SuperWidget.php somewhere inside the protected/ directory
Copy superwidget.js to your js/ directory
Copy superwidget.css to your css/ directory
Copy image_for_css.png to your images/ directory or perhaps also inside css/ to help reduce the relative path dependencies
Then at runtime SuperWidget would emit appropriate tags to include the CSS and JavaScript; to do this, it would need to know where exactly you have placed these assets. In other words: some choices regarding the installation can be made arbitrarily, but then they are set in stone unless you go and edit the source.
Is the widget reusable?
If this widget were highly customized and meant to be an inseparable part of your application then this approach would work fine and there wouldn't be much need to have an asset manager. But what if it's a broadly useful component that you want to distribute?
Problems start arising.
First of all the deployment scheme we have examined requires users of the widget to copy different files into different directories, complicating the installation procedure and increasing the chance of error.
But the greater issue is that your deployment scheme could conflict with that of any other component developed independently of yours. What if someone else decided to have a superwidget.js file too?
If the installation instructions for these two components conflict then obviously one of them cannot be installed as intended, and then you resort to changing some details and hacking the source code of the component to accommodate these changes. If you later upgrade to a newer version of that component you will be forced to carefully account for your customizations, making a "copy/overwrite" upgrade impossible.
All of this is really not pretty, and while it can be unlikely to happen in practice it certainly doesn't feel right.
Asset manager, make it so
Here's where the asset manager comes in. Let's assume you decide to structure your component like this:
superwidget/
SuperWidget.php
assets/
css/
superwidget.css
js/
superwidget.js
images/
image_for_css.png
You can directly copy this somewhere inside your protected/ directory no matter what other components you have installed; the worst thing that could happen here is that you'd have to rename superwidget/ to something else if there was a conflict.
Using the asset manager, SuperWidget.php publishes the whole superwidget/assets/ directory, with the copy ending up at e.g. assets/1337c0de/ where assets/ is your application's base asset path and 1337c0de/ is a random hash created by Yii and guaranteed to not conflict with any other published asset.
This means that the assets for SuperWidget cannot possibly conflict with those of any other component, making SuperWidget truly reusable. And since the directory structure inside 1337c0de/ will be the same as in your distribution, CSS can refer to images using the relative path ../images/ without needing to refer to the value of the random hash (which is only know after publishing).
What the asset manager is not
It's not a way to increase security. Your component source would be somewhere inside protected/ anyway (so no improvement there), and the assets need to be web-accessible no matter where they end up being copied (no security for them no matter what).
It's not a catch-all solution for processing your assets (e.g. minifying CSS). While it is possible to install a custom asset manager that does this, don't forget that assets included with reusable components will a small minority among all of your "base application" assets; if you want minification across the board, you 'll have to also process everything else and the asset manager will not help you there.
TL;DR
The asset manager allows you make components that are easily distributable and can be included in applications without the fear of creating conflicts with other components.

Another perk that I like about the asset manager, is that it allows you to update your asset files without having to tell your users to clear their cache.
http://www.yiiframework.com/wiki/311/assetmanager-clearing-browser-s-cache-on-site-update/

Related

Folder structure for modular development with PHP and vuejs (or angular)

Essentially, I'm looking to have a PHP development workflow that needs to be modular, but using a Single Page Application technology.
I understand it is recommended to separate the back-end from the front-end. Develop them separately. But is there a way to group all related code into one module (or folder), meaning all backend code with its own views presentation inside the same folder?
It's like MVC, but the "V" contains fragments of vuejs (or angular) files, which extends from a master file somewhere in your project.
For example
Assume we are building a modular CMS, where you can upload "plugins" (really, PHP modules), extending the CMS' functionality:
-project[root-folder]
----core[folder] # contains all infrastracture code, api routes, master view file, magic, etc.
----modules[folder] # uploadable modules goes here
--------User[folder] # sample module; follows the MVC pattern
------------Controllers[folder] # contains files, e.g. UserController.php
------------Models[folder] # contains User.php
------------views[folder] # where vue components is housed
----------------users/index.php # contains vue code
----------------users/create.php # etc...
----------------users/js/user.js
----------------users/css/user.css
--------Blog[folder] # another module
----index.php # the master view or just the bootstrap file
----gulpfile.js
Then inside the core/ folder, there is a master layout that binds all views together.
Will a folder structure like this be viable?
Obvious problem there is you can't use .vue files (as that would mean, every time you upload a new module, you need to run gulp or re-compile).
Hoping for your feedback. Thanks.
This question will strike a lot of folk as bizarre and twisted. That's the reaction I got when I asked it in the context of .net mvc. I'm with you 100%.
I'm too new to js frontend development (and too ignorant of PHP) to have much advice. It's going to be tricky. Ajax calls to PHP code will need to go to paths below the src directory. But then you want to stop your frontend resources being served from these same paths. Both PHP and gulp will want to use file paths for urls, but at least for Gulp this can be controlled.
I'll follow this with interest. My ambition is to keep in the same folder things you're likely to want to delete together, and for those things to be able to call each other with short, relative paths. The ideal would be to be able to specify the module route independently of the path on disk, and to have this route work for both frontend bundled resources and services. Good luck !
I came across this question whilst searching for an approach for exactly the same problem. I'm building a "platform" rather than an application with a plugin system along the lines of Wordpress. I have the additional issue of the platform itself being a 'multitenancy' environment, too - so any plugins cannot interfere with the core "Dashboard" that holds these things together.
So; posting for a few reasons, two years on...
Did you get anywhere and would you care to share any thoughts?
I came across a quite extensive article for PHP Phalcon that has certainly given me a few ideas. Sharing incase it helps you/others:
https://blog.antsand.com/singlepost/index/5619/How-to-integrate-php-(Phalcon)-and-Vue.js-components
There's a line buried in the series that says "As a rule of thumb. Structure your code, based on the application and NOT on the programming language and frameworks." I'm not sure how wise or not this is, but it certainly gave me something to crack on with.
So right now, I have a module folder a bit like:
/mymodule
/Controller
/Model/
/Template
thing.vue
/Assets
/js
/css
MyModule.php
Assets are handled via a framework route (i.e, /assets/{path:.*} )
Templates are handled via the (PHP) module install script to make sure webpack knows where they live.
Still at proof-of-concept stage but rightly or wrongly, it seems to work well enough!

Codeigniter3: What are the core directories required?

I wish to use codeigniter NOT as a framework for building a site, but simply as a backend to handle some php stuff (eg. db in/out, image manipulation, file writing to the server).
In the default download of CodeIgniter3, there are 3 primary directories (application, system, and user_guide). Most of application is roughly empty, other than application/config; and user_guide is surely unnecessary.
So what parts of CodeIgniter3 are needed such that it is functionally complete?
TL;DR: All of it
If you want to use just a set of a framework's components, CodeIgniter is not the right pick.
Long answer:
In theory: it should be just system/core/
But most of that code assumes that you have constants defined in index.php, that you do have an "application" directory (containing "config/" and "views/errors/" subdirectories).
A lot of it also depends on language translations, for which the defaults are in system/language/, so you need that too.
Some badly written parts may also depend on a particular system/libraries/ or system/helpers/ component.
So while we started with just system/core/, you now need all of system/ and at least some of application/ (though that can be renamed to something else).
CodeIgniter has a monolithic architecture; it is simply not built in a way to allow you to do what you're asking for.
And those are only a few kylobytes of files anyway - it's not 1980 and that's not a problem; unless you actually load the extra components that you don't use, they wouldn't get in the way.

Directory structure in MVC PHP Frameworks

At this moment, my framework's directory structure looks like this:
framework/
libraries/
autoload/
autoload.class.php
resource.namespaces.php
router/
tests/
router.test.php
router.class.php
resource.routes.php
configuration/
framework.configuration.php
router.configuration.php
controllers/
index.controller.php
models/
index.model.php
views/
default/
index/
index.view.php
header.view.php
footer.view.php
assets/
css/
javascript/
images/
index.php
When my framework was smaller, it was a lot cleaner. I have give a look at other popular frameworks. They have two main folders:
framework/
app/
web/
Actually, this structure is very clean and nice because we separate the front-end and the back-end. But I wonder what should I put in each of these.
Logically, libraries folder should be inside the app folder, but it is not really a part of the application. For me, an application has models, controller and views. I think libraries should be put outside. Where should I put my libraries?
I has a lot of PHPUnit tests in my libraries. Should I add a folder named tests inside each library, or should I put it inside/outside the app folder?
If I want to implement a template feature, where I could choose which template I want to use for my website, how could I organise it? Every template has differents elements, so header.view.php will not be the same, etc. Now, I'm creating a folder in views which is the template folder. But I think it is a bad idea, 'cause now, for every template I must recreate all the views.
In a lot of applications, there is a vendor folder that contains all the main classes. Is this the same as my libraries folder? Does it have the same role?
I also have some 'resources' files (eg.: resources.routes.php). They are used to add some routes/namespaces. It's a bit like a configuration file. Should I create another direcotry for these files, or put them inside the class which they refers to?
I'll try to cover all your questions.
The vendors folder that you see in many apps is from composer. In that folder are all the dependencies of your application/framework (often libraries from other people).
Composer allows you to pull in some good components for your framework so that you don't have to write everything from scratch. Say for example I want to use FastRoute because it is much better than any router I am capable of writing myself. So I just add the following to my composer.json, run composer update and I can use it in my framework.
{
"require": {
"nikic/fast-route": "dev-master"
}
}
You can also use composer to autoload your classes so that you don't have to write your own autoloader (and cache that for production).
I really dislike your current file names. adding .class to a filename makes absolutely no sense to me. The dots also just complicate Autoloading. I recommend you have a look at PSR-0 for some inspiration on how to handle file names/namespaces (This is supported by the composer autoloader).
For the tests you could create a Tests folder in the root folder of your project and in there recreate the directory structure of your project and add the test classes in the matching folders. You can also put your mock objects in there. This makes it easy to just run tests for a certain part of your application.
I also recommend that you move your application out of your public folder and instead have a public folder with only an index.php and your assets. That index.php does nothing other than requiring your front controller that bootstraps your app. Doing it that way adds another layer of security if for some reason your webserver stops processing PHP. Otherwise a visitor would be able to see your whole source code.
To get some inspiration for your folder structure questions, I recommend that you have a look at how other people solved this issue. Arya and PitchBlade would be a good starting point because they are way smaller than a framework like symfony.
I hope this helps. In the future I recommend that you split up your questions into different SO questions, that makes answering easier and you will get better answers because people who know the answer to one of your questions don't also have to answer all of them.

Automatic re-compilation with asset management tools

I have been looking into incorporating an asset management/pipelining tool (probably Assetic) into my PHP project.
Since assets can be grouped into collections or wildcard-based paths using such tools, if I wanted to set up a watch process that re-compiled/minified only those source files that had changed, how would I do that given that assets have to be looked up by name (see example below)?
(I noticed that for Symfony there's a watch task for Assetic but I'm not sure that it re-compiles only the changed file(s) and also I would have to make it work outside of Symfony since my app uses the CodeIgniter framework.)
In Assetic, you can create a wildcard-based asset, e.g.:
new GlobAsset('/path/to/compass-sources/*')
You can tell it to send the assets through a filter (Compass in this example) and then output the result (CSS) to a folder like public/css.
Let's say I set up the watch process using node.js's fs.watch so that I can theoretically tell Assetic to re-compile a particular asset whenever one of its source files changes.
Since my node.js script would only know the name of the actual file that changed (e.g. compass-sources/layout.scss), how could I look up which AssetCollection or GlobAsset that particular file belonged to (say an asset called global-styles) in order to recompile it?
I'm open to alternatives here. I looked at grunt and may very well use grunt-contrib-watch to handle the file watching, but I like the idea of using Assetic because the project is in PHP and I think that will be easier on future PHP developers working on the system who may not be familiar with node.js. It seems grunt take a different approach where assets don't necessarily go in named bundles. Mostly I want to understand the conceptual approach of named asset bundles (like in Assetic) as it relates to my goal of recompiling assets whenever the source files change.

Codeigniter Shared Resources - Opinions Wanted

I run multiple websites all running off of a single installation of CodeIgniter on my server (separate application directories and a single system directory). This has been working fabulously and I don't see any reason to change it at this point.
I find myself writing library classes to extend/override CI all of the time and many times if I find a bug or improve effeciency I have to go back to several websites to make the same adjustments at risk of a typo that breaks one of the websites. Because of this it requires that I change each file and then test that site for bugs.
I have been pondering a solution of using a single libraries directory in a central location and symlinking all of my websites to that central directory. Then when I make a file change it will immediately propagate to all of the downstream websites. It will still require that I test each one for errors, but I won't have to make the changes multiple times. Anything that is specific to a single website will either be a non-shared file (still in the linked directory just not used elsewhere) or can be put in a local helper.
Also, I keep separate 'system' directories by CI version so I can migrate my websites independently if necessary--this central libraries file would be attached to a specific version to reduce possible breaks.
Does anyone see potential issues or pitfalls from taking this approach? Has anyone accomplished this in another direction that I should consider?
Thanks in advance!
I think this actually makes sense :] Go for it. Even on official CodeIgniter page, they mention it's possible.
Also, I don't see one reason why there should be any problem.
Edit: they touch the problem of multiple sites here: http://codeigniter.com/user_guide/general/managing_apps.html
also:
http://codeigniter.com/wiki/Multiple_Applications/
http://www.exclusivetutorials.com/setting-multiple-websites-in-codeigniter-installation/
How to Handle Multiple Projects in CodeIgniter?
http://codeigniter.com/forums/viewthread/56436/
I have a single system directory and separate application directories for my CI apps. In order to share libraries and some view templates between my apps, I have created a "Common" directory, in the same folder as the CI system and with the same structure as a regular app folder and used symlinks, but you can modify the Loader class so that it looks in the Common folder too. My setup looks something like this:
/var/CodeIgniter/
/var/Common/
/var/Common/config/
/var/Common/controllers/
...
/var/Common/libraries/
...
/var/www/someapp/
/var/www/someotherapp/
...
I'm not sure how you handle publishing your sites (assuming you actually do any of that), but I'd look into version control. For example, in SVN you can make external to another svn directory (or file) and then just update the current svn directory which grabs the external file. This approach gains one benefit from the others, which is when you modify the common library, the others aren't immediately affected. This prevents unwanted breaks before you have time to go test all the sites using the common library. You can then just update each site's folder whenever you are ready to test the changes. This is "more work", but it prevents code duplication AND unwanted breaks.
I wrote a MY_Loader to do exactly that.
http://ellislab.com/forums/viewthread/136321/

Categories