CakePHP: What should go in /Lib vs /Vendor vs /Plugin - php

I've been using CakePHP for a while and I still don't really understand what should go in /Lib vs /Plugin vs /Vendor. I know that plugins are basically mini apps with their own controllers, etc. But there are many situations when all three seem like ok options. Could someone shed some light on this?

Lib
Contains 1st party libraries that do not come from 3rd parties or
external vendors. This allows you to separate your organization’s
internal libraries from vendor libraries.
Plugin
Contains plugin packages.
Vendor
Any third-party classes or libraries should be placed here.
Doing so makes them easy to access using the App::import(‘vendor’,
‘name’) function. Keen observers will note that this seems redundant,
as there is also a vendors folder at the top level of our directory
structure. We’ll get into the differences between the two when we
discuss managing multiple applications and more complex system setups.
Source: http://book.cakephp.org/2.0/en/getting-started/cakephp-folder-structure.html
To clarify further, Libis recommended for libraries that you write yourself. This may just be a few classes or entire libraries. Vendor is recommended for libraries or scripts that you may download from github for instance. Plugin is strictly for cakephp framework plugins.
Regarding Lib vs Vendor for you own scripts or 3rd party scripts there is no difference that I am aware of. I have put my own scripts in both as well as 3rd party scripts in both locations and it hasn't made any difference. It's just a recommended way to organize your files.
You can load your scripts from Lib or Vendor using App::import() which is the same as require_once(). To load framework files or your own scripts that follow cakephp conventions, you would use App::uses(). This uses the paths defined using App::path() or App::build() to find the files.

Related

PHP, GIT, Location for reusable components

Thanks for your attention, this is a question of organization, I work with PHP and GIT for version control. I use Netbeans IDE to program, GIT integrated (although I am still a rookie).
Normally, I follow the approach that Symfony2 specifies for organize the project files, but I use my own framework for my projects.
The (main) question is: Any component or code part which has its own version control must be located under the /vendor/directory?
For example:
I have my project files in src\Acme\ProjectX\, also the utility package which use all my projects: src\Acme\Util\, and it is under the version control too (GIT).
and now let's remember the basic skeleton of a project based on Symfony or similar:
/app (application related elements)
/src (source code of the project)
/vendor (third party libraries)
/web (front end controller, the web directory, assets resources etc...)
So, Must be 'Acme\Util' included in the vendor directory? And, is necessary to use composer to declare the dependences?
In addition, the Utility package has a lot of classes but only few are used in projects. Must I remove those are not using by the project.
Summarizing, It will be nice if someone can contribute his knowledge for help me to represent an scenario like this.
I hope I could explained...
Thanks in advance!
Vendor directory
It's a good practice to separate external dependencies and the application code. If you are using Composer you can change it to something else.
Unused classes
Unused classes shouldn't matter if they aren't being loaded. They'll just take a bit of extra disc space.
It might be a good idea to separate the Utility package into multiple packages if you find yourself frequently using only a small part of it.
Dependency managers
It isn't necessary to use a dependency manager, but it sure does help. Having to install, configure and maintain everything manually (especially with many dependencies and sub-dependencies) would be a horror.

Publishing assets from modules in Zend Framework 2

It is generally adviced to store module assets inside the module's directory, inside moduleName/public (or whatever you want to name the asset's directory).
Zend Framework 2 unfortunately doesn't support asset publishing for module assets by default. According to MWOP, there was nothing planned ~1 month ago and I guess there still is no real plan (they had probably a lot of work to get the stable version ready). (But, some day, they are going to address this issue.)
As my ZF2 app is growing and growing, I reached the point where I need to have module-specific assets. At the moment, I maintain them inside the module directories and copy them to the application's public directory. You can imagine that this method is error-prone and exhausting.
How do you handle this problem? Is there maybe a simple solution to this issue with little coding effort? My project plan doesn't allow me to create a complex asset handling on my own. Is there a recommendable, lightweight asset framework compatible to ZF2? I've already considered creating symlinks but I don't think this would be the best solution because it would require some additional web server configuration (FollowSymlinks) and additional maintenance work (the app is developed locally and deployed on a remote server).
Thanks in advance.
This has been discussed before in many places and it comes down to three ways to manage this.
Copy and Paste the assets into the public/ directory
Use symlinks
Use an asset loading module like assetic
A simple solution would be to make the copying of assets part of you build process.
Another question was already asked How to merge Zend Framework 2 module public directories for info.
I know this is pretty old, but I wanted to add this information for other readers.
Now there's also a module for this, which has been fully tested and is being used (and even depended on) by many modules.
Check it out here: https://github.com/RWOverdijk/AssetManager
Hope this helps.
There is also fourth option. Use a directory Alias in VirtualHost configuration.

