Running ZendServerGateway on the embedded PHP 5.4 Server

Michael Andrew Davidson writes; So you have discovered ZendServerGateway and you are like, “Wow, this makes web services easy”. However, you quickly discover that there is a little magic behind the scenes, and that this add-on works best within the context of Zend Server 6. That can be a little frustrating, especially if you or your organization does not use Zend Server 6. Never fear, there is a way around this “implied” requirement. In just a moment I will walk the reader through setting up the embedded PHP 5.4 webserver to utilize the ZendServerGateway. All the steps should easily translate to whatever environment you use for serving your PHP pages. I am going to assume a Window environment for development.

read the rest Michael Andrew Davidson’s Blog.

Zend_Config_Ini and a string

Rob Allen as usual writes useful stuff; One thing that is different between Zend_Config_Xml and Zend_Config_Ini is that with Zend_Config_Xml you can pass in an XML string as the first parameter of the constructor and it will work. This doesn’t work with Zend_Config_Ini as we use parse_ini_file() under the hood.

With PHP 5.3 however there is is a new function called parse_ini_string() which will allow us to load arbitrary ini string into Zend_Config objects. This can’t go into Zend Framework 1 though due to our PHP 5.2.4 minimum version requirement.

As I needed this for a project, I extended Zend_Config_Ini to support this feature, which means simply overloading a single method


class App_Config_Ini extends Zend_Config_Ini
{
/**
* Load the INI file from disk using parse_ini_file(). Use a private error
* handler to convert any loading errors into a Zend_Config_Exception
*
* @param string $filename
* @throws Zend_Config_Exception
* @return array
*/
protected function _parseIniFile($filename)
{
set_error_handler(array($this, '_loadFileErrorHandler'));
if (substr($filename, -4) == '.ini') {
$iniArray = parse_ini_file($filename, true);
} else {
$iniArray = parse_ini_string($filename, true);
}
restore_error_handler();

// Check if there was a error while loading file
if ($this->_loadFileErrorStr !== null) {
/**
* @see Zend_Config_Exception
*/
require_once 'Zend/Config/Exception.php';
throw new Zend_Config_Exception($this->_loadFileErrorStr);
}

return $iniArray;
}
}

The actual change is to see if the last 4 characters of the filename are “.ini” and if they aren’t then use parse_ini_string() instead of parse_ini_file(). The rest of the code is just error handling.

This is one area where I really like it when a class implements methods that done just one thing.

More at Rob Allen’s Dev notes

A Zend Framwork compound form element for dates

Rob Allen writes; A while ago I needed to ask a user for their date of birth on a Zend_Form. The design showed three separate select elements to do this:

Screen shot of a 3 select boxes for a date on a form

A little bit of googling found this site http://codecaine.co.za/posts/compound-elements-with-zend-form which has not unfortunately disappeared, so the code in this article owes a lot of the author of that article.

It turns out to be remarkably simple to create a single Zend Form element that is rendered as multiple form elements. We create an element object and a view helper object and we’re done. Usage then looks like:

< ?php class Application_Form_Details extends Zend_Form { public function init() { $this->addPrefixPath('App_Form', 'App/Form/');

// other elements before

$this->addElement('date', 'date_of_birth', array(
'label' => 'Date of birth:'
));

// other elements after

$this->addElement('submit', 'Go');
}
}

Obviously, this form lives in application/forms/Detail.php and is rendered as usual in a view script. In our form definition, we have added an element called ‘date’ and with the addition of the addPrefixPath call have told the form that in addition to using the standard Zend Framework form elements, also look in library/App/Form. (Incidentally, we can also now override any supplied form element by simply dropping a replacement into the libraryApp/Form folder.)

The date form element lives in library/App/Form/Element/Date.php as Zend_Form knows to look in a subfolder for App/Form called Elements for any element objects and will look in the Decorator/ sub folder for decorator objects.

The Date element looks like this:

Read the rest at Rob Allen’s DevNotes.

Using Action Helpers To Implement Re-Usable Widgets

Using Action Helpers To Implement Re-Usable Widgets

