Share controllers, models and views in multisite CakePHP 2.3 installation - cakephp-2.0

I'm creating a CakePHP 2.3 advanced installation (several apps -websites- that share one same lib folder where all of cake's core files are located). This works without any problems, I just edit the core.php file in the Config folder for each app so it knows where to find cake's files. The file system looks something like:
[root]
[cake-core-files]
[websites]
[website-1]
[app]
[plugins]
[vendors]
[website-2]
...
[website-N]
These different apps are in fact different in some things (they are different websites) but at the same time there's many things that are common to all of them (for example some models, controllers, functions...). What I would like to do, if possible, is to have those apps also share a bunch of controllers, models, etc so I can put them in one place, instead of replicating them now for each app.
I've seen the concept of vendors and plugins in CakePHP (I actually use plugins in those websites, but from the /app/plugins folder), but I'm not sure if that would work in my case, or how I would set that up. I guess the idea would be to have another folder (for example [shared_objects]) at the same level of [cake-core-files] and [websites], but I don't know how I would have to configure cake to do that or how to call those objects from each app.
Any ideas?
EDIT
Based on the comments/responses below I'm trying to do this using the App:build() function in the bootstrap.php, but I can't get it to work. This is what I've done:
Added a new folder where I want to put the stuff to share between all apps:
[root]
[cake-core-files]
[shared-stuff] --> NEW FOLDER
[Model]
[Config]
[websites]
[website-1]
etc...
Placed the model User.php inside the new folder [shared-stuff/Model]
Added this line in the bootstrap:
App::build(array('Model' => array('/path/to/shared-stuff/Model')));
Deleted the model User.php from its original location [website-1/app/Model]
After this steps, it seems to work, the model User.php is loaded correctly from the [shared-stuff] folder (I've tested that printing App::objects('Model');, the User model is listed). However, it actually doesn't work, when I call that model from the UsersController in the login() function, the login doesn't work (although I don't receive any kind of error, even with debug set to 2).
This model uses a database configuration different from the default one (the users table is located in a different database than the default one). I don't know if this matters.
One thing is for sure, if I leave the same exact User.php model in its original location ( [website-1/app/Model]) it all works fine, including the login, so it's a problem with how I try to configure all this sharing stuff, not the model itself.
Any ideas what am I doing wrong?

I think it could be useful to share some controller/model between multiple websites, and do it without a plugin: Using shared controller/model lets you to overwrite it if needed. It should happen simply copying the controller/model in the website's correct folder and the system should use it instead of the shared one!
EDIT: Wonderful, it works, but i think there is a little error in cake's official documentation: All paths should be terminated with a Directory separator! In the cakephp book there aren't trailing slash. Add it to your App::build path and everything will work perfectly!

You can have plugins in the core Plugins/ dir
[root]
[lib]
[Cake]
[Plugins]
[Available]
[To]
[All]
[website-1] // the 'app' dir -> https://github.com/cakephp/cakephp/tree/master/app
[plugins]
[vendors]
[website-2] // you can have many of them named anything, 'app' is just one.
...
[website-N]
This folder specifically will make the plugins available to any app using the cake lib
EG:
Look at this. Copy app to website-1, repeat till website-n.

Related

How can I create an add folder functionality to my React CMS application?

Click here to see a picture of what I mean
I haven't tried anything yet because I'm not sure how to even approach this problem. I'm not even sure what to Google. I do, however, have a pretty good handle on React. Thanks!
Update: The folders will not be storing files, just hyperlinks.
You need to model the problem space first. i.e. models for folders, and files. Each having properties (name, etc.) and associations (folders can have many files and subfolders).
To store the physical files you can use a third-party service like Amazon S3.
This would get you started at least.

CakePHP 2.x Acl

