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.
Related
I've developed My Own MVC Framework using php.
I call view files in controller like:
include('../view/home.php');
but I want to use it like:
$this->view('home');
How can I define common function for that where I can just pass view name i.e home only and it will do include view file without passing the full file path?
No one could answer you without seeing your codes really. But this should be my approach.
You should have a class that all your controllers extend. Lets say that you have class Controllers and all your controllers extend it.
Then you may have a method inside the class named view($view_name).
public function view($view_name){
include $some_path . '/' . $view_name . '.php';
}
then whenever you call view by $this->view it will include the view if it exists.
This is not the best approach and I did not test the code. I just wanted to show you the path
I don't know Your MVC file/directory/namespace and etc structure.
But for beginner who tries to learn MVC and Frameworks by "reinventing wheel" (: I can give such example:
1) Create common abstract controller class in app/controllers folder:
namespace App\Controllers;
abstract class Controller {
public function view($name) {
include(__DIR__.'/../views/'.$name.'.php';
}
}
2) Create Your own controller i.e. PagesController and use it:
namespace App\Controllers;
class PagesController extends Controller {
public function home() {
$this->view('home');
}
}
p.s. You may omit namespace-ing, abstract word depending on autoloader logic
Like in Codeigniter we do have 'core' folder where we can define our own controller like 'MY_Controller' and can be used to extend all the class to extend from this controller is there any possibility to do so in Symfony2.
In symfony I want to create class 'MY_Controller' which extends from the base class 'Controller', and I want all the classes in the controllers to extend from MY_Controller' class.
Thanks in Advance...
Note:
When working with Symfony2 it is strongly recommended you follow the Symfony2 coding style. It's basically the same as PHP-FIG, with one or two deviations. So underscores are a no-no in class names. Other than that: Symfony is pretty easy to work with, and fully OO, so changing the class a controller extends from is as simple as replacing extends Controller with extends AnotherClass.
But now, the symfony2-way of using a custom controller:
What you could do, is create a Core bundle (CoreBundle henceforth). Then, in this CoreBundle, define a controller, that extends from the Symfony Controller component. From the command line, in your project root, use this command:
php app/console generate:bundle --namespace=YourNameSpace/CoreBundle --bundle-name=YourNameSpaceCoreBundle
More options can be found here
After that, you'll find a DefaultController class in the bundle directories. (probably in the folder src/YourNamespace/CoreBundle/Controller). Then, set about generating your Core controller:
php app/console generate:controller --controller=YourNameSpaceCoreBundle:Core
See the documentation for more options on how to generate your core controller.
After you've finished setting up your custom controller, you can use it in any of the other bundles at will:
namespace YourNameSpace\AnotherBundle\Controller;
use YourNameSpace\CoreBundle\Controller\CoreController;
class DefaultController extends CoreController
{//extends from your custom controller
}
And that's it: you're done.
First, don't name the class using underscores as in PSR-0 each underscore char is converted to a directory separator, when used in class name.
Second, put your controllers to <bundledir>/Controller/
Third, name your controller something like BaseController and extend all other controllers from it.
Fourth, think of using dependency injection rather than coupling functionality in a base controller.
It appears that in Zend Framework 2, every controller seems to extend the AbstractActionController by default.
I was thinking if there's a way for all my controllers to extend a CustomController that in turn extends the AbstractActionController.
The purpose of this CustomController, is to do checks like whether a user is authorized to access my other controllers or not and also may be generate menu navigation.
Is this still a good idea and if so, will doing this work?
**IndexController.php**
class IndexController extends CustomController {
}
**CustomController.php**
class CustomController extends AbstractActionController {
}
Thanks,
Of course you can extend a base class and it will work.
Is it a good idea ? It really depends on your project.
For authentication and permission check, you could also use a module like ZfcRbac or BjyAuthorize
For navigation, there is spiffy-navigation
If you use php 5.4+, Traits can also be an alternative to inheritance
I'm trying to integrate PHP namespaces into an existing Zend Framework project (v1.12). When I add namespacing at the top of a working controller, it doesn't work anymore and the application throws an Invalid controller class error. Here's my controller definition :
namespace MyProject\Controller;
use MyProject\Controller\MyRestController;
class MyFooController extends MyRestController
{
}
and the init method within the Bootstrap.php:
protected function _initAutoload()
{
$autoloader = Zend_Loader_Autoloader::getInstance();
$autoloader->registerNamespace('MyProject');
return $autoloader;
}
Just a guess (have not used ZF for quite some time): Zend will not accept any class as a controller, just those extended from the framework's base controller class. As you don't extend from the frameworks base controller class you see the error.
If that is the reason, take care you initially extended from the base framework controller class or you implemented the needed interface.
namespace MyProject\Controller;
class MyRestController extendes Zend_Framework_Base_Controller_Class_Name_Here
{
...
p.s. the use MyProject\Controller\MyRestController; looks superfluous as that class is in that namespace already. Let's review your code:
namespace MyProject\Controller;
This sets the namespace of the file. That means, non-FQCN will resolve into it. For example:
new MyRestController();
Resolves to the following FQCN:
new MyProject\Controller\MyRestController
Which - oha! - is exactly what you wrote in use:
use MyProject\Controller\MyRestController;
Which means, that this use clause is superfluous, the extend in:
class MyFooController extends MyRestController
Would go to it anyway at first. Because it's the same namespace.
I am facing similar problem now. For me this looks like that Zend cannot properly resolve namespaced controller name. So when I put for example IndexController into namespace \Basic\Controller, it will be not loaded because Zend want to load \IndexController class, which does not exist.
I am thinking about extending standard zend router class, which has method getControllerName.
Then I can set this in bootstrap by:
$router = new \My\Namespaced\Router();
$front = Zend_Controller_Front::getInstance();
$front->setRouter($router);
I didn't tried that code yet but this should work.
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.