Get Loaded Config In Controller - zend-framework

How do i get the already loaded options in the controller file in a zend framework installation without creating a new Zend_Config([ ** ]); instance.

Once Zend_Application reads application.ini, the values are stored in bootstrap.
You may access them anywhere, without accessing the disk, or using the registry:
$front = Zend_Controller_Front::getInstance();
$bootstrap = $front->getParam('bootstrap');
if (null === $bootstrap) {
throw new My_Exception('Unable to find bootstrap');
}
$options = $bootstrap->getOptions();
In the controller you may also use $this->getInvokeArg('bootstrap');

I am not sure at all what you are asking but are you asking how to use configs set in application.ini from a controller? If so you should load that config in Zend_Registry in your bootstrap and then retrieve it in your controller.
So in bootstrap.php
protected function _initConfig() {
$config = new Zend_Config_Ini("../application/configs/application.ini");
Zend_Registry::set('config', $config);
}
The in your Controller
$myConfig = Zend_Registry::get('config');

Related

Default_Bootstrap overrides Admin_Bootstrap

In the Admin module installation Layout and Navigation of Default module
application/modules/default/Bottstrap.php
<?php
class Default_Bootstrap extends Zend_Application_Module_Bootstrap
{
protected function _initNavigation()
{
$layout = Zend_Layout::startMvc()->setLayout('layout');
$config = new Zend_Config_Xml(APPLICATION_PATH.'/configs/navigation.xml','nav');
$navigation = new Zend_Navigation($config);
Zend_Registry::set('Zend_Navigation', $navigation);
}
}
application/modules/admin/Bottstrap.php
<?php
class Admin_Bootstrap extends Zend_Application_Module_Bootstrap
{
protected function _initNavigation()
{
$layout = Zend_Layout::startMvc()->setLayout('admin');
$config = new Zend_Config_Xml(APPLICATION_PATH.'/configs/navadmin.xml','nav');
$navigation = new Zend_Navigation($config);
Zend_Registry::set('Zend_Navigation', $navigation);
}
}
application/configs/application.ini
;Modules
resources.frontController.moduleDirectory = APPLICATION_PATH "/modules"
resources.frontController.defaultModule = "default"
resources.modules[] =
resources.frontController.actionhelperpaths.Default_Controller_Helper = APPLICATION_PATH "/modules/default/controllers/helpers"
;Layout
resources.layout.layoutpath = APPLICATION_PATH "/layouts"
;View
resources.view.doctype = "HTML5"
resources.view.encoding = "UTF-8"
resources.view.contentType = "text/html; charset=UTF-8"
In a single-module application, layout and navigation are typically initialized in the single app-level bootstrap (sometimes by reference to an application resource plugin).
However, in a multi-module application, all the module bootstraps will run. Therefore, the last one that runs ends up overriding all the others.
For these types of tasks that depend upon knowing which module has been requested, you can use a front-controller plugin with routeShutdown() hook. Each module X could register its own plugins for navigation and layout that check if the requested module matches X. If not, bail early. If so, perform your initialization.
See MWOP's article on the subject of module bootstrapping for more details:
http://mwop.net/blog/234-Module-Bootstraps-in-Zend-Framework-Dos-and-Donts
a technique of loading a program into a computer by means of a few initial instructions which enable the introduction of the rest of the program from an input device.
start up (an Internet-based business or other enterprise) with minimal financial resources.

Zend framework and Ext-Js4, file and folder structure

I am trying to use Zend Frame work and Ext-Js4 together.
But I don't know how to setup file and folder structure correctly.
I setup like this,
And in application/controllers/IndexController.php
$this->view->headScript()->appendFile('/js/ext-4.0.7/ext-all.js','text/javascript');
$this->view->headScript()->appendFile('/js/app.js','text/javascript');
$this->view->headLink()->appendStylesheet('/js/ext-4.0.7/resources/css/ext-all.css');
Is it right structure? anyone has a better idea?
Thank you.
If you're using Ext-Js4 in your entire application, a better idea would be to add this in your bootstap, so that you don't have to include your javascript paths in every controllers.
protected function _initView()
{
$view = new Zend_View();
$view->headScript()->appendFile('/js/ext-4.0.7/ext-all.js','text/javascript');
$view->headScript()->appendFile('/js/app.js','text/javascript');
$view->headLink()->appendStylesheet('/js/ext-4.0.7/resources/css/ext-all.css');
$viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('ViewRenderer');
$viewRenderer->setView($view);
return $view;
}
I tend to use a layout for things like this:
function _initViewHelpers()
{
$this->bootstrap('layout');
$layout = $this->getResource('layout');
$view = $layout->getView();
$view->doctype('HTML4_STRICT');
$view->headMeta()->appendHttpEquiv('Content-type', 'text/html;charset=utf-8')
->appendName('description', 'My App');
$view->headTitle()->setSeparator(' - ')
->headTitle('My App');
}
Then in my application.ini file I include:
resources.view[] =
resources.layout.layoutPath = APPLICATION_PATH "/layouts
There are always more ways to skin the proverbial cat!

