What class(FrontController , Bootstrap, Dispacher....) sets up the default structure path in ZF?
There is no single instance that has all the paths. Each component has it's own defaults, e.g. the FrontController knows that the controller directory should be named controllers, but it doesn't know how to make a full path from it (Dispatcher does it) or where to find the Action Helpers. That's defined in ActionHelper Broker. Consequently, Zend_View_Abstract holds the paths for View filters, helpers and scripts, etc.
Like #Pascal mentioned in his comment, you should not modify ZF at it's core. You will lose the changes once you update to a newer version anyway. Configure the paths through the API in your bootstrap or through the application.ini instead.
Actually it's the dispatcher's job to find the requested action controller.
So you'll have to extend either Zend_Controller_Dispatcher_Abstract or Zend_Controller_Dispatcher_Standard or even create a completely new one based on Zend_Controller_Dispatcher_Interface to fit your requirements.
But be aware that you'll have to change the way Zend_Controller_Action_Helper_ViewRenderer tries to find the required view files, too.
Related
I'm using CodeIgniter and I have a few utils that I want each controller (that is, each controller file) to have access to.
The question is: where to put these?
I thought of helpers, but the CI documentation talks only about extending existing helpers, not making your own. I'm sure that doesn't mean I can't make my own helpers, but it does mean I don't know how they should be built (procedural? Methods of the global CI instance? etc)
I also considered hooks, but this is a poor fit I think as I'm not extending core functionality.
Or is there some other way I'm missing?
It's been a while since I've done this but I believe I used two approaches.
Creating a new, custom helper that goes into /application/helpers, following steps noted from this answer: CodeIgniter: Create new helper?
Creating a new library class into /application/libraries which I also activate in the autoload configuration found in /applications/config/autoload.php. This way it's always available to my controllers when I need it. CI has good documentation on this one (http://ellislab.com/codeigniter/user-guide/general/creating_libraries.html).
I did it simply by adding a file to the application/helpers folder (maybe I created that folder - I can't remember) and then loading them in the usual way.
My site structure is currently like this:
/cms/
/data/ - caches etc
/modules/
/public/ - aliases from site public folders
/website1
/images
/layouts, views, scripts, css etc
(no index.php because of the alias)
This works fine, my system looks to the alias folder to run the app. However, I've now got to the point where I would like to extend one of the module controllers.
Ideally my structure would be:
/cms/
.. as above
/CLIENT_ID/
/modules
..extending/overriding scripts
However, this is the problem: the controller to be called must be called according to Zend's file name structure (Module_IndexController etc), so to extend the base classes would be:
Module_IndexController extends Module_IndexController
Which obviously wouldn't work nicely. My thought is that it should be:
CLIENTID_Module_IndexController extends Module_IndexController
But I'm stuck on ideas on how to implement this? I can add the controller directory using: addControllerDirectory on the front controller but I'm guessing I need to change the called class name somewhere?
I can then check if the folder is a directory and run the overriding class rather than the base one.
Any ideas? I'm open to restructuring the folders, but obviously need to keep media files in the public folder.
The problem is that you are not using the conventional directory structure that Zend_Dispatcher, Zend_Autoloader and Zend_Controller are programed to work with.
In my opinion you have two possible solutions:
customize Zend_Autoloader and Zend_Controller and Zend_Dispatcher. You can find possible customizations here, here and here.
modify the directory structure.
In this second case consider theese possible projectual choices:
create independent standalone zend framework projects for all the sites, and create in those the aliases of the CMS folders
like the previous but customizing the module locations with:
http://framework.zend.com/manual/en/zend.controller.modular.html#zend.controller.modular.directories
Use the CMS as a library: you put all the cms files in folder outside the /websiteN and then in websiteN's application.ini you set includePaths.library = /path/to/cms/folder". There are a lot of possible problems in this possibilty, that must be valuated knowing your project. In this way you can call models, extends websites's classes to extend cms's, but you cannot use your cms as the entry point and manager of the user interactions at variuos levels.
As you said, you can tell Zend the base controller directory for each module.
$controller = Zend_controller_Front::getInstance();
$controller->setControllerDirectory(
array("module_name" => "directory_path")
);
I would think Zend would want the naming convention to be ClientId_Module_Controller. But, if you really get stuck with the naming convention, and are using php 5.3 you could use namespaces.
I'm building a codeigniter application that will serve custom microsites. Essentially each microsite will be a collection of seven different views all loaded by a single controller's methods. To 'Theme' each microsite there will be different folders containing different versions of these view files (and their associated css, js and image files) and the controller will know which folder of views to load based on information stored in the database for each microsite record.
The problem with this approach is when a single microsite needs to have a custom page that is unique from all the other microsites. Since they're all controlled by one controller, we run into the limitation that either all the microsites need to support this page.
To futher explain what I'm referring to imagine these urls:
http://www.fakewebsite.com/index.php/microsite/index/david_site
http://www.fakewebsite.com/index.php/microsite/index/frank_site
In both of these links the controller is 'microsite' and the method is 'index'
'index' knows what template to return based off it's first argument which is either 'david_site' or 'frank_site' in the above example.
I can't say if this is possible with Codeigniter, but I assume so:
So what's now your problem? That you have too much code in the controllers? Move code from the controllers into the models. Then the code is more re-useable and you can have small controllers on each microsite with fat models that are shared anyway.
Sounds not really good so far, right? Still there's one controller per each site. Well, make each microsite's controller extend from a base controller. So all code's still in one place but for some controller methods they can extend that base controller on a per-site basis.
So the front-end controller then will provide the right controller class per site as it does for the themes - if I understood your question right.
Can you have a default "theme" for that controller, which would accommodate most of your microsites, and then if you need to create custom themes on top you can change it?
So like this
http://www.fakewebsite.com/microsite/david_site/ <-- default theme
http://www.fakewebsite.com/microsite/frank_site/ <-- default theme
http://www.fakewebsite.com/microsite/john_site/customtheme/ <-- custom theme
As I understand the question, you're asking how to load a different view file for only specific "microsites", but you're using the same controller and codebase for all of them.
In your views directory, have 1 directory for default themes, and and then for each "microsite" you want to do something custom with, create another directory which will contain the unique files, then when loading files - check if the unique exists first.
Hasty example that assumes default files are in the root of views/:
// I assume we know which site we're loading
$theme = 'david_site';
// Whatever the current view's name should be
$view = 'page3';
// Path to our custom file if it exists
$custom = APPPATH.'views/'.$theme.'/'.$view;
// Does a custom view exist?
if (file_exists($custom))
{
$view_file = $theme.'/'.$view;
}
else
{
// Use the default
$view_file = $view;
}
$this->load->view($view_file);
As far as I know, there's nothing like view_file_exists() in CI, so we're just using plain old file_exists() with the full path.
It would be worth writing a function for this of course, but hopefully this helps. You could even apply it to loading libraries, models, etc. - or even extend the Loader class to do it automatically (probably overkill).
CI2 already has a version of this feature in the ENVIRONMENT constant, although this usage is not its intention - but that is basically what it does.
I have a project that uses Zend Framework and Zend_Translate.
I had to alter the standard CSV Adapter to Zend_Translate slightly. Now I'm confronted with the question where to put this altered adapter.
By default, adapters are stored in
/Library/Zend/Translate/Adapter/Adaptername.php
This is where I've put the new adapter as well.
However, I wouldn't like to "pollute" the Zend library with my custom extensions: I would like to stay able to update ZF without having to worry about losing files; I want to remain able to use a centrally installed version of ZF; and the custom adapter is part of the project I'm working on, really.
Is there a Zend Framework way of dealing with this, or specifying an alternative loading location?
Language adapters are loaded using
$this->_adapter = new $adapter($data, $locale, $options);
(Where $adapter will be Zend_Translate_Adapter_Adaptername)
so standard autoloading rules apply. Is there a simple way to tell the Zend Autoloader to look in a second location?
You can add it to the lib folder
/lib
/Zend
/Translate
/Adapter
/Csv.php
/My
/Translate
/Adapter
/Csv.php
Depending on how your autoloader is setup, you have to setup the "namespace" with it:
$autoloader->registerNamespace('My_');
Or, if you dont like this, put it into your models folder. Basically, it doesnt matter where you put it, as long as it is accessible somehow by the autoloader. The Zend_Autoloader can register arbitrary autoloader callbacks, so it's really up to you.
I can't comment on Gordon's answer due to this site's rules, but he's got it right. To answer your question regarding how to load the adapter, you'll need to pass the full class name to the constructor of the translate object:
$translate = new Zend_Translate('My_Translate_Adapter_Class', ...);
The component first checks in the Zend namespace in case you've passed in a short name (like 'gettext'), but will then attempt to load the adapter name as a class directly.
At least, this is true in 1.10, and I imagine has been for a while.
straight to the point :
I am using Kohana, and I am looking at another script written in plain PHP. In the script, I have a class ShoppingCart. If I am to convert the script to Kohana, where am I to put the class, its methods and its properties?
Is it in my existing default controller? Or should I put it in a separate controller? Or as noobie as it may sound, will I put it in the model?
That depends on the specifics of the class I suppose. To be honest I don't know anything about Kohana, but there's probably a place for "vendor files" somewhere. Maybe it's best to place it there and write wrapper functions for it in your controller. If the class already integrates well with Kohana you may instead choose to use it as a controller or model directly. Or you might want to take the time to rewrite it to make it work as a controller...
Only you can evaluate the best place for it, there's no hard and fast rule here.
Kohana has a folder for 3rd party libraries. The main one is under system/vendor, you can put it in you application/ as well.
Many PHP class loaders require details like your filename should be the same as the class name (at least that's what I read in the Kohana documentation) if you want the classes to be automatically loaded.
If you need to use 3rd party code in your app it's recommended that you create a folder in your app / module folder called 'vendor' and place all of that code there.
You can then include the files by calling:
include kohana::find_file('vendor', 'filename');
If needs be you can also create a wrapper for the external library, a good example of this is the email helper which uses the 3rd party Swift email library.
If you're porting your own class to kohana then you need to work out what the class will be doing and categorise it accordingly.
If the class will be fetching items from some kind of database then you should make it a model. Libraries are usually sets of code that you want reuse across controllers / models, such as authentication, calendar generation etc. Controllers are used for passing data from models to your views / libraries.
See the docs for more info
As per kohana convention, you should place custom classes in application/libraries folder. However for this, you need to know how to get the class to work after putting it there. If you can't figure that out, you can do anything like putting it in your controller or making another controller of it, etc.