I had a twitter/IRC exchange yesterday with Andries Seutens and Nick Belhomme regarding applications that include widgets within their layout. During the exchange, I told Andriess not to use the action() view helper, and both Andriess and Nick then asked how to implement widgets if they shouldn’t use that helper. While I ended up having an IRC exchange with Nick to give him a general idea on how to accomplish the task, I decided a longer writeup was in order.

Background

The situation all started when Andries tweeted asking about what he considered some mis-behavior on the part of the action() view helper — a situation that turned out not to be an issue, per se, but more a case of bad architecture within Zend Framework. His assumption was that calling action() would fire off another circuit of the front controller’s dispatch loop — which would mean he could rely on plugins he’d established to fire. However, action() does nothing of the sort. It instead pulls the dispatcher from the front controller, and manually calls dispatch() on a new action. As such, action helpers will trigger, but no front controller plugins will. Additionally, if a redirect or “forward” condition is detected, it simply returns an empty string.

The helper was done this way because Zend Framework does not render views a single time — it instead renders after each action, and accumulates views to render in the layout. If we were accumulating view variables and rendering once, and if we were using a finite state machine of some sort, we could probably operate the way one would expect — within the dispatch loop. Since we don’t, any solution around looping over actions (such as the ActionStack action helper/front controller plugin) or rendering the content of executing an action will be a hack. Note: ZF2’s MVC layer may make this possible… though still not necessarily recommended.

There are other reasons to avoid the use of these solutions, though. If you are invoking additional controller actions in order to help populate your view, you’re likely putting domain logic into your controllers. Think about it. The controller should only be responsible for taking the input, funneling it to the correct model or models, and then passing information on to the views

With that in mind, here’s the approach I recommended to Nick and Andries.

The Secret Weapon: Action Helpers

I’ve blogged about action helpers before. They’re a built-in mechanism in Zend Framework to allow you to extend your action controllers in a way that uses composition instead of inheritance.

One approach to widgets for Zend Framework makes use of these. Consider the following “user” module:

via read more.

Zend_Log with multiple writers

eschrader writes; So I was sitting here thinking to myself “This is Friday and I’m not getting much of anything done.  Maybe I should write another Friday Framework Highlight.”  I figured that it was a good idea so I pondered what I should write.  I came up blank and so I asked Matthew Weier O’Phinney.  “Multiple writers for Zend_Log,” he said.  I agreed.

If you were not aware, Zend_Log provides facilities for writing to multiple logs through the same log instance.  Additionally, you can do this via configuration options when using a Zend_Applicatin resource plugin.  Together those make for very powerful logging mechanisms.  “How?” you ask?  It’s really easy.  Take your application.ini file, which you use to configure your Zend_Application instance, and make it look something like this.  I’ll highlight the pertinent parts

[production]
phpSettings.display_startup_errors = 0
phpSettings.display_errors = 0
includePaths.library = APPLICATION_PATH "/../library"
bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
resources.frontController.params.displayExceptions = 0
resources.log.stream.writerName = "Stream"
resources.log.stream.writerParams.stream = APPLICATION_PATH "/logs/application.log"
resources.log.stream.writerParams.mode = "a"
resources.log.stream.filterName = "Priority"
resources.log.stream.filterParams.priority = 4

[development : production]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1
resources.log.stream.filterParams.priority = 7
resources.frontController.params.displayExceptions = 1
resources.log.firebug.writerName = "FireBug"
resources.log.firebug.filterName = "Priority"
resources.log.firebug.filterParams.priority = 7

What this does is say that “in production, log warnings and above to the log file, but in development, log debug to the log file AND send the log items to FirePHP.”  Then, in our index controller we put this:

class IndexController extends Zend_Controller_Action
{

public function indexAction()
{
$this->getInvokeArg('bootstrap')->log->debug("I'm at indexAction");
}

}

When we execute this code we get both the output in the application log

$ tail -f application.log
2010-09-10T16:27:25-05:00 DEBUG (7): I'm at indexAction

and in the Firebug log