Zend Framework Bootstrap Issue

I have been working on a new installation of a Zend Framework application for a while now, and I cannot figure out what's going on. I have two custom action helpers I would like to use and I would like to initialize those in the bootstrap. But it seems as though my _init functions are not being called at all. In the index.php that starts the application I have:
require('Zend/Application.php');
$app = new Zend_Application(APPLICATION_ENV, APPLICATION_PATH
.'/configs/application.ini');
$app->bootstrap()->run();
Here's what I have in the application.ini file:
[production]
appnamespace = "Application_Name"
includePaths.library = APPLICATION_PATH "/../library"
bootstrap.path = "/home/user/website/includes/library/Application_Name/Resource/Bootstrap.php"
bootstrap.class = "Bootstrap"
resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts"
resources.view[] =
autoloaderNamespaces[] = "Application_Name"
pluginPaths.Application_Name_Resource = "Application_Name/Resource"
I know the application is somewhat working because it is using a layout that I have and I can do things in the controllers and views and have it output to the page. I also know that it is at least looking at the Bootstrap file because I can make a PHP error happen when I leave out an end curly brace.
Here's a portion of my Bootstrap file:
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
public function _init()
{
Zend_Controller_Action_HelperBroker::addPrefix(new Application_Name_Controller_Action_Helper_ResourceInjector());
Zend_Controller_Action_HelperBroker::addPrefix(new Application_Name_Controller_Action_Helper_Em());
}
Any ideas why this would be or see something that I've messed up in my configuration? I've looked at tens of tutorials on how to configure Zend, and no one else seems to have this problem.
You're not using the helper broker correctly. addPrefix() is used to add pluginloader prefix paths, not actual classes.
If you want to add concrete helpers (to use their dispatch hooks presumably), then place something like this in your Bootstrap class
protected function _initActionHelpers()
{
$helper = new My_Helper;
Zend_Controller_Action_HelperBroker::addHelper($helper);
}
For regular, runtime helpers, you can easily add prefix paths in your config, eg
resources.frontController.actionHelperPaths.ProEquipTrack_Controller_Action_Helper = "ProEquipTrack/Controller/Action/Helper"
These will be automatically loaded by the broker at call time, eg (controller context)
$resourceInjector = $this->getHelper('ResourceInjector');
$em = $this->getHelper('Em');
or using the strategy pattern (direct() method)
$this->_helper->resourceInjector($arg1, $arg2 /*, etc */);
Doctrine Entity Manager
Do something like this in your Bootstrap class
protected function _initDoctrine()
{
// initialise and create entity manager
$em = // whatever
return $em;
}
You can now access the entity manager in your controllers using this
$em = $this->getInvokeArg('bootstrap')
->getResource('doctrine');

Zend Layout - A "Smart" layout selector

