I was wondering can I change default view folder for a controller in Yii2?
If we can change layout just by using public $layout, how we can do it with view?
Class HomeController extends \yii\web\Controller
{
public $layout = 'mylayout';
public $view = 'newview';
public function actionIndex()
{
return $this->render('index');
}
}
To achieve that your controller should implement ViewContextInterface.
use yii\base\ViewContextInterface;
use yii\web\Controller;
class HomeController extends Controller implements ViewContextInterface
Then just add getViewPath() method which should return the desired directory path:
public function getViewPath()
{
return Yii::getAlias('#frontend/views/newview');
}
You can use aliases here.
Also check the official documentation about organizing views.
Since 2.0.7 you can simply write in your controller's init() method: $this->viewPath = '#app/yourViewPath'
I'm on Yii 2.0.42.1, And added this in my controller.
public function init()
{
$this->viewPath = '#app/modules/report/views/test';
parent::init();
}
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 trying to set up PSR-4 within a new Laravel 4 application, but I'm getting some troubles achieving what I want when it comes to build controllers.
Here's what I have now :
namespace MyApp\Controllers\Domain;
class DomainController extends \BaseController {
public $layout = 'layouts.default';
public function home() {
$this->layout->content = \View::make('domain.home');
}
}
I'm not so fond of using \View, \Config, \Whatever to use Laravel's classes. So I was wondering if I could put a use Illuminate\View; to be able to use View::make without putting a \.
Unfortunately, while doing this, I'm getting the following error : Class 'Illuminate\View' not found.
Could somebody help with this please ?
The problem in your case is that View is not located in Illuminate namespace but in Illuminate\View namespace, so correct import would be not:
use Illuminate\View;
but
use Illuminate\View\View;
You can look at http://laravel.com/api/4.2/ to find out which namespace is correct for class you want to use
Assuming BaseController.php has a namespace of MyApp\Controllers\Domain
namespace MyApp\Controllers\Domain;
use View;
class DomainController extends BaseController {
public $layout = 'layouts.default';
public function home() {
$this->layout->content = View::make('domain.home');
}
}
If BaseController.php has other namespace, i.e MyApp\Controllers
namespace MyApp\Controllers\Domain;
use MyApp\Controllers\BaseController;
use View;
class DomainController extends BaseController {
public $layout = 'layouts.default';
public function home() {
$this->layout->content = View::make('domain.home');
}
}
If, for instance, you controller needs to use another base class from Laravel, lets say Config.
namespace MyApp\Controllers\Domain;
use MyApp\Controllers\BaseController;
use View;
use Config;
class DomainController extends BaseController {
public $layout = 'layouts.default';
public function home() {
$this->layout->content = View::make('domain.home')->withName(Config::get('site.name'));
}
}
The use of View::make() takes advantage of the Laravel facades. To properly reference the facade, instead of directly referencing the class that gets resolved out of the iOC container, I would use the following:
use Illuminate\Support\Facades\View;
This will reference the View facade that is being used when calling View::make()
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');
}
}