X-Wf-Protocol-1            http://meta.wildfirehq.org/Protocol/JsonStream/0.2
X-Wf-1-Structure-1    http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1
X-Wf-1-Plugin-1            http://meta.firephp.org/Wildfire/Plugin/ZendFramework/FirePHP/1.6.2
X-Wf-1-1-1-1            122|[{"Type":"LOG","File":"C:\\workspace\\Test\\application\\controllers\\IndexController.php","Line":8},"I'm at indexAction"]|

In production we wouldn’t get anything since this code would filter out debug logging, due to the resources.log.stream.filterParams.priority setting in the production section in application.ini.  Simple.  Done.

via e_schrade.

Zend_Server Class

e_schrade wrote a neat way of doing things in the service layer; Let’s take a quick look at something that’s kind of neat in Zend Framework. I’ve been doing some work with Adobe on some articles and one of them was on working with mobile clients with Flash. Well, me being the masochist I did more. What I did was write an example that worked as a full website, an Ajax website, a Flash service and an XML-RPC service.

Looks like a lot, right?  Actually there’s not much there.  Here’s the logic flow.

  • Is it an XMLHTTP Request and is it a POST? Create the Json server
  • Is it an AMF request? Create the AMF server
  • Is it an XmlRpc request? Create the XmlRpc server
  • Is it an XMLHTTP Request and is it a GET? Create the Service Map (for JSON-RPC 2.0)
  • If a service handler has been created add all of the application’s mappers, attach the service handler to the request and redirect to the service action.

And with that you have an application that can serve content for multiple different types of service with almost no effort on your part.  At least.. if you copy and paste this code.

Have a good Friday!!!

via Zend_Server – zf ffh zend_server on e_schrade – zend php.

Complete Doctrine 1.2x Integration with Zend Framework 1.10+

To achieve complete Doctrine 1 integration with Zend Framework some glue is required, Benjamin Eberlei has created a complete solution thats straight forward, easy to use and understand.

This project tries to offer a complete Integration of Doctrine 1 with Zend Framework. The following components belong to this Integration:

  • Zend_Application Resource
  • Zend Framework Modular Project Support
  • Zend_Tool Provider for Doctrine Model Generation, Migrations and Fixtures
  • Zend_Paginator Adapter for Doctrine Queries
  • Dynamic Zend_Form generation from Doctrine Models

This integration requires the latest Doctrine version 1.2.2 to work completely

Get it!

SVN Export or Externals

Github offers SVN Read support for a while now, you can either use svn export or svn:externals to include ZFDoctrine into your project or into your PHP Include Path.
svn checkout http://svn.github.com/beberlei/zf-doctrine.git

Git Clone

git clone git://github.com/beberlei/zf-doctrine.git
If you follow the tutorial and installation steps your will get this in ZFTool.

Zend Framework Command Line Console Tool v1.10.4
Actions supported by provider "Doctrine"
Doctrine
zf create-project doctrine dsn zend-project-style library-per-module single-library
zf build-project doctrine force load reload
zf create-database doctrine
zf drop-database doctrine force
zf create-tables doctrine
zf generate-sql doctrine
zf dql doctrine
zf load-data doctrine append
zf dump-data doctrine individual-files
zf generate-models-from-yaml doctrine
zf generate-yaml-from-models doctrine
zf generate-yaml-from-database doctrine
zf generate-migration doctrine class-name from-database from-models
zf excecute-migration doctrine to-version
zf show-migration doctrine
zf show doctrine

Read it ALL at beberlei’s zf-doctrine at master – GitHub.

Akrabat_Db_Schema_Manager: table prefix support

Rob Allen posts; I’ve updated Akrabat_Db_Schema_Manager so that it now supports table prefixes.

It uses the application.ini key of resources.db.table_prefix as I couldn’t think of a better one 🙂 and then uses that for the schema_version table’s name and also makes it available in your change objects.

For example, if application.ini contains resources.db.table_prefix = “myapp”, then the manager will create the table myapp_schema_version to store the current version of the schema. In your change classes, you can then do this:

001-Users.php:

class Users extends Akrabat_Db_Schema_AbstractChange
{
function up()
{
$tableName = $this->_tablePrefix . 'users';
$sql = "
CREATE TABLE IF NOT EXISTS $tableName (
id int(11) NOT NULL AUTO_INCREMENT,
username varchar(50) NOT NULL,
password varchar(75) NOT NULL,
role varchar(200) NOT NULL DEFAULT 'user',
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;";
$this->_db->query($sql);

$data = array();
$data['username'] = 'admin';
$data['password'] = sha1('password');
$data['role'] = 'admin';
$this->_db->insert($tableName, $data);
}

function down()
{
$tableName = $this->_tablePrefix . 'users';
$sql= "DROP TABLE IF EXISTS $tableName";
$this->_db->query($sql);
}

}

which will create a table called myapp_users. Note that you are responsible for using the prefix property as the change classes cannot enforce what you do within the up() and down() methods. It also follows that you’ll have to ensure that your models also use the correct prefix.

I have also made a change to the provider (Akrabat_Tool_DatabaseSchemaProvider) so that it loads the correct application.ini file based on the data in the project’s profile. This shouldn’t affect anyone using Akrabat_Db_Schema_Manager, except that we no longer define APPLICATION_ENV and APPLICATION_PATH for you.

Enjoy!

via Rob Allen’s DevNotes.

Zend Framework Class to retreive your RSS feeds used in Google Reader

Rémi Goyard wrote a nice little class to access your Google Reader Feeds take a peek below, he says;

I finally wrote my own class to retreive data from my Google reader Account (stared items, shared items, …)
The class needs some more work.
Regards
Rémi

< ?php /** * Class to retreive your rss feeds used in Google Reader * thanks to : * @see http://www.niallkennedy.com/blog/2005/12/google-reader-api.html * @see http://code.google.com/p/pyrfeed/wiki/GoogleReaderAPI * * @author Rémi Goyard * @category Core * @package Core_Gdata * @subpackage Gdata * @copyright Rémi Goyard * @license http://framework.zend.com/license/new-bsd New BSD License * @version 0.1 */ /** * Zend_Gdata_HttpClient */ require_once 'Zend/Http/Client.php'; /** * Zend_Version */ require_once 'Zend/Version.php'; class Core_Gdata_Reader{ /** * The Google client login URI */ const CLIENTLOGIN_URI = 'https://www.google.com/accounts/ClientLogin'; /** * The default 'source' parameter to send to Google */ const DEFAULT_SOURCE = 'Zend-ZendFramework-Google-Reader 1.0/Zend'; /** * The Google reader Base URI */ const GOOGLE_READER_BASE_URI = "http://www.google.com/reader/"; /** * Default Google Reader Actions */ private $GOOGLE_READER_ACTIONS = array( "subscriptions" =>"atom/user/[USERID]/pref/com.google/subscriptions",
"starred" =>"atom/user/[USERID]/state/com.google/starred",
"shared" => "atom/user/[USERID]/state/com.google/broadcast",
"broadcast" => "atom/user/[USERID]/state/com.google/broadcast",
"read" => "atom/user/[USERID]/state/com.google/read",
"reading-list" => "atom/user/[USERID]/state/com.google/reading-list",
"tag" => "atom/user/[USERID]/label/[TAG]"
);

/**
* Default Params
*/
private $_defaultParams = array("n"=>20);

const SERVICE_NAME = "reader";

private $_userID = "";
private $_email = "";
private $_password = "";

/**
* @var Zend_Http_Client
*/
private $_client = null;

/**
*
* @param string $email
* @param string $password
* @param string $userID
*/
public function __construct($email, $password, $userID){
if (! ($email && $password && $userID)) {
require_once 'Zend/Exception.php';
throw new Zend_Exception(
'Please set your Google credentials before trying to ' .
'authenticate');
}
$this->_email = $email;
$this->_password = $password;
$this->_userID = $userID;
$this->_setHttpClient();

}
private function _setHttpClient()
{
if (! ($this->_email && $this->_password)) {
require_once 'Zend/Exception.php';
throw new Zend_Exception(
'Please set your Google credentials before trying to ' .
'authenticate');
}
$this->_client = new Zend_Http_Client();
$this->_client->setParameterPost("Email", $this->_email);
$this->_client->setParameterPost("Passwd", $this->_password);
$this->_client->setParameterPost("Service", self::SERVICE_NAME);
$this->_client->setConfig(array(
'maxredirects' => 0,
'strictredirects' => true,
'useragent' => self::DEFAULT_SOURCE.Zend_Version::VERSION
)
);
$this->_client->setUri(self::CLIENTLOGIN_URI);
$this->_client->setMethod("POST");
$response = $this->_client->request();
if($response->getStatus() == 200){
foreach (explode("\n", $response->getBody()) as $l) {
$l = chop($l);
if ($l) {
list($key, $val) = explode('=', chop($l), 2);
$this->_client->setCookie($key,$val );
}
}
return true;
}else{
$this->_client = null;
require_once 'Zend/Exception.php';
throw new Zend_Exception('Authentication Error got Response Code : '.$response->getStatus());
}
}

/**
* Import Atom Feed
*
* @param String $type request type
* @param Array $params request params
* @return Zend_Feed_Abstract
*/
public function import($type, $params = array())
{
if(array_key_exists($type, $this->GOOGLE_READER_ACTIONS)){
if(! empty($params)){$this->_defaultParams = $params;}
// TODO : TAG ...
// TODO : manage POST actions
$urlId = str_replace("[USERID]", $this->_userID, $this->GOOGLE_READER_ACTIONS[$type] );
$url = self::GOOGLE_READER_BASE_URI.$urlId;
$this->_client->resetParameters();
$this->_client->setMethod("GET");
require_once 'Zend/Feed.php';
Zend_Feed::setHttpClient($this->_client);
return Zend_Feed::import($url);
}else{
require_once 'Zend/Exception.php';
throw new Zend_Exception('The action '.$type.' does not exists or is not yet implemented');
}
}
}

A Simple Resource Injector for ZF Action Controllers

Matthew Weier O’Phinney writes a very useful article about resource injection; Brandon Savage approached me with an interesting issue regarding ZF bootstrap resources, and accessing them in your action controllers. Basically, he’d like to see any resource initialized by the bootstrap immediately available as simply a public member of his action controller.

So, for instance, if you were using the “DB” resource in your application, your controller could access it via $this->db.

I quickly drafted up a proof of concept for him using an action helper:


class My_ResourceInjector extends Zend_Controller_Action_Helper_Abstract
{
protected $_resources;

public function __construct(array $resources = array())
{
$this->_resources = $resources;
}

public function preDispatch()
{
$bootstrap = $this->getBootstrap();
$controller = $this->getActionController();
foreach ($this->_resources as $name) {
if ($bootstrap->hasResource($name)) {
$controller->$name = $bootstrap->getResource($name);
}
}
}

public function getBootstrap()
{
return $this->getFrontController()->getParam('bootstrap');
}
}

In this action helper, you would specify the specific resources you want injected via the $_resources property – which would be values you pass in. Each resource name would then be checked against those available in the bootstrap, and, if found, injected into the action controller as a property of the same name.

You would initialize it in your bootstrap:


class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
protected function _initResourceInjector()
{
Zend_Controller_Action_HelperBroker::addHelper(
new My_ResourceInjector(array(
'db',
'layout',
'navigation',
));
);
}
}

The above would map three resources: “db”, “layout”, and “navigation”. This means you can refer to them directly as properties in your controllers:


class FooController extends Zend_Controller_Action
{
public function barAction()
{
$this->layout->disableLayout();
$model = $this->getModel();
$model->setDbAdapter($this->db);
$this->view->assign(
'model' => $this->model,
'navigation' => $this->navigation,
);
}

// ...
}

This approach leads to some nice brevity — you no longer need to fetch the bootstrap from the instantiation arguments, and then fetch the resource.

I thought about it some more, and realized that there’s a few problems: How do you know what is being injected from within the controller? How do you control what is being injected.

So, I revised it to pull the expected dependencies from the action controller itself…

Read the complete article here A Simple Resource Injector for ZF Action Controllers.