I'm using the default Zend_Application design pattern which loads a zend config ini file automatically in the application bootstrap and I need to ini file's variables across many models and controllers.
Right now, I'm solving it by settings the config object as a key into Zend_Registry:
protected function _initConfig()
{
$config = new Zend_Config($this->getOptions());
Zend_Registry::set('config', $config);
}
Generally, I don't like using Zend_Registry, as it doesn't offer code auto complete in my IDE, and it's hard to keep track on what I have in the registry namespace.
Is there another way to access the Zend_Application's config ini?
In a controller you should be able to do:
$this->getInvokeArg('bootstrap')->getOptions();
to access the config. For models you really should be passing in the options you need. Otherwise your only choice is really the registry.
You could always initialise it as needed yourself with
$options = new Zend_Config_Ini('/path/to/config.ini',
'config');
Wich is pretty much what the bootstrap does for you. Then you would have autocomplete on $options. But you would have to initialise it everytime you need it.
I think modifying your code to suit autocomplete is not the greatest idea ever. But this is personnal.
If I am not mistaken with Zend Studio 8/9 (maybe 7) you DO have autocomplete even for objects returned by Zend_Registry::get().
Related
I am currently developing OpenCart extensions. I am looking through existing extensions to understand the architecture (and familiarizing MVC/PHPOO concepts).
Frequently, this line of code comes up:
$seller_email = $this->config->get('service_seller_email');
My interpretation based on reading this thread:
I understand that this is a variable assignment, where it's accessing a model (?) called config to retrieve a string called service_seller_email from the admin settings portal. However, I have tried navigating through the various MVC folders within OpenCart, and I could not find a specific config.php. Could you please correct my interpretation if it's wrong?
EDIT: To add to the confusion, the article I linked specifies that you need to load a config in a controller before using it, like $this->language->load('product/search');, but I cannot find a line such as $this->config->load('...'); or the like.
Your interpretation is incorrect. The config class is not considered as model (despite it is accessing DB directly) but as a system library class - that's why you can find it under system/library/ folder.
OpenCart has it's implementation of service locator (registry) which is used to to store the config object so that you can access it directly from anywhere (inside of OpenCart of course).
It is loaded in both index.php files (in root and under admin/) like this:
$config = new Config();
$registry->set('config', $config);
This $registry is our service locator and it is passed over to any controller in it's __construct() method. Each controller has also a magic method __get() which is responsible for retrieving objects from this $registry - take a look at abstract Controller class at system/engine/controller.php which each controller extends (and should extend).
That's why you can freely call directly
$this->config->get('some_config_key');
The first part, $this->config will fall into the __get() method passing over the 'config' value as a $key which in turn is passed over to next call
return $this->registry->get($key);
And since the config object is registered under 'config' key in our service locator, it is retrieved and returned so that we could call get('some_config_key') on it.
Now the some_config_key key is stored in DB in setting table and the config object tries to find it and get it's value (you can take a look at how this works in system/library/config.php).
Hopefully this clarifies your confusion.
Looking at the docs, it looks like the config values are stored in the setting table. The Config class itself is located in /system/library/config.php.
In admin > index.php you wil find
// Config
$config = new Config();
$registry->set('config', $config);
That's where it is initialized. The class is located in
system > library > config.php
Config loaded in system > engine >loader.php:
public function config($config) {
$this->config->load($config);
}
I was wondering if yii components are also supporting the theme feature? In my environment right now a component is only considering files within the component/views/ folder.
Now that I am also using themes it would be nice to tell the component to look for the view under the themes/themeName/ folder.
Using the method below I can work around this but it certainly doesn't feel like this is the yii-way to do it.
protected function renderContent()
{
$view = './../../../themes/'.Yii::app()->theme->name.'/views/viewName';
$this->render($view);
}
Do you know of a more elegant solution to achieve this?
There isn't any theming on components. Mainly because they're not intended to be rendering content for anything. Nothing wrong with that though, sometimes it's required.
Easiest solution is probably to just make it more readable, using path aliases always helps:
protected function renderContent()
{
$view = 'webroot.themes.'.Yii::app()->theme->name.'.views.viewName';
$this->render($view);
}
Or you could add a method the component, or extend CComponent to get it across all components if you want it:
public function getViewsPath(){
return 'webroot.themes.'.Yii::app()->theme->name.'.views';
}
Or you could set a path alias:
Yii::setPathOfAlias('theme','webroot.themes.'.Yii::app()->theme->name);
Then you could use that anywhere in your application provided you run it at an early enough point in the process.
I'm a beginner in Zend Framework and I find it hard to understand their documentation.
The only PHP Framework I have used was CodeIgniter.
I am used to this method in utilizing libraries:
//load the My_Library class and assign the object to $this->myLibrary property
$this->load->library('my_Library'); //CodeIgniter way
public function index()
{
$this->my_Library->method(); //make use of the methods in the loaded library
}
So far I'm figuring out how this code works in zend, say in the bootstrap class:
protected function _initSetDoctype()
{
$doctypeHelper = new Zend_View_Helper_Doctype();
$doctypeHelper->doctype('XHTML1_STRICT');
}
And in the layout.phtml file we can put:
<?php echo $this->doctype() ?>
My question is: Since I have instantiated a new Zend_View_Helper_Doctype();
How did ZF assign $this->doctype and made this available in view?
Is there some kind of storage where these values update the view object?
I'm trying to find out how the flow works in zend so I could have a better understanding on how to make use of its resources. Sorry for my English if it's hard to understand #_#
Thank you very much!
Usually ZF uses Zend_Registry to store instances of objects that it creates. The specific example that you provided (i.e. _initSetDoctype) works, because constructor of Zend_View_Helper_Doctype will check if it is already stored in Zend_Registry or not. So, in your bootstrap, new Zend_View_Helper_Doctype() will store doctype info in a registry (because it is created for the first time), and than in the layout.phtml, the stored value in the registry will be retrieved.
Other ZF resources (or objects) such as Zend_View, Zend_Layout, are also stored and access through registry.
Off course, you can also store your own objects (or whatever) in a registry. This way, you will be able to access them in every place of you ZF app.
I'm not really sure what the best way to use global configuration options.
For example, if when a file is uploaded I want to move it in the correct folder.
I can hardcode the path, but it's not really the best thing.
I can use a CONSTANT
I can use config.ini and sets some common config options. Maybe then register a config object in Registry
How do you do? Any advice?
A Zend_Config object in the Registry is the usual method that ZF follows here. Many of the ZF classes can accept Configs, and there's pretty much no better way to deal with it within ZF.
(Just remember, the Registry pattern is little more than a glorified global anyway.)
Create a config.ini, and within it separate your configurations like so:
[development]
;File Upload settings
FileUpload.path = /some/path
[production]
;File Upload settings
FileUpload.path = /production/path
Now somewhere in your Bootstrap.php, you can do this:
$config = new Zend_Config_Ini(
self::$root . '/config/config.ini',
'development'
);
self::$registry->configuration = $config;
And in any controller:
$config = Zend_Registry::get('configuration');
echo $config->FileUpload->path;
I use Zend_Registry::set('foo', '/path/to/correct/folder') once, and then call it whenever I need it with Zend_Registry::get('foo') anytime I need it. Works great!
Just need get some vals located in application.ini(main ini) in the Controller plugin
I know I can create an instance of Zend_config_Ini but would like to use the existing resource (application.ini is already used in Front Controller)
Use Zend Registry
// when loading the config
Zend_Registry::set('config', $config);
// later, somewhere
$config = Zend_Registry::get('config');
Try:
Zend_Controller_Front::getInstance()->getParam('bootstrap')->getOptions();
If you now that you will need your configuration values from application.ini in few places around your whole application, you could read it up in bootstrap and store it in registry:
$appConfig = new Zend_Config_Ini('path/to/application.ini');
Zend_Registry::set('applicationConfig', $appConfig);
then later you can always access it:
Zend_Registry::get('applicationConfig')->someValue;
For reasons of testability and decoupling I would not use the Zend_Registry approach. In my opinion the plugin should not know anything about Zend_Config, but instead all options that are needed in the plugin should be injected from outside.
For example, if you want to use the config option "MyOption" in the Plugin Controller_Plugin_MyPlugin you could inject the needed parameters in the Bootstrap class as follows:
public function run()
{
$sopPlugin = $this->getResource('frontcontroller')->getPlugin('Controller_Plugin_MyPlugin');
$sopPlugin->setMyOption($this->getOption('MyOption'));
parent::run();
}
The advantage is that with this solution you avoid dependencies to Zend_Registry (which in fact is just an euphemism for a global variable) in your plugin code.