How do I change the default layout globally (= for all controllers and views) in Yii2? I want to leave the main.php layout as is in case I want to use it later.
In root of configuration you can write default layout [[\yii\base\Application::$layout]] for all views:
[
...
'layout' => 'main',
'components' => [
...
]
]
Configure layout & layoutPath in Yii2 config:
$config = [
...
'layoutPath' => '#app/views/layouts2',
'layout' => 'main2.php',
];
Above example changes default view app/views/layouts/main.php to app/views/layouts2/main2.php.
Yii2 Application Structure > Application
You can do in the following way. For example a defaultLayout.php layout can be created like this:
<?php $this->beginContent('#app/views/layouts/main.php'); ?>
<div class="container">
<div class="row">
<div class="col-lg-4">Left Side Bar</div>
<div id="content" class="col-lg-4">
<?php echo $content; ?>
</div><!-- content -->
<div class="col-lg-4">Right Side Bar</div>
</div>
</div>
<?php $this->endContent(); ?>
Inside the relative action
public function actionIndex()
{
$this->layout = 'defaultLayout';
return $this->render('index', [
'model' =>$model,
]);
}
In configuration(config/main.php) you can overwrite the default layout for all your views
[
// ...
'components' => [
'view' => [
'layout' => 'main.php'
],
// ...
],
]
In your config, you can edit the layoutPath .
Example:
$config = [
...
'layoutPath' => '#app/views/layouts-2'
];
Change in config/web.php file
and add this line before components array
your new style name which is created in view/layout/main_style.php
'layout' => 'main_style'
Using this whole project layout changed
I'm working with yii framework I have installed the yii booster extensions and I work with vagrant. My friend also works on this project, however the problem is that the application doesn't use the correct CSS. Instead, it uses a CSS saved in cache.
Here how it is: There is a folder at: www\SVN\wwwroot\public\assets
it contains some folders with weird names, one of them contains all the bootstrap CSS and everything belonging to bootstrap. This is wrong because this art is regenerated every-time I regenerate vagrant. The problem is I am using the correct CSS unless I do a (delete cookie cash) sometimes I get the correct CSS sometimes I get the wrong CSS, but all the other people using this they get the wrong CSS, unless I change it for them manually on assests folder, which is totally wrong because every time I update my workstation using svn it should apply the new lay out to other prople as well but it doesn't work.
Here is my main config:
<?php
/**
* This is the main Web application configuration.
*
* Any writable CWebApplication properties can be configured here.
* It is constructed the following way:
* main.php = return the main settings
* unless overwritten by the local main settings if available
* unless overwritten by the test settings if available
* unless overwritten by the local test settings if available
* (mergeArray: latter will overwrite the former, see http://www.yiiframework.com/doc/api/1.1/CMap#mergeArray-detail)
*
* #author Yii, adapted by Robbert <Paulussen#Momentum-Technologies.nl>
* #since release 1.0 (sprint 1)
*/
// Set up path variables to reflect the directory structure
// $WEBHOME/ -- doePath // = wwwroot
// $WEBHOME/public/ -- webrootPath
// $WEBHOME/private/protected/ -- protectedPath
// $WEBHOME/private/runtime/ -- runtimePath
$pathToDoeDirectory = realpath(dirname(__FILE__) . '/../../..'); // = wwwroot
$privatePath = $pathToDoeDirectory . '/private/';
$protectedPath = $pathToDoeDirectory . '/private/protected/';
$runtimePath = $pathToDoeDirectory . '/private/runtime/';
$publicPath = $pathToDoeDirectory . '/public/';
$webrootPath = $publicPath;
$vendorPath = '/vagrant/vendor/';
/**
* Namespace MTE
*/
Yii::setPathOfAlias('MTE', $protectedPath);
// used by the themeUrl of widgetFactory settings, in case the DOE is in a subdirectory
$baseUrl = (isset($_SERVER['DOCUMENT_ROOT'])) ? str_replace($_SERVER['DOCUMENT_ROOT'], '', realpath('.')) : '';
//define('EOL','<br/>');
//echo '$pathToCcsDirectory = ' . $pathToCcsDirectory . PHP_EOL;
//echo '$privatePath = ' . $privatePath . PHP_EOL;
//echo '$protectedPath = ' . $protectedPath . PHP_EOL;
//echo '$runtimePath = ' . $runtimePath . PHP_EOL;
//echo '$publicPath = ' . $publicPath . PHP_EOL;
//echo '$webrootPath = ' . $webrootPath . PHP_EOL;
/** the following defines path aliases using: Yii::setPathOfAlias('local','path/to/local-folder');
* usage e.g. ... Yii::getPathOfAlias('runtimePath') ...
*/
Yii::setPathOfAlias('doePath', $pathToDoeDirectory);
Yii::setPathOfAlias('privatePath', $privatePath);
Yii::setPathOfAlias('publicPath', $publicPath);
Yii::setPathOfAlias('protectedPath', $protectedPath);
Yii::setPathOfAlias('runtimePath', $runtimePath);
Yii::setPathOfAlias('webrootPath', $webrootPath);
Yii::setPathOfAlias('vendorPath', $vendorPath);
Yii::setPathOfAlias('booster', $vendorPath . 'clevertech/yii-booster/src/'); // a twitter bootstrap library
//Yii::setPathOfAlias('booster', $publicPath . 'css/yii-booster/src/'); // a twitter bootstrap library
$config_database = require(dirname(__FILE__) . '/database.php');
$config_main = array(
'sourceLanguage' => 'en', // for i18N
'timeZone' => 'Europe/Amsterdam',
'basePath' => $protectedPath,
// override the default of Yii
'runtimePath' => $runtimePath,
'name' => Yii::t('systemwide', 'DOEN - DOssier opvolg- EN actiesysteem'),
//'theme'=>'bootstrap',
'preload' => array(
'log',
'translate', // for i18N
'booster', //Yii-Booster, a twitter bootstrap library
),
'behaviors' => array(
'onBeginRequest' => array(
'class' => 'application.components.modulesloader',),
), // for i18N
// autoloading model and component classes, Note that importing a directory does not import any of its subdirectories!
'import' => array(
'application.components.*',
'application.models.*',
'application.modules.rights.*',
'application.modules.rights.components.*',
'application.modules.translate.TranslateModule',
'booster.helpers.TbHtml',
'booster.helpers.TbArray',
'booster.behaviors.TbWidget',
'booster.widgets.*'
),
'modules' => array(
'rights' => array(
'install' => false, // Whether to install rights.
'userNameColumn' => 'login', // Name of the user name column in the database.
'userClass' => 'RightsModuleUser', // extended User model
'cssFile' => '/MTE/modules/rights/default.css', // custom css for rights module
'superuserName' => 'MTeAdmin', // doe_user.login of the user with super user privileges. Default 'Admin'
/* more options */
// 'appLayout' => 'application.views.layouts.main', // Application layout.
// 'authenticatedName' => 'Authenticated', // Name of the authenticated user role.
// 'baseUrl' => '/rights', // Base URL for Rights. Change if module is nested.
// 'debug' => false, // Whether to enable debug mode.
// 'displayDescription' => true, // Whether to use item description instead of name.
// 'enableBizRule' => true, // Whether to enable authorization item business rules.
// 'enableBizRuleData' => false, // Whether to enable data for business rules.
// 'flashErrorKey' => 'RightsError', // Key to use for setting error flash messages.
// 'flashSuccessKey' => 'RightsSuccess', // Key to use for setting success flash messages.
// 'layout' => 'rights.views.layouts.main', // Layout to use for displaying Rights.
// 'userIdColumn' => 'id', // Name of the user id column in the database.
),
'translate',
'components' => array(
//use component to store the cookies
'Cookies' => array(
'class' => 'application.components.CookiesHelper'
),
// uncomment the following to enable URLs in path-format
'urlManager' => array(
'urlFormat' => 'path',
'showScriptName' => false,
'rules' => array(
'<controller:\w+>/<id:\d+>' => '<controller>/view',
'<controller:\w+>/<action:\w+>/<id:\d+>' => '<controller>/<action>',
'<controller:\w+>/<action:\w+>' => '<controller>/<action>',
),
),
'errorHandler' => array(
// use 'site/error' action to display errors
'errorAction' => 'site/error',
),
'log' => array(
'class' => 'CLogRouter',
'routes' => array(
array(
'class' => 'CFileLogRoute',
'levels' => 'info, warning, error',
),
),
),
),
),
// application components
'components' => array(
// this class is used to simplify template actions
'TemplateHelper' => array(
'class' => 'application.components.TemplateHelper',
),
/* i18N - begin */
'messages' => array(
'class' => 'CDbMessageSource',
'onMissingTranslation' => array('TranslateModule',
'missingTranslation',
),
),
'translate' => array(
'class' => 'translate.components.MPTranslate',
'acceptedLanguages' => array(
'en' => 'English',
'nl' => 'Nederlands',
),
),
/* i18N - end */
'authManager' => array(
'class' => 'RDbAuthManager',
'connectionID' => 'db',
'defaultRoles' => array('authenticated', 'user'),
),
'user' => array(
'class' => 'WebUser',
/* enable cookie-based authentication */
'allowAutoLogin' => true,
/* #see http://www.yiiframework.com/doc/guide/1.1/en/topics.auth */
'loginUrl' => array('/site/login'),
),
'booster' => array(
'class' => 'booster.components.Bootstrap',
'coreCss' => true,
'responsiveCss' => true,
'yiiCss' => true,
'minify' => true,
),
),
/** application-level parameters that can be accessed
* using Yii::app()->params['paramName']
*/
'params' => array(
// this is used in contact page
'adminEmail' => 'beheer#momentum-technologies.nl',
'cookie_duration' => 3600 * 24 * 30,
'composer.callbacks' => array(
// args for Yii command runner
'yiisoft/yii-install' => array('yiic', 'webapp', dirname(__FILE__) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..'),
'post-update' => array('yiic', 'migrate'),
'post-install' => array('yiic', 'migrate'),
),
),
);
$mainDbIncluded = CMap::mergeArray($config_database, $config_main);
// include and merge local main config if it exists
if (file_exists(dirname(__FILE__) . '/main-local.php'))
{
return CMap::mergeArray($mainDbIncluded, include(dirname(__FILE__) . '/main-local.php'));
}
// otherwise just load the main config file
return $mainDbIncluded;
As you can see I have defined my CSS path to be:
Yii::setPathOfAlias('booster', $vendorPath . 'clevertech/yii-booster/src/'); // a twitter bootstrap library
here is my header.php that goe wrong:
<?php
$lang = Yii::app()->getLanguage();
if (empty($lang))
{
$lang = 'en';
}
?>
<!DOCTYPE html>
<html lang="<?php echo $lang; ?>">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" type="text/css" href="<?php echo Yii::app()->request->baseUrl; ?>/css/screen.css" media="screen, projection" />
<link rel="stylesheet" type="text/css" href="<?php echo Yii::app()->request->baseUrl; ?>/css/main.css" />
<link rel="stylesheet" type="text/css" href="<?php echo Yii::app()->request->baseUrl; ?>/css/widgets/jui.tabs.css" />
<link rel="stylesheet" type="text/css" href="<?php echo Yii::app()->baseUrl; ?>/css/common.css" />
<?php
Yii::app()->clientScript->registerCoreScript('jquery');
Yii::app()->clientScript->registerScriptFile(Yii::app()->baseUrl . '/js/common.js');
?>
<title><?php echo CHtml::encode($this->pageTitle); ?></title>
<link rel="stylesheet" type="text/css" href="<?php echo Yii::app()->request->baseUrl; ?>/css/widgets/jui.tabs.css" />
</head>
<body>
<div id="header">
<?php
$this->widget('booster.widgets.TbNavbar', array(
'brand' => '<img src="' . Yii::app()->request->baseUrl . '/images/logo_mte.png" alt="" />' ,
'brandUrl' => '#',
'collapse' => true,
'type' => null,
'items' => array(
'brand' => Yii::App()->name ,
array(
'class' => 'booster.widgets.TbMenu',
'items' => array(
array('label' => 'Login', 'url' => array('/site/login'), 'visible' => Yii::app()->user->isGuest),
array('label' => 'Logout (' . Yii::app()->user->name . ')', 'url' => array('/site/logout'), 'visible' => !Yii::app()->user->isGuest)
),
),
)));
?>
</div>
<div id="ajaxLoading">
<!--<img src="../public/images/ajax-loader.gif" alt="Loading..."/>-->
</div>
an when I look at my inspect element in chrome this is what I see:
as you can see it is generated in assets. but I dont want it to be like this how can I fix that?
But it doesn't use this one and instead, it uses an incorrect version. Can someone help me out with this? Maybe I am getting this wrong and the problem is from something else. Thanks
I experienced many CSS issues when working with the Booster extension before, re-installing it following those steps fixed them for me at that time:
Get YiiBoilerplate
and unzip it somewhere, it's created by the same guys at clevertech
and using the booster extension by default.
Go to {unzipped}backend/views/layouts/ and grab main.php,
column1.php and column2.php
create a new theme in your webapp under the /themes folder (I called
it 'booster')
Copy the three files from (3) into themes/booster/views/layouts In
your main.php add 'theme' => 'booster' as a top-level entry of the
array (I put it first)
That was #TeacherT solution that worked out for me after posting this Stackoverflow question, other solutions has came out later and seemed to solve the CSS issues to other users, so you may try them too.
I found a similar topic How to create modular MVC components in Zend Framework but it's about ZF1, and I wanted to know, maybe ZF2 has more convinient ways to implement widgets?
For example, I need to display Featured Products block on several pages but without duplicating the code.
You can do this with child layouts and partials.
You will need to add a line like to your layout (called my-layout.phtml in my example):
my-layout.phtml
<?php echo $this->featuredProducts; ?>
Then in your controller you can do:
$view = new ViewModel();
$featuredProductsView = new ViewModel(array('products' => $products));
$featuredProductsView->setTemplate('partial/featured-products');
$view->addChild($featuredProductsView, 'featuredProducts');
return $view;
This assume you have some config entries like:
'view_manager' => array(
'template_map' => array(
'layout/layout' => __DIR__ . '/../view/layout/my-layout.phtml',
'partial/featured-products' => __DIR__ . '/../view/products/partial/featured-products.phtml',
'template_path_stack' => array(
'expert' => __DIR__ . '/../view',
),
),
Then you would probably want to wrap this up into a controller plugin or something maybe
I would like to make navigation buttons in my view, for example index.phtml but it's not working. I did know how to do it in Zend1 but in Zend2 I have a problem. My code looks like this (file index.phtml):
$container = new \Zend\Navigation\Navigation($tableActions);
var_dump($container);
echo '<div class="table-column">';
echo $this->navigation($container)->menu();
echo '</div>';
Variable $tableAction looks like this:
public $tableActions = array(
array(
'label' => 'On/Off',
'module' => 'import',
'controller' => 'import',
'action' => 'setstatus',
'params' => array('id' => null),
),
);
I did not get any error, just whole site die on this line. var_dump returns object(Zend\Navigation\Navigation) so it's fine so far. Problem is, how to show it...
The navigation pages have dependencies which aren't being met by just creating a new container class in a view. The Mvc page needs a RouteStackInterface (Router) instance and a RouteMatch instance. Similarly Uri pages need the current Request instance.
You can see this clearly if you take a look at the Zend\Navigation\Service\AbstractNavigationFactory and its preparePages and injectComponents methods.
The view is not the right place to be instantiating menus, instead put the menu configuration spec in your module.config.php...
<?php
return array(
'navigation' => array(
'table_actions' => array(
array(
'label' => 'On/Off',
'module' => 'import',
'controller' => 'import',
'action' => 'setstatus',
'params' => array('id' => null),
),
),
),
);
Write a factory extending the AbstractNavigationFactory class and implement the getName() method which returns the name of your menu spec key (table_actions in this example)
<?php
namespace Application\Navigation\Service;
use Zend\Navigation\Service\AbstractNavigationFactory;
class TableActionsFactory extends AbstractNavigationFactory
{
/**
* #return string
*/
protected function getName()
{
return 'table_actions';
}
}
Map the factory to a service name in the service_manager spec of module.config.php ...
<?php
return array(
'navigation' => array(// as above ... )
'service_manager' => array(
'factories' => array(
'TableActionsMenu' => 'Application\Navigation\Service\TableActionsFactory',
),
),
);
Now you can call the view helper using the service name TableActionsMenu you just mapped
<div class="table-column">
<?php echo $this->navigation('TableActionsMenu')->menu(); ?>
</div>
Finally, if, as I suspect, you need to change an attribute of the page depending on the view, you can do that too, navigation containers have find* methods which can be accessed from the navigation helper and used to retrieve pages.
Here's an example looking for the page with a matching page label, then changing it before rendering (obviously not an ideal search param, but it gives you the idea)
$page = $this->navigation('TableActionsMenu')->findOneByLabel('On/Off');
$page->setLabel('Off/On');
// and then render ...
echo $this->navigation('TableActionsMenu')->menu();
I need to use autoloading for my custom classes in Zend Framework 2.0. My custom library located in /vendor/Garvey/library/Garvey. I have a simple extended AbstractTable class in /vendor/Garvey/library/Garvey/Db/Table/AbstractTable.php:
<?php
namespace Garvey\Db\Table;
use Zend\Db\Table\AbstractTable;
abstract class AbstractTable extends AbstractTable
{
public function getItemById($id)
{
}
}
In the index.php I have the following code:
require_once 'vendor/ZendFramework/library/Zend/Loader/AutoloaderFactory.php';
Zend\Loader\AutoloaderFactory::factory(array('Zend\Loader\StandardAutoloader' => array(
'prefixes' => array(
'Garvey' => 'vendor/Garvey/library/Garvey',
)
)));
But I have the following error. What I have missed?
Fatal error: Class 'Garvey\Db\Table\AbstractTable' not found
Thank you in advance.
Your original index.php would also worked if you changed the 'prefixes' key to 'namespaces' and specify path like below:
Zend\Loader\AutoloaderFactory::factory(array('Zend\Loader\StandardAutoloader' => array(
'namespaces' => array(
'Garvey' => dirname(__DIR__) . '/vendor/Garvey',
)
)));
Or you can defime method in Module.php
public function getAutoloaderConfig()
{
$return = array(
'Zend\Loader\ClassMapAutoloader' => array(
__DIR__ . '/autoload_classmap.php'
),
'Zend\Loader\StandardAutoloader' => array(
'namespaces' => array(
__NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
'Garvey' => __DIR__ . '/../../vendor/Garvey/library/Garvey',
)
)
);
}
But I would not recommend it. Since ZF2 purpose all centered about speed in autoloading the best way is to use class_map style to load your classes. It will work much quicker at the end but require additional work. You can to register every class in you class_map file.
You can create class_map.php in the root of your library and place there
<?php
return array(
'Garvey\Db\Table\AbstractTable' => __DIR__ . '/Garvey/Db/Table/AbstractTable.php',
);
And add there as many classes as you use. And in getAutoloaderConfig() you can add you classmap
public function getAutoloaderConfig()
{
$return = array(
'Zend\Loader\ClassMapAutoloader' => array(
__DIR__ . '/autoload_classmap.php',
__DIR__ . '/../../vendor/Garvey/library/Garvey/class_map.php',
),
'Zend\Loader\StandardAutoloader' => array(
'namespaces' => array(
__NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
)
)
);
}
Matthew Weier O'Phinney explains in this video that there are now 3 methods for autoloading :
ZF1-style include_path autoloader ( old zf1 method, not recommended )
Per-namespace/prefix autoloading ( new zf2 method, better )
Class-map autoloading ( recommended and the fastest )
A class-map generator utility is mentioned in the docs that will take care of writing the /vendor/vendor_name/library/autoload_classmap.php for you.
The solution you found is similar to the one Matthew mentions in the video for the Per-namespace/prefix autoloading. Following the code structure in ZendSkeletonApplication, that code would go in the /init_autoloader.php file, rather than in the /public/index.php file.
I have found the answer. Put this in your index.php:
require_once 'vendor/ZendFramework/library/Zend/Loader/StandardAutoloader.php';
$loader = new Zend\Loader\StandardAutoloader();
$loader->registerNamespace('Garvey', realpath('vendor/Garvey/library/Garvey'));
$loader->register();
Have a quick look at this post.
Now next step is add some code into our custom library.
First of all open a file ./vendor/Garvey/autoload_classmap.php
return array(
'Garvey\Module' => __DIR__ . '/Module.php',
'Garvey\Db\Table' => __DIR__ . '/library/Garvey/Db/Table/AbstractTable.php',
)
Next is ./vendor/Garvey/Module.php
namespace Garvey;
use Zend\ModuleManager\Feature\AutoloaderProviderInterface;
class Module implements AutoloaderProviderInterface
{
public function getAutoloaderConfig()
{
return array(
'Zend\Loader\ClassMapAutoloader' => array(
__DIR__ . '/autoload_classmap.php',
),
'Zend\Loader\StandardAutoloader' => array(
'namespaces' => array(
__NAMESPACE__ => __DIR__ . '/library/' . __NAMESPACE__,
),
),
);
}
}
Now inside your library create a file inside a folder:
./vendor/Kdecom/library/Kdecom/Db/Table/AbstractTable.php
One final thing that we need to do which is add this library into your application.config.php file.
So your application.config.php file will looks something like this way...
return array(
'modules' => array(
'Application',
'Garvey'
),
'module_listener_options' => array(
'config_glob_paths' => array(
'config/autoload/{,*.}{global,local}.php',
),
'module_paths' => array(
'./module',
'./vendor',
),
),
);