I am using CakePHP 2.3.6. In a project, I implemented Acl. I followed the official tutorial given, populated the acos table by cake's shell scripting,used AclExtras plugin, then populated the aros_acos table using "customized" initDb function.
Everything is ok now, the tables are populated successfully. So, I thought I don't need the allow()/deny() functions, which I used before for Authorization. So I deleted these functions from the beforeFilter() functions from the corresponding controllers. But, when I deleted them, I cant access any page(fucnction) in my whole project.
To populate the acos table I used this command :
./Console/cake AclExtras.AclExtras aco_sync
To populate the aros_acos table I customized the initDB() and put it in the Users controller and run it.
All tables are populated, everything is good, but its not working the allow()/deny() functions defined before I implemented ACL.
My question is, if I use Acl, if I have all AROs & ACOs stored in the database, and if I define all permissions in the database, then why do I need those allow()/deny() functions ? And if I need those, then why should I use Acl ? My project was fine without the Acl implementation, with the allow()/deny() functions.
So, what should I do ?
Can anyone help me please ?
Thanks.
Ok,
Finally I got the ACL working. I found that its so easy, I just had to know the shellscrpting. I always knew that its implemented well in CakePHP, I just have to make it working in my project.
First of all, we have to make PHP and CakePHP executable from our shell/command prompt. I did it in Windows(7), will try for Linux & MAC later.
First, if you dont have PHP executable from your command prompt, go to My Computer->Properties->Environment Variables(forgot exact path, but you will get it easily). Then paste this c:\wamp\bin\php\php5.3.13; in the Environment Variable, where php5.3.13 is version-specific.
After that, paste this in the same place : cakephp\lib\Cake\Console. You can copy the cakephp folder to your htdocs/www permanently, for later use.
Now, run this in your command prompt : cake bake all, and follow the instructions. You must have to have a database, configured in your config.php file.
By now, you should be ready with the newly created project. Now follow the CakePHP documentation for ACL.
Remember, which functions/methods you want to be open for all kind of users, allow them explicitly by allow(), in AppController, or in the specific controller.
Suppose, you want pages/index,users/login,users/signUp - these 3 pages/functions to be open for all. So, allow() them in the AppController or in Pages & Users controllers.

CakePHP multi-site file system organization with shared functions