I currently have Zend setup to look for a layout script in each module's view/scripts/layout.phtml file (ie: /application/modules/moduleName/scripts/layout.phtml). This is by setting layout[] to nothing (blank) in the application.ini file (resources.layout[] = )
The issue is that many modules may share the same layout. I don't want to copy the same exact layout into each module that uses it. I know I can set everything to use one layout script by setting a specific path like resources.layout.layoutpath = /layoutPath and everything would use /layoutpath/layout.phtml, and I know I can set individual pages (or whole Controllers, in the init) by using $this->_helper->layout->setLayout('foobaz');
The issue is that some modules will have different layouts, other than the 'standard' one, and I don't want to set it on a by Controller or by Action basis. I want to set it for the entire module, set in one place (or intuitively figured out by code/Zend automatically). Ideally, it would be setup how it is currently, but if a module doesn't have its own layout.phtml, it would use the default module's layout.
So... how do I do it?
There are several solutions, choose their own strategy
1 extending the action controller
class App_Controller_Action extends Zend_Controller_Action
{
public function init()
{
parent::init();
$moduleName = $this->getRequest()->getModuleName();
$layoutPath = APPLICATION_PATH . '/modules/' . $moduleName . '/layouts';
if (is_dir($layoutPath)) {
$this->view->addScriptPath($layoutPath);
}
}
}
and then do as usual IndexController extends App_Controller_Action ...
if layout file exists in APPLICATION_PATH . '/modules/' . $moduleName . '/layouts' directory - it will ne used instead of default layout
2 you can write frontcontroller plugin
class App_Controller_Plugin_ModuleSwitcher extends Zend_Controller_Plugin_Abstract
{
protected $_view = null;
public function routeShutdown(Zend_Controller_Request_Abstract $request)
{
$moduleName = $request->getModuleName();
Zend_Layout::startMvc();
$layout = Zend_Layout::getMvcInstance();
$layout->setLayoutPath(APPLICATION_PATH . '/modules/' . $moduleName . '/layouts')->setLayout($moduleName);
return $request;
}
}
and dont forget to google for another solutions ;)
you can set own layout selector in few steps
step 1:
make module admin and default.
step 2:
create layout folder in each module as admin/layouts/scripts
and default/layouts/scripts
put into layout.phtml
step 3:
delete the layout.phtml file from Application/layouts/scripts.
step 4:
make the the Plugin folder inside library and make Plugin.php
as
class Plugin_Layout extends Zend_Controller_Plugin_Abstract
{
public function preDispatch(Zend_Controller_Request_Abstract $request)
{
$layoutPath = APPLICATION_PATH . '/modules/' . $request->getModuleName() . '/layouts/scripts/';
Zend_Layout::getMvcInstance()->setLayoutPath($layoutPath);
}
}
step 5:
open Application/configs/Appication.ini file
and edit it
as
;resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts/"
resources.layout.layout = "layout"
;register your plugin
autoloaderNamespaces[] = "Plugin"
resources.frontController.plugins[] = "Plugin_Layout"
Step 6:
open bootstrap file Application/Bootstrap
put the code inside
protected function _initAutoload()
{
$loader = new Zend_Application_Module_Autoloader(array(
'namespace' => '',
'basePath' => APPLICATION_PATH . '/modules/'
));
return $loader;
}
protected function _initPlugins()
{
$this->bootstrap('frontcontroller');
$fc = $this->getResource('frontcontroller');
$fc->registerPlugin(new Plugin_Layout());
}
The quickest solution might be to create a symlink to point what would be a module layout file to the default layout. This won't work on Windows and is harder to maintain.
Better, create a method in your Bootstrap to set the layout.
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
public function _initLayoutScript(){
//ensure layout is setup
$this->bootstrap(array('layout', 'FrontController'));
$layout= $this->getResource('layout');
$front = $this->getResource('FrontController');
//do something with $layout and $front - set layout script/path etc based on request
//You could use file_exists to detect module layout scripts
}
}
See http://framework.zend.com/manual/en/zend.application.quick-start.html#zend.application.quick-start.resources for more details.
Finally, you could write your own application resource for use with Zend_Application.

Registering Zend Database Adapter in Registry