What is the correct way of adding CSS or JS libraries as dependencies with Composer in Symfony2?

In the Symfony 2 docs it's said:
A bundle should not embed third-party libraries written in JavaScript, CSS, or any other language.
Then how should I do that? I want to install Twitter Bootstrap, DataTables, and many other things as dependencies using Composer. But the only way I can think of is creating a bundle and embedding them.
What is the correct way to do this?
You should use Bower by Twitter. It is a package manager for HTML, CSS and Javascript. It was created to address this very issue you are having.
EDIT:
As of now, there are very good package managers for JS Libraries such as Bower, Jam or Component.
Versioning system
Semantic Versioning - Composer advises to use the semantic versioning system. It uses a X.Y.Z setting, in which X is the major version, Y is the minor version and Z is the patch version. Y and Z should always be backwards compatible while X reflects changes in code which MIGHT break backwards compatibility.
Embeding
Embeding should be read as copy and pasting the code (and binary) as part of your library, rather then requiring it as a third party (vendor) package/bundle. Its like including query.js in a resource folder or copying and pasting propel code to a folder inside your bundle.
Why not embed 3rd party libs
A bundle should not embed third-party libraries written in JavaScript, CSS, or any other language.
This statement comes from a best practice point of view. Embeding (as in copy/paste) third party libraries of any kind (PHP libs especially) is usually not a good idea. For instance, imagine that BUNDLE A uses LIBRARY FOO v1.4.1, and BUNDLE B also uses LIBRARY FOO but with a different version v1.5.2. If any of the BUNDLES (A or B) embeds FOO lib, they might (most probably will) become incompatible. For instance, php classes and functions cannot be redeclared. Any of the bundles can, of course, use workarounds to mitigate this problem, such as namespacing their version of FOO or autoloading rules, but this can rise other problems as well besides surely increasing memory usage as there are 2 versions of the same thing parsed by PHP.
If a PHP package does not follow this best practice, the errors that arise are usually easy to spot (with error: cannot redeclcare function blablabla). With Javascript Libraries, however, that is not true. You can redeclare functions (as they are object properties). So if now FOO is a JS Lib instead, and BUNDLE A and B embed them into their libraries, when they are included, strange problems can arise. For instance, a function can be redeclared that lacks a crucial functionality for one of the bundles and break it.
Symfony is a PHP framework.
It deals with PHP libraries/bundles. Symfony advises to require a library as dependency instead of embedding it since it uses Composer as a Package manager, which takes care of downloading and loading the require packages. As far as I remember, when 2 bundles/packages use the same library, if they have different version requirements, the most actual is used, unless its backwards incompatible. Composer then reports a conflict that you have to manually resolve.
However... There is no way to handle javascript libraries properly. That's because Composer is a package for PHP libraries. You can workaround this in two ways I can think of: (there are probably more and best ways to handle this, I just thought of these two, read them as suggestions)
Create a PHP wrapper around the javascript library and including it (although this potentially creates the same problem if another bundle decides to do the same thing but giving the package a different name)
Creating a bundle which requires the javascript library as a third party dependency through composer. Since the javascript library won't probably have a composer.json file in it's repository (sometimes they live as a standalone minified file), this can be accomplished by creating a custom composer installer, forking the javascript repository (in gitHub for instance) adding a composer.json to it, etc... However, you will need to constantly maintain and upgrade the said library, which can be troublesome.
You will have to keep in mind that:
JS and CSS libs have to be exposed publicly, so that the client can access it (security considerations)
Symfony is a PHP framework and deals with server-side packages. JS/CSS are client side. This as to be taken in consideration so it works properly.
One of the main ideas behind symfony (as with other PHP Frameworks) is code reusability within and between projects. Pure Javascript Library are reusable in themselves. They are usually self contained. Besides, there is no real gain in "bundling" a JS library from the server side. You don't need any kind of bundle to achieve reusability.
My Approach
Since the composer system is so appealing, specially when deploying bundles/packages/libraries to other people, my approach to using third party javascript/css libraries was to create a dependency manager specific to JS/CSS that other packages/bundles could rely on to take care of their JS/CSS dependencies without worrying about this.
My sugestion
If you are planing to release your project to the public, namely as a symfony bundle, you should plan carefully how to approach this.
If your project is self contained (personal use or to a client, not widespread use) then this has much less relevancy since you (the programmer) have total control in what third party tools you use and include in your project. These are just best practice "suggestions" to avoid
future problems.

Best Way To Sync Core Files In Multiple PHP Projects?