I have a CakePHP 1.3 mutli-site installation in the server. Each site has its own folder, and they all load the CakePHP core libraries from one same place. This is how it looks like:
[cake] (cake's core libraries)
[sites]
[site 1]
[app]
[plugins]
[vendors]
.htaccess
index.php
[site 2] (also with its own app, plugins and vendors folders)
[site 3] (also with its own app, plugins and vendors folders)
etc
I find myself many times in the situation where I want to implement some functions that I would like to use in all of the apps, but so far I just replicate the code inside each site. I would like to be able to declare those functions in one place and be able to call them from any site. I believe vendors could have something to do with this, but I've been looking in the cookbook and I can't figure out how to use that in my case.
Any help would be much appreciated!
UPATE
So by looking at the vendors, it seems to me (maybe I'm wrong) that it would work in my case if the functions in those vendors files don't need to directly interact with other CakePHP classes (for example Session, Auth, etc). I'll give an example of one of the things I'm trying to do, maybe that helps to understand better what I'm trying.
Each of the sites has its own login system (using cake's Auth). One of the things I want to do is, when a user logs in (the login() function in UsersController is called), have there a function that does some processing with the username of the user, and then calls the Session->flash() function to insert there a message (the message changes depending on that processing the function makes). So this function needs to use the User model and the Session model.
Can I do this using vendors, so I declare this one function (i.e. processLogin()) in a vendor, and all the sites can use that function? If so, how? If not, is there any other way to do this?
Stick them in the vendor folder at the same level of cake and sites, name-spaced under a name of your choice (usually the agency name or other unique identifier).
Examples on loading vendor files in CakePHP 1.3 is explained in the Cookbook here: http://book.cakephp.org/1.3/en/view/943/Loading-Vendor-Files
However, I’d advise upgrading to CakePHP 2, and placing your code in a sub-folder under lib.

cakephp disable routing for specific URLs

I have a CakePHP 1.3.10 app which I'm trying to make it do the following:
I want to embed a mp3 file in some views, using Google's reader flash audio player. If I put the mp3 file in the webroot directory of my app, there's no problem. However, I would like to have those files in a directory called AUDIO at the same level of my app directory. Like:
[public_html]
[app]
[cake]
[AUDIO]
...
The problem is that if I put my mp3 files there, when I link to them from my view, Cake looks for the controller audio, which doesn't exist, instead of just linking my file. I believe this has something to do with routing, so I was wondering if I can disable automatic routing for a specific folder (**audio in this case).
I want to do this in this way because in the future I might have to access those mp3 from other websites, so I don't want to put them deep into cake's directory system.
Thanks so much in advance for any tips!
Files that should be directly served by the web server without going through Cake should be put in the /app/webroot directory. You can create such a /webroot directory in plugins as well (see here), which technically will use routing, but behaves the same as the general webroot directory.
If you place them anywhere else you're going against Cake conventions, which I wouldn't recommend. Not because it's not possible, you're just making your life harder than it needs to be. You can edit the /app/webroot/.htaccess file to rewrite certain URLs to wherever you stored your files or use Media Views (as pointed out by #Ivo) if you really want to do this.
CakePHP won't be able to automatically find files in folders that it doesn't know about.
I'd suggest using Media Views to serve files from a custom directory.
If you want them to be freely downloadable, you can do this using MediaView also, or put them in a custom folder inside webroot. You'll need to include that folder in paths etc, though.

Share resources among multiple CakePHP webroots on Windows / IIS?

I've got a CakePHP install running six different web sites, each with their own webroot. All of the base code is the same (controllers, models, etc.), just the css, images, js and so forth are split into the separate webroots (app/webroot, app/webroot_second_site, app/webroot_third_site, etc.)
My question is: Is there a way to share common resources among the webroots? So we don't have six different copies of TinyMCE and jQuery cluttering up our project, and more importantly to me, so that we can make a change in a common CSS file instead of having to copy/paste a change across six different sites' folders?
If these sites were running on a Linux box, I think it could be fairly easily accomplished with a symlink from each of the webroots to a common folder higher up in the directory tree, but we're running Windows Server 2003 / IIS 6. Any suggestions?
Turns out you can do directory symlinks in NTFS file systems. Or at least close enough for practical purposes. "NTFS Junctions" will work for what you want.
Grab the Sysinternals "Junction" program for a simple command-line program to create/delete these junctions.
Then you can link whatever common directories you need to a single master directory.
For example, if you have
webroot1/
webroot2/
webroot3/
each with their own "js/" directory, then you could create
webroot_common/js/
and then symlink... er, "create junctions" to that new directory like so:
junction webroot1/js/common webroot_common/js
junction webroot2/js/common webroot_common/js
junction webroot3/js/common webroot_common/js
(yes, the "junction" program takes its inputs backwards from Linux "ln -s")
Then you can put whatever common js files you need, like jQuery, in that common folder, and leave any site-specific js files in "webrootX/js".
You could make a static server. Add a DNS entry to something like static.yoursite.com. Link to those files from your other sites -- probably you could just modify the HTML helper so that it will automatically create links to the other domain.
This can help with performance, because you can run something like nginx to serve these static files. It will also parallelize the resource retrievals -- most browsers will allow 2 connections to a given server, so the static stuff competes with those connection resources that are needed by the dynamic stuff. In essence, the user will start 2 connections to your dynamic stuff as well as 2 connections to the static resources.
Works pretty well IME.
This will work. You will need to redefine the directories for a windows server, but you will understand it well enough.
First, put your APP and CAKE directories a level above the public_html.
/var/www/app
/var/www/cake
Make sure that the folder cake has all of the cake folders in it (cake, vendors, etc.)
Point your sites to their public_html directories.
/var/www/html/site1
/var/www/html/site2
The webroot content will sit in each of the public_html directories. Now, modify your index.php file in each of the webroots to point to the same app:
if (!defined('ROOT')) {
define('ROOT', DS.'var'.DS.'www'.DS.'app');
}
if (!defined('APP_DIR')) {
define('APP_DIR',dirname('app'));
}
if (!defined('CAKE_CORE_INCLUDE_PATH')) {
define('CAKE_CORE_INCLUDE_PATH', DS.'var'.DS.'www'.DS.'cake');
}
Make sure that rewrite is turned on of course. Then it will all run off the same code but use the webroot where the index.php is being served from.

Resources