I am looking to register a reference to the main Database Adapter in the Registry during Bootstrapping so it can be used elsewhere in my site (specifically the Authorisation action).
I have implemented an ugly fix where i create a Database Table object and call the getAdapter() method on it and pass through that. However, this is a bad way of doing it and I would like it to be available via the registry.
Does anyone know how to do this? Any help or pointers in the right direction are appreciated!
I'm using Zend Framework 1.8.
If you're using Zend Framework 1.8+, and created your project with the command line tool, then it's as simple as registering your database settings in your application.ini config file.
resources.db.adapter = "PDO_MYSQL"
resources.db.params.host = "your.database.host"
resources.db.params.dbname = "database_name"
resources.db.params.username = "username"
resources.db.params.password = "password"
resources.db.isDefaultTableAdapter = true
If your database settings are preceded by resources.db you won't even need to do anything in your Bootstrap.php file because it will do it for you. Also, by setting the isDefaultTableAdapter setting to true, you can get an instance of your database adapter anywhere in your application.
$dbAdapter = Zend_Db_Table::getDefaultAdapter();
$authAdapter = new Zend_Auth_Adapter_DbTable($dbAdapter);
Thanks for the replies. Ive decided to change the accepted answer and post the solution I finally used - which is insanely simple in the end!!
This is basically based on Dcaunt's comment...
In the bootstrap class..
protected function _initDb()
{
$resource = $bootstrap->getPluginResource('db');
$db = $resource->getDbAdapter();
Zend_Registry::set("db", $db);
}
Then access that elsewhere with...
$dbAdapter = Zend_Registry::get("db");
Thanks for the help and hopefully this helps someone else.
Your missing the best thing :)
If you use the Zend_Db_Table models (you should be) etc then you can set up a default adaptor - this way when you instantiate a model the DB connection it taken care off - this way you dont really need to save it in the registry or bother about connection before running a query through the model.
I do save it in the registry for later use if needed though - but I may remove this
protected function _initDB()
{
// Check that the config contains the correct database array.
if ($this->_config->db) {
// Instantiate the DB factory
$dbAdapter = Zend_Db::factory($this->_config->db);
// Set the DB Table default adaptor for auto connection in the models
Zend_Db_Table::setDefaultAdapter($dbAdapter);
// Add the DB Adaptor to the registry if we need to call it outside of the modules.
Zend_Registry::set('dbAdapter', $dbAdapter);
}
}
My 2 cents...
How to grab the default DB Adapter:
From Bootstrap:
<?php
$dbResource = $this->getPluginResource('db');
db = $dbResource->getDbAdapter();
var_dump($db);
?>
From a Controller there are two methods:
<?php
// Method 1
$bootstrap = $this->getInvokeArg('bootstrap');
$dbResource = $bootstrap->getPluginResource('db');
$dbAdapter = $dbResource->getDbAdapter();
var_dump($dbAdapter);
// Method 2
$dbAdapter = Zend_Db_Table::getDefaultAdapter();
var_dump($dbAdapter);
?>
Check the zend-documentation at :
15.5.3.3. Storing a Database Adapter in the Registry
http://framework.zend.com/manual/en/zend.db.table.html
$db = Zend_Db::factory('PDO_MYSQL', $options);
Zend_Registry::set('my_db', $db);
// Later...
$table = new Bugs(array('db' => 'my_db'));
something like that you're looking for?
Edit:
to load your configuration from an ini-file, use:
parse_ini_file($inifile)
;configuration.ini
host = 127.0.0.1
user = username
password = blabla
;yourfile.php
$options = parse_ini_file('configuration.ini');
$db = Zend_Db::factory('PDO_MYSQL', $options);
I have a method in my bootstrap to add the adapter to the registry. I'd prefer a cleaner solution, but it works:
protected function _initRegistry(){
$this->bootstrap('db');
$db = $this->getResource('db');
$db->setFetchMode(Zend_Db::FETCH_OBJ);
Zend_Registry::set('db', $db);
}
Here is what i do:
Inside the bootstrap:
define('CONFIG_FILE', '../config/general.ini');
define('APP_MODE', 'development');
Inside the Initializer:
/**
* Initialize data bases
*
* #return void
*/
public function initDb ()
{
$options = Zend_Registry::get('conf');
$db = Zend_Db::factory($options->database);
$db->query(new Zend_Db_Expr('SET NAMES utf8'));
Zend_Registry::set('db', $db);
}
public function initConfig ()
{
if (file_exists(CONFIG_FILE) && is_readable(CONFIG_FILE)) {
$conf = new Zend_Config_Ini(CONFIG_FILE, APP_MODE);
Zend_Registry::set('conf', $conf);
} else {
throw new Zend_Config_Exception('Unable to load config file');
}
}
And finaly my config file looks like this:
[production]
database.adapter = pdo_Mysql
database.params.host = db.example.com
database.params.username = dbuser
database.params.password = secret
database.params.dbname = dbname
; Overloaded configuration from production
[development : production]
database.params.host = localhost
database.params.username = root
database.params.password =
Take a look at:
Zend_Db::Factory()
Zend_Config_Ini
Zend_Registry
If you are using Zend Framework 1.8 just do something like this in your controller/action:
class CreateorderController extends Zend_Controller_Action
{
public function testAction()
{
//more code
$users_obj = new Default_Model_Users(); //this would load the model using the Default namespace
//more code
}
}
My Defaul_Model_Users class would look something like this:
<?php
/**
* application/models/Users.php
*/
class Default_Model_Users extends Zend_Db_Table
{
protected $_table;
public function getTable()
{
if(null === $this->_table) {
$this->_table = new Default_Model_DbTable_Users();
}
return $this->_table;
}
public function fetchAll()
{
$result = $this->getTable()->fetchAll();
return $result;
}
}
And the part of the model which "interacts" directly with the database tables is found inside DbTable directory will look like this:
<?php
/**
* application/models/DbTable/Users.php
*/
class Default_Model_DbTable_Users extends Zend_Db_Table_Abstract
{
/** Table name */
protected $_name = 'users';
public function init()
{
$this->_db->setFetchMode(Zend_Db::FETCH_OBJ);
}
}
Then I would have the same application.ini generated by Zend Framework with this small addition:
resources.db.adapter = "PDO_MYSQL"
resources.db.params.host = "localhost"
resources.db.params.dbname = "mydb"
resources.db.params.username = "root"
resources.db.params.password = "password"
That is how I did without without having to change the bootstrap files.
I didn't want to use the registry to store an object that I should be able to access, so I did a little digging. It turns out that the bootstrap is registered as the front controller parameter "bootstrap", which is accessible from any of your controllers as explained in this manual page for Zend_Application.
So in your controller classes you can get the db adapter that has been defined in your ini file like this:
$bootstrap = $this->getInvokeArg('bootstrap');
$resource = $bootstrap->getPluginResource('db');
$db = $resource->getDbAdapter();