The ZF Docs reference 'Subclassing the Action Controller' (bottom of the page), but don't reference a standard place to put the new Action_Controller class.
Application_Module_Autoloader sets up pats for a bunch of things, but never controllers. I guess putting it on library/APPNAMESAPCE/Action/Contoller would work. But that seems a bit odd since every other application specific file is stored under application/.
The class gets autoloaded like any other class, there isn't a 'standard' place for it as such. So the question becomes, where do you want it to live?
The convention I usually follow in modular applications is to have most stuff in the modules, but register an app namespace and use application/models for 'core' type classes. So in your case, say your app namespace was Wordpress, you'd have:
class Wordpress_Controller_Action extends Zend_Controller_Action
{
}
and the file would live in application/models/Wordpress/Controller/Action.php.
To make this work you'll need application/models on your include path, and you'll want to init the standard autoloader with something like this (in your bootstrap class):
protected function _initAutoloader()
{
$autoloader = Zend_Loader_Autoloader::getInstance();
$autoloader->registerNamespace('Wordpress_');
return $autoloader;
}
alternatively you could setup the above in application.ini.
Related
I want to have two folders where save codeigniter's controllers:
/application/controllers
/application/buckets
i'm a order paranoic person and i want to separate two types of my controllers.
In bucket folders the structure app was this:
/application/buckets/example/index.php
/application/buckets/example2/index.php
/application/buckets/example3/index.php
¿Maybe extending the router class?
A working example:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/*
Extended the core Router class to allow for sub-sub-folders in the controllers directory.
*/
class App_Router extends CI_Router {
function __construct()
{
parent::__construct();
}
function _validate_request($segments)
{
if (count($segments) == 0)
{
return $segments;
}
if (file_exists(APPPATH.'buckets/'.$segments[0].'/index.php'))
{
$this->set_directory(APPPATH.'buckets/'.$segments[0]);
$this->set_class(ucfirst($segments[0]));
$this->set_method(isset($segments[1]) ? $segments[1] : 'index');
return $segments;
}
}
}
You can use Hierarchical MVC(HMVC) with Codeigniter to accomplish this.
For reference, see Modular Extensions - HMVC
You may want to look into parent-child controller ...one extending another. To be more clear you can make as many controller you want.
I Agreed with #Brian Gottier : "what does changing their location do?"
You can perform anything if you have core functionalities in your hands.
You can play around with hooks (CodeIgniter's Hooks feature provides a means to tap into and modify the inner workings of the framework without hacking the core files. When CodeIgniter runs it follows a specific execution process, diagramed in the Application Flow page.)
Create "Base"/"Admin"/"Public"/"XYZ" Controllers in
application/core/MY_Controller.php
and keep rest of your controllers in same application/controller folder
MY_Controller is a basic core library extension. Whenever you create a class with the MY_ prefix the CodeIgniter Loader class will load this after loading the core library.
All we have done here is create a base class that all of our Controllers and "controller types" will inherit. Anything we put in here and assign to $this will be available to anything that extends this class.
Base Controllers are a nice simple way to give you global data, logic and shared code which can be specific to a certain part of your site. They can do all sorts of crazy stuff which I will leave for you to think about.
I Hope this help.
Ok so I have two files, one called Database.php and another called Auth.php...
class Database {
// method inside
}
Then I have Auth:
class Auth extends Database {
//methods inside
}
They are both in the same directory. I know my object list will get pretty huge and I rather not put 5 million includes at the top of every class script.
How do I make it so the extends keyword automatically searches all the classes in the same directory?
Use PHP autoloader feature - http://php.net/manual/en/language.oop5.autoload.php.
This is example of autoloader in Nette framework - http://doc.nette.org/en/auto-loading
I need to create some base exception classes and inherit from it.
I see two approaches:
1. Create folder 'Exceptions' in library and use standard autoload mechanism
/library
/Exception/
Base.php
InvalidParameter.php
2. Just declare exception classes in model, that uses it.
Is there a better more "Zend-ish" approach?
If you look into zend library, what they normally do is
/library
Exception.php
/Exception/
InvalidParameter.php
And InvalidParameter Class would look something like Exception_InvalidParameter extends Exception. It is quite similar to what you have suggested in option 1.
I generally love to have all my custom library classes in to /library/custom
The purpose of creating specific exception classes is to associate it with some specific functionality (database , session etc) . If your functionality can be fully described in one class for example
Class AdminController extends Zend_Controller_Action
{
public function loginAction()
{
throw new LoginException('Failed login');
}
}
Class LoginException extends Exception {
}
Note both classes are in same file AdminController.php . This approach is faster since no autoloading is needed to load LoginException since its in same file.
Alright I have a tiny framework that I hope to open source soon and I'm trying to implement namespacing so that controllers and models don't need appended text. Here's the basic code logic:
url request
htaccess reroutes to index.php which initiates the framework
framework parses route & determines which controller/action to instantiate & fire
the framework's front controller is 'Controller' & project controllers extend 'Controller'
So in order to allow for controllers to be named for example:
class Foo extends Controller {}
and later a model be:
class Foo extends Model {}
My directory structure is like so:
project/
controllers/
foo.php
models/
foo.php
So, I'm obviously needing to implement namespacing. (And yes, I'm running php 5.3). So my question is, how exactly would I implement namespacing where the front Controller and Model is extended by other controllers and models?
One way to do it would be to manually prepend the namespace assuming your controllers are living in the same space. Take the following example.
public function __construct( $controller, $model )
{
$this->controller = 'Application\Controllers\\' . $controller;
$this->model = 'Application\Models\\' . $model;
}
There may be a more autoload-ish way of doing it but I think this will suffice in most cases. Don't quote me but perhaps you could use Reflection and get the namespace of the called object. However, this may still require a more unique naming convention otherwise the autoloader still wouldn't know if you were calling Controllers\Index.php or Views\Index.php.
Always check php.net... http://php.net/namespace
I'm trying to extend my controllers with a global base controller as such:
class BaseController extends Zend_Controller_Action {
// common controller actions
public function listAction() {
// do stuff
}
}
class IndexController extends BaseController {
// index controller specific actions
}
class LoginController extends BaseController {
// login controller specific actions
}
But I get this error:
PHP Fatal error: Class 'BaseController' not found in /var/www/Zend/project/application/controllers/IndexController.php on line 3
Any ideas on how to get Zend to "see" this controller?
Autoloader
Setup the autoloader and register your library which should be besides the Zend library with the autoloader like so (in your bootstrap.php after setting the include path):
//AutoLoad loads classes automatically if they are used
require_once 'Zend/Loader/Autoloader.php';
$loader = Zend_Loader_Autoloader::getInstance();
$loader->registerNamespace('Mylibrary_');
Zend naming conventions
Then you should rename your BaseController as follows
/Zend (folder)
/Mylibrary (folder)
/Controller (folder)
Action.php <-- this is your basecontroller file
which contains:
class Mylibrary_Controller_Action extends Zend_Controller_Action
{
}
and your normal controllers in the controller folder:
class IndexController extends Mylibrary_Controller_Action
{
}
so basically when you want to extend the framework you keep a parallel structure in your own library.
I would separate it into your own library, i.e. create the file library/YourApp/Controller/Action.php, and consequently name it YourApp_Controller_Action extends Zend_Controller_Action. From there you could place controllers where they should be and let them extend YourApp_Controller_Action in favor of Zend_Controller_Action.
To find the file you should rely on the autoloader to look not just inside of library/Zend, but also in library/YourApp. I.e. look for the set_include_path in your bootstrap.
With this technique you should keep in mind that your custom "basecontroller" might get bloated with methods that not all of your controllers needs to inherit.
the quick solution that does not take advantage of the autoloader functionality is to
require_once '/path/to/BaseController.php' in the index-controller file.
If you have set-up autocontroller, then it can not find it, so you should consider checking what's wrong. Try the previous approach and inform on results.
Even more quicker solution (and conceptually more correct) is NOT to create base controllers at all:)
You have common action? Use action helpers. You have some functionality that must be autorun? Use controller plugins.
By design ZF controllers were made as flexible as possible, and limiting yourself by inheritance (and coupling it brings) is just not the best possible strategy.