My question is, how can I inherit Controllers action in YII, like:
class MainController extends FController
{
public function ActionIndex()
{
$this->render("index"); //the view;
}
}
--------------------------------------------
class SecondController extends FController
{
public function ActiondIndex()
{
MainController::ActionIndex();
}
}
Actually in my case the SecondController is the DefaultController of a sub-module. I want to make single code based webpage.
Since PHP does not support multiple inheritance, you may access the base class via the parent keyword.
class MainController extends FController
{
public function ActionIndex()
{
$this->render("index"); //the view;
}
}
class SecondController extends FController
{
public function ActionIndex() // Note: you mistyped the name of this action in your example
{
parent::ActionIndex();
}
}
Although you cannot reach the grandparent's ActionIndex method directly, you have to create a workaround for that.
Related
I have a the following in mysite/code/Page.php:
...
class Page_Controller extends ContentController {
public function init() {
parent::init();
Requirements::javascript("themes/example/js/global1.js");
Requirements::javascript("themes/example/js/global2.js");
Requirements::javascript("themes/example/js/global3.js");
}
}
...
and then a custom controller in mysite/controllers/PlayController.php:
...
class PlayController extends ContentController {
public function init() {
parent::init();
Requirements::javascript("themes/example/js/play.js");
}
}
...
I would like to use the Requirements from Page.php in PlayController.php. Since they both extend ContentController, is this possible?
A little background; PlayController is used to display a page for a theatre play with the template Layout/PlayPage.ss. If I put the Requirements in templates/Page.ss, they are inherited by PlayPage.ss. But I'd like to put the Requirements in a controller, so I can use Silverstripe's combine_files feature. Hope this makes sense!
Thanks :-)
You could create a subclass of ContentController that can serve as the base-class for both of your controllers. Eg. you create a MyController extends ContentController and then PlayController and Page_Controller extend MyController.
Or you could just require all the files in both controllers… if that's too much redundancy, you could also use the config API for this. Here's an example:
class Page_Controller extends ContentController
{
private static $js_requirements = [
"themes/example/js/global1.js",
"themes/example/js/global2.js",
"themes/example/js/global3.js"
];
public function init() {
parent::init();
foreach ($this->config()->js_requirements as $js) {
Requirements::javascript($js);
}
}
}
And then in your PlayController, you could access the config of Page_Controller like so:
class PlayController extends ContentController
{
public function init() {
parent::init();
foreach (Config::inst()->get('Page_Controller', 'js_requirements') as $js) {
Requirements::javascript($js);
}
Requirements::javascript("themes/example/js/play.js");
}
}
You could then also use the YAML config to configure your requirements, eg.:
# mysite/_config/config.yml
Page_Controller:
js_requirements:
- "themes/example/js/global4.js"
Note: Always use dev/build, so that your config variables are being picked up.
I am new into Phalcon framework. I just got the basic idea about it. Every controller has methods with multiple specific actions. I wrote a huge indexAction method but now I want to break it down with multiple private method so that I can reuse those functionality. But when I try to create any method without action suffix, it returns error(Page Not Found). How can I break it down into multiple methods?
<?php
use Phalcon\Mvc\Controller;
class PostsController extends Controller
{
public function indexAction()
{
$this->someMethod();
}
public function someMethod()
{
//do your things
}
}
Controllers must have the suffix “Controller” while actions the suffix “Action”. A sample of a controller is as follows:
<?php
use Phalcon\Mvc\Controller;
class PostsController extends Controller
{
public function indexAction()
{
}
public function showAction($year, $postTitle)
{
}
}
For calling another method, you would use it straight forward
<?php
use Phalcon\Mvc\Controller;
class PostsController extends Controller
{
public function indexAction()
{
echo $this->showAction();
}
private function showAction()
{
return "show";
}
}
Docs.
What exactly do you want? The answer seems trivial to me.
class YourController extends Phalcon\Mvc\Controller
{
// this method can be called externally because it has the "Action" suffix
public function indexAction()
{
$this->customStuff('value');
$this->more();
}
// this method is only used inside this controller
private function customStuff($parameter)
{
}
private function more()
{
}
}
I'm developing an API to acces some data on my database. I'm creating a controller for each part of the API. For example, I will have a controller to attend API calls to get a film list (FilmsController) and other controller to attend API calls to get a director list (DirectorsController)
Each controller will have a basic set of methods (getList, getInfo) so I made an ApiController to use as the base for the others. In the ApiController I have the basic set of methods but I have to call the models in non very polite way.
I'm I missing something? Is there any other way to call the models dynamically? I'm using the controllers wrong?
Here is the code, thanks.
class ApiController extends BaseController {
protected $model = '';
public function getList()
{
$items = call_user_func(array($this->model,'all'));
return Response::json($items);
}
...
}
And the FilmsController
class FilmsController extends ApiController {
protected $model = 'Film';
}
Am I going with a bad design?
If you really want to bind model to controller, it would be better to use Laravel IoC container and its automatic resolution feature.
class ApiController extends BaseController {
protected $model;
public function getList()
{
$items = $this->model->all();
return Response::json($items);
}
}
class FilmsController extends ApiController {
public function __construct(Model $model)
{
$this->model = $model;
}
}
Find more about this in documentation
why you call model using variable and use call_user_func function
you can just create ApiController as abstract class and you override the basic set of methods (getList, getInfo) into FilmsController and DirectorsController then you can use Film Model
ApiController:
class ApiController extends BaseController {
public function getList()
{
}
FilmsController:
class FilmsController extends ApiController {
public function getList()
{
$items = Film::all();
return Response::json($items);
}
}
I have this route: Route::controller('/', 'PearsController'); Is it possible in Laravel to get the PearsController to load a method from another controller so the URL doesn't change?
For example:
// route:
Route::controller('/', 'PearsController');
// controllers
class PearsController extends BaseController {
public function getAbc() {
// How do I load ApplesController#getSomething so I can split up
// my methods without changing the url? (retains domain.com/abc)
}
}
class ApplesController extends BaseController {
public function getSomething() {
echo 'It works!'
}
}
You can use (L3 only)
Controller::call('ApplesController#getSomething');
In L4 you can use
$request = Request::create('/apples', 'GET', array());
return Route::dispatch($request)->getContent();
In this case, you have to define a route for ApplesController, something like this
Route::get('/apples', 'ApplesController#getSomething'); // in routes.php
In the array() you can pass arguments if required.
( by neto in Call a controller in Laravel 4 )
Use IoC...
App::make($controller)->{$action}();
Eg:
App::make('HomeController')->getIndex();
and you may also give params
App::make('HomeController')->getIndex($params);
You should not. In MVC, controllers should not 'talk' to each other, if they have to share 'data' they should do it using a model, wich is the type of class responsible for data sharing in your app. Look:
// route:
Route::controller('/', 'PearsController');
// controllers
class PearsController extends BaseController {
public function getAbc()
{
$something = new MySomethingModel;
$this->commonFunction();
echo $something->getSomething();
}
}
class ApplesController extends BaseController {
public function showSomething()
{
$something = new MySomethingModel;
$this->commonFunction();
echo $something->getSomething();
}
}
class MySomethingModel {
public function getSomething()
{
return 'It works!';
}
}
EDIT
What you can do instead is to use BaseController to create common functions to be shared by all your controllers. Take a look at commonFunction in BaseController and how it's used in the two controllers.
abstract class BaseController extends Controller {
public function commonFunction()
{
// will do common things
}
}
class PearsController extends BaseController {
public function getAbc()
{
return $this->commonFunction();
}
}
class ApplesController extends BaseController {
public function showSomething()
{
return $this->commonFunction();
}
}
if you were in AbcdController and trying to access method public function test() which exists in OtherController you could just do:
$getTests = (new OtherController)->test();
This should work in L5.1
I have two controllers which have some actions that are really the same.
How do I refer to the identical action in another controller?
class UserController extends Zend_Controller_Action {
public function listAction() {
//do something here
}
}
class AdminController extends Zend_Controller_Action {
public function listAction() {
//how to call UserController::listAction here?
}
}
What do I put in AdminController::listAction above so that I only have to write the code in UserController::listAction?
thanks
I would use a controller action helper, that way if you ever have to do the same thing again you can reuse it.
class My_Controller_Action_Helper_Whatever
{
public function direct()
{
return $this;
}
public function doSomething($paramA, $paramB)
{
// code
return $whatever;
}
}
Then implement in your controllers:
class UserController extends Zend_Controller_Action
{
public function someAction()
{
$this->getHelper('Whatever')->doSomething($a, $b);
}
}
class AdminController extends Zend_Controller_Action
{
public function anotherAction()
{
$this->getHelper('Whatever')->doSomething($a, $b);
}
}
You could do:
class baseController extends Zend_Controller_Action {
// common controller actions
public function listAction() {
// do stuff
}
}
class AdminController extends baseController {
// admin controller specific actions
}
class UserController extends baseController {
// base controller specific actions
}
You could also forward the request to the other controller by using:
class AdminController extends Zend_Controller_Action {
public function listAction() {
$this->_forward('list','user');
}
}
or if you would prefer the URL to change:
class AdminController extends Zend_Controller_Action {
public function listAction() {
$this->_redirect('/user/list');
}
}
You can forward to another action - simply specify the action, controller, module and params.
Parameters default to values of the current request, i.e. if you're in the default module, the code below will redirect to the listAction of UserController in the default module.
class AdminController extends Zend_Controller_Action {
public function listAction() {
//call UserController::listAction
return $this->_forward('list', 'user');
}
}