I have a PHP Platform that I've built.
I use a copy of that project for each project I do.
I add assets and configure each project with it's own content.
Configuring a project changes some of the core files which contain
the configuration defaults.
When I update core files in the library/platform itself and I want to disseminate those changes to all of the other projects using that platform, what would be the best approach?
I think it may be worth noting that I have each project as an SVN project in Eclipse.
UPDATED DETAILS:
The platform is based on AMFPHP 1.9.
AMFPHP has a services folder.
I have to put core services in the services folder as well as
implementation specific services and therefore cannot achieve
complete separation between the "library" and the "application".
Also, the default configuration files need to be in the "platform" folder
so they can be easily distributed with it, but when configuration is
changed, those files become "implementation specific" as well.
Is there a solution that will allow me to designate certain files to update?
Take a look at the use of svn:externals. Configure each secondary project with your core libraries as an external.
Excellent question, here's the way I solved this problem with my own PHP framework.
If you have all the project-specific and core files mixed together, and platform code interspersed with your project code, it's going to be really difficult to update the core code to all of your projects.
The best way to get around this is to make it easier for svn (or git, or any other versioning software) to update your files: if they're all neatly organized, with project and core files in their respective places. Let me give you an example to clarify.
Put all of the core files of your framework in this directory:
/App/FrameworkName
Here you can place core classes, functions, and other code that won't change for all of your different projects.
Then, any project-related content, settings or pages go in:
/App/Project
Here, you have all of the data that your projects use.
With this system, if you add a feature to your platform, all you have to do is svn the latest version of your framework to /App/FrameworkName, and your project will be using up-to-date code.
My programs are usually organised in two parts. the core framework folder, and the addon folders.my framework (in house) does all the initial work then loads the addon for additional functionality.
For example, the framework deals with all the user auth , the addon provide additional crud functions the each project needs.
That way, i can keep them in separate repository. and the framework can be checked out and used for other projects.

Which PHP frameworks have a code base that can be shared accross entire separate sites easily?

I am looking to reduce redundancies in code shared across entire web sites. I have tinkered with several frameworks but cannot think of any that allow you to EASILY separate the framework code from the site code while sharing it to multiple sites at the same time.
What PHP frameworks can do this easily?
EDIT - I am trying to determine which frameworks are the easiest to share.. I was already guessing that nearly all could be shared, but which frameworks are geared towards sharing? It sounds like Yii recommends placing the framework code outside the site code, that is a good start.
If someone is sharing the same framework code across sites already, I would love to know about that.
It's pretty easy to do that with Fuel (http://fuelphp.com).
Each website has an index.php where some paths are defined:
/**
* Set all the paths here
*/
$app_path = '../fuel/app/';
$package_path = '../fuel/packages/';
$core_path = '../fuel/core/';
As you can see, you may share the core and packages in a central repository and create a single app and public folders to each web site.
You may even share an app with different web sites customizing stuff (let's say, the site title or the database used) by just setting a different environment in the .htaccess. That works out-of-the-box for development/stage/production sites, for example, but may be extended to anything. You may also setup central packages to use in multiple apps. Powerful, easy and just works.
Many can do this. For instance YII is supposed to be installed OUTSIDE of your www-root directory (httpdocs, /var/www/ or something like that). You can use several sites to point to that base dir.
Any framework (or part) that does not need specific settings for your site can be shared among multiple sites I guess.
I believe Zend can do what you ask, possibly even Symfony and Fuel, and I'm sure many other frameworks that allow you to pick what parts of it to use will let you do this.
However, doing so will require you to do a little more configuring to get it all running. Which is kind of why I ended up creating my own framework.
Symfony does. I love the Symfony framework, and it comes with some great frameworks. You might like the Routing and YAML ones. A person I know calls Symfony the best php framework.
Symfony components
Some of the components have their own specific sites
You can find a really good documentation here.
Symfony2 is suitable for your needs. It's a full stack framework with a lot of standalone components. It works with "bundles", a bundle is a kind of container with a complete logic (controllers, model objects, views, assets, configuration, ...). That means you write one bundle and you can reuse it without any problem.
But you can also consider symfony 1.4. One project can handles many applications so your model is shared across these applications and the same code can be reused in all applications. Note an application can be a complete website.
I can't think of any frameworks that do this natively, but you could use several SVN (or hg, etc) repositories to accomplish this. Example using CakePHP:
1 repo has the CakePHP default files. If you wish to update CakePHP,
you update this repo in the future.
1 repo per website that stores everything inside your app folder.
It's not built in functionality, but it isn't very difficult to setup either.

Categories