How to implement a site wide class and functions that can be called from anywhere in a Zend Framework Application? - zend-framework

I know there are view controllers and action controllers. I think that view helpers can be used from views and action helpers used from actions in controllers.
I need a class that at bootstrap or wherever, it initializes a number of configuration options, arrays for things like convert month numbers to their names and role numbers to their names.
How can this be achieved?

Put them in a model and use it anywhere you like by instantiating it and calling its helper methods. All model files are auto loaded whenever you call them.
Have a model Constants.php:
<?php
class Constants {
public static function convertMonth($month) {
doLogic();
return $something;
}
}
?>
In your controller or view:
Constants::convertMonth(12);

You could build a Resource Plugin and then add it to yout bootstrap class.

The Constants class or Resource approaches both work nicely. However, I recently had to undo/upgrade a Constants class based solution to meet new requirements, so you might want to consider your future plans before going down those paths.
Specifically, if you ever intend to support multiple languages, or even different words for the constants in different contexts, check out Zend_Translate API docs, Zend_Translate example, or this blog post.

Related

How to extend for bespoke classes in UI5 (not custom controls)

Using the AMD and module paradigm used by UI5, I want to use separate JS classes in distinct JS files to separate my ajax code from the related controllers.
A foundation class will be concerned with common activity such as generic error handling whilst specific classes extending from this will deal with subject-specific ajax communication only. This will NOT be a custom control so no requirement for render capability, metadata, etc.
I wish to benefit from the sap.ui.define functionality and also want my new class to be good UI5 citizen. For example I want to fire my init when the class is instantiated.
Which sapui5 class or classes should I extend from? I am currently using sap/ui/base/Object but would like to know if there is a better choice based on better performance or better fit to purpose.
I am aware of the documentation on custom controls but this seems to focus only on details of classes that render to screen.
This is the skeleton of my current approach:
sap.ui.define(['sap/ui/base/Object'],
function(BaseObject) {
"use strict";
var AjaxBase = BaseObject.extend("myAjaxBase", {
constructor: function(oControl) {
BaseObject.apply(this);
console.log("AjaxBase.constructor() fires")
}
})
AjaxBase.prototype.init = function() {
console.log("AjaxBase.init() fires")
}
return AjaxBase;
}, true)
You can use sap.ui.define even for objects which do not extend sap.ui.base.Object. So if you do not really need functionality provided by UI5 objects you are not forced to extend them. However, in your case it looks like you want to use event support and in this case it would be useful to at least extend sap.ui.base.EventProvider.
As you want to separate backend calls from your controllers it looks like you are using a JSONModel and have more complex use cases than just reads. In this case you could also extend the JSONModel with support for create, update and delete operations.

AS3 targeting controller class variable using string

I'm looking for a way of condensing some of my AS3 code to avoid almost duplicate commands.
The issue is that I have multiple variables with almost the same name e.g. frenchLanguage, englishLanguage, germanLanguage, spanishLanguage
My Controller class contains public static variables (these are accessed across multiple classes) and I need a way to be able to call a few of these variables dynamically. If the variables are in the class you are calling them from you can do this to access them dynamically:
this["spanish"+"Language"]
In AS3 it's not possible to write something like:
Controller.this["spanish"+"Language"]
Is there any way to achieve this? Although everything is working I want to be able to keep my code as minimal as possible.
It is possible to access public static properties of a class this way (assuming the class name is Controller as in your example:
Controller['propertyName']
I'm not sure how this helps to have "minimal code", but this would be a different topic/question, which might need some more details on what you want to achive.
Having said that, I like the approach DodgerThud suggests in the comments of grouping similar values in a (dynamic) Object or Dictonary and give it a proper name.
Keep in mind, that if the string you pass in as the key to the class or dynamic object is created from (textual) user input you should have some checks for the validity of that data, otherwise your programm might crash or expose other fields to the user.
It would make sense to utilize a Dictionary object for a set of variables inherited: it provides a solid logic and it happens to work...
I do not think this is what you are trying to accomplish. I may be wrong.
Classes in AS3 are always wrapped within a package - this is true whether you have compiled from Flash, Flex, Air, or any other...
Don't let Adobe confuse you. This was only done in AS3 to use Java-Based conventions. Regardless, a loosely typed language is often misunderstood, unfortunately. So:
this["SuperObject"]["SubObject"]["ObjectsMethod"][ObjectsMethodsVariable"](args..);
... is technically reliable because the compiler avoids dot notation but at runtime it will collect a lot of unnecessary data to maintain those types of calls.
If efficiency becomes an issue..
Use:
package packages {
import flash.*.*:
class This implements ISpecialInterface {
// Data Objects and Function Model
// for This Class
}
package packages {
import...
class ISpecialInterface extends IEventDispatcher

GWT Reflection loading Form

I have a circumstance where I have to create a lot of forms for an application, the forms are all located in the same package. They are named like: A11111.java, A11112.java, etc.
When the user clicks in the NavigationPane, I wish to load the form into a TabItem and display the form. The issue is I need to dynamically generate the name of the form by appending the form name to the location, such as String formName = "com.foo.appName.client.forms" + e.getData("formCode"); something like that, where e is the event of the user click.
I have looked at several Reflection methods, but you cannot pass a derived string to them. How best to do this? Several posts mention using generators, but I get lost trying to sort their logic, and none have to do with displaying forms.
Note, I am not passing any variables to the forms, or calling any methods in the form java files, also the forms are created using uibinding.
Thanks in advance
if you're aiming at lazy-loading classes via the class-loader, like you would when using the command design pattern, note that it can't be done within a GWT application, as the frameworks JRE emulation only provides a subset of types and/or methods available in the JRE, so most of the reflection API - like forName() - will not be available.
rather than lazy-loading classes, think in terms of lazy-rendering widgets to the DOM. this can be achieved by instantiating all your form classes on module load, but only render upon tab-switching. place all your render-related functionality inside onRender() callbacks and you're good to go:
public class FormItem extends TabItem {
#Override
protected void onRender(Element parent, int index) {
super.onRender(parent, index);
// render related functionality
}
}

Initiating objects in Zend Framework?

How can I eliminate to write $object = new Application_Model_Database() in every controller?
For example for an article controller, I have to type $articles = new Application_Model_Articles() for every controller. Should I put it under viewer controller, action helpers, or any other way?
Your question almost sounds like an OOP best practices question as opposed to a Zend Framework specific question. Regardless of whether or not I'm using a framework, and regardless of what framework I choose, I base when and where I create new objects on testability how many times I have to write $object = new My_Random_Object();.
Speaking specifically to the Zend Framework: Objects I'm going to use everywhere, or almost everywhere, get created in Bootstrap.php. These objects generally include a database adapter, logger, view object, and any plugins I might use. To access these across the application, I'll create private properties in the appropriate controllers and assign the objects to those properties in the controller's init() method.
class ExampleController extends Zend_Controller_Action
{
public function init()
{
$bootstrap = $this->getInvokeArg('bootstrap');
$this->_db = $bootstrap->getResource('db');
$this->_log = $bootstrap->getResource('log');
// and so on, and so forth
}
}
Ideally, models, services, daos, etc, will all be relatively tightly grouped by controller and by action. In my experience, and this is speaking generally, if I have the same model or service class showing up across all of the controllers in my application, I have an organization problem. That being said, any model that shows up in only one action gets created in that action. If it's across actions in a controller, it gets created in the init() method and assigned to a property. If it shows up across multiple controllers, it gets created in my Bootstrap.php.
(Ideally, everything gets created in the Bootstrap.php, so you can swap out that bootstrap for testing purposes. Sadly, I don't always do that, and I most often use the principles I outlined above.)
Well do you really need it in every controllers? Because that's pretty much by design. You implement models when you need them. Its not that much code really.
Now if its to be used across actions from a controller you could always:
class MyController extends Zend_Controllers{
$protected $_articleModel;
...
and in your constructor or __init() function initialize it so you can use it in every action thru $this->_articleModel
If you REALLY want it everywhere in your application just initialize it in your bootstrap and store it in the registry.
public function __initModels(){
$articles = new Application_Model_Articles()
Zend_Registry::set('articles', $articles );
}
And access it in your controllers like so:
Zend_Registry::get('articles')->fetchAll();
But then your still writing a couple of characters.
Hope this help!
IF you want to use models in the controllers you must call it..anyway some shortcuts are here
1.You can initialize it in the init section of your controller like
public function init(){
$this->object = new Application_Model_Database();
}
So that the this->object is available in all the actions of that particular controller
2.Use Zend_registry as suggested in the above answer
Another possibility is to use a Dependency Injection container, such as the Symfony DI component. It takes care of instantiating your objects, and you get some additional benefits:
Separation of concerns. You have a component devoted to create your object tree.
Easier testability of the objects.
Last, but not least, the performance benefits given by lazy instantiation (objects are created only when you ask for them). Thus, if some object is not used by the particular controller serving your request, it's not instantiated).
It's a bit more laborious than the above solutions, but much more flexible if you need to maintain and extend your application in the future.
Hope that helps,
If you are using this object to just display data in your view and are using your controller to grab the data and assign it to your view, like so:
//someControllerAction
$object = new Application_Model_Articles();
$object->fetchAll();
//assign to view
$this->view->articles = $object;
You might be better off making a view helper similar to:
//Articles.php put in /application/views/helpers
class Zend_View_Helper_Articles extends Zend_View_Helper_Abstract {
public function Articles() {
$articles = new Application_Model_Articles();
$articles->fetchAll();
//return rowset object
return $articles;
Then in your view (phtml) you could do something like:
//someView.phmtl
<?php $articles = $this->Articles(); ?>
<h1><?php echo $this->escape($articles->title); ?></h1>
<p><?php echo $this->escape($articles->body); ?></p>
building a view helper allows you to bypass the controller completely if you just need to display data from the model. This is a very simple example and can be used with partials and partialLoops.
REF:ZF reference Custom View Helper
ZF partial view helper reference

How to make a global Zend_Log with Zend_Application_Bootstrap

I would like to make a global Zend_Log object that I can reach from my Controllers and my Models.
What should I add to my Bootstrap? (My bootstrap extends Zend_Application_Bootstrap)
How then can I reach the logger object from my controller actions and from my model?
As you do with any other class - assign it to the Zend_Registy. I'd suggest setting like this:
Zend_Registry::set('Zend_Log',$logInstance);
This is a common way, which is used also for translate (set translate instance to 'Zend_Translate' and classes like forms and validators will find it automatically).
You can use Zend_Registry::get('Zend_Log')->log(...) to log anywhere you want. It's not very good from the point of architecture (you should not use normally), but for log - which can appear practically anywhere in the app from view helpers to controllers and models it's a good thing.