Zend Framework 1 and Doctrine 2 Integration

Elink Media posts; Doctrine 2 is in beta. It is for sure one of the most exciting things that caught my attention recently.

As a Zend Framework user, I started looking into ways to integrate Doctrine 2 with Zend Framework (currently in version 1).

The same as any other times, the solutions are already out there. The integration’s already been done by Giorgio Sironi’s nakedphp project.

So … I borrowed code from nakedphp and put up a skeleton ZF projects myself.

My sample project is available on Github. You can find it here.

Have a play, let me know if anything. Hope it’ll help people like myself, who cannot wait to try out new and cool things.

Reference

Zend Framework 1 and Doctrine 2 Integration | Elink Media.

Transparent Logging with Zend_Log

Lebesold publishes another screencast; First of all, I’d like to thank you all for your patience! Zendcasts takes quite a bit of time and research to put together and I’m deeply touched by all your support.
On a personal note, my wife and I are heading out of North America in a week to visit Namibia and South Africa for 3 months. I’m going to do my best to keep up Zendcasts on a weekly basis, however my connectivity and upload speed will be limited. We’ll see how it goes!

Now for today’s episode:

I was working on a project for a client the other day and noticed a couple of lines in the ErrorController for automatically logging errors with Zend_Log. In 10 minutes, you can have a fully integrated logging framework. I also implement a singleton pattern for reusing your Zend_Log configuration (defined in the application.ini) anywhere else in your application.
Grab a copy of the project or browse the repository.
Enjoy!

Watch @ Zendcasts.

Generate the WSDL file from a class using a Zend component

Matthew Weier O’Phinney answers a very common question;

“Is there a way to generate the WSDL file from a class using a Zend component?”

Yes — via Zend_Soap_Autodiscover:

http://framework.zend.com/manual/en/zend.soap.autodiscovery.html

A typical workflow is to do the following:


if ('GET' == $_SERVER['HTTP_METHOD']) {
$server = new Zend_Soap_Autodiscover();
} else {
$server = new Zend_Soap_Server();
}

$server->setClass('SomeClass');
echo $server->handle();

Basically, you handle GET requests as a request for the WSDL, and anything else as a SOAP request.

Acceptance Test-Driven Development

Giorgio Sironi writes an interesting TDD story; I am halfway through reading Growing object-oriented software, guided by tests, a book that teaches Test-Driven Development in a Java environment. A review will come soon, since the process described in this work is really language-agnostic and interesting also for php developers.

However, the book’s authors introduce a very productive practice, which consists in a double cycle of TDD:

* a longer cycle, where you write acceptance (aka end-to-end) tests, deriving them from the user stories or formal requirements, and make them pass;

* a shorter cycle contained in the first, which happens in the phase when an acceptance test is red: you write unit tests and make them pass until the related acceptance test does not fail anymore.

Read complete story @ PHP Zone.

Zend Framework + Doctrine 1 Integration

Benjamin Eberlei writes; Hello everyone,

I completed a first version of Zend + Doctrine 1 integration today and want to share it with all you. Since currently the status on a 1.11 release is unclear I contacted all the contributors to various Doctrine-related components and combined them into a single release and wrote some documentation on all the different parts and how they relate to each other.

http://github.com/beberlei/zf-doctrine

The code is under the New BSD License. There is a comprehensive getting started guide shipped with the Github Project.

The following parts are included in this release:

  • Application Resource contributed by Matt Lurz
  • Dynamic Form Generation contributed by Jani Hartikainen
  • Paginator Adapter contributed by Matt Lurz and Juozas Kaziukenas
  • Zend Tool Provider and modular Zend Project Style Support

Thanks to all the contributors and various other people that contributed ideas and code.

For any feedback regarding this integration, you can use the issue tracker on Github.

This release depends on Doctrine 1.2.2 to allow model code-generation from YAML files that supports Zend Framework Modular projects and their directory structure.

Most of the current glue code out there is made obsolete by generating Models that follow the Zend Framework naming conventions, into Zend Framework models/ directories. Additionally there is also support for modular applications whose model classes should follow the PEAR naming schema.

Additionally the dynamic form support allows to create simple forms that allow to create and edit Doctrine_Record instances and their relations.

This is a great help to rapidly prototype admin forms (however support for more complex forms is not yet included).

Since both projects are currently very focused on their 2.0 releases, this release aims to glue all the existing code for Doctrine 1.x and Zend Framework integration 1.x together, giving them a platform to flourish.

greetings,
Benjamin

Talk: PHP Best Practices – Matthew Weier O’Phinney and Lorna Jane Mitchell

Writing maintainable code is an art that takes effort and practice to master.
Part of that art is learning what tools and strategies will assist you in that effort. In this tutorial, we will cover a variety of practices and tools that can make your life, and the lives of your team members, easier as you develop your applications. Among them, we will provide overviews of:

  • Version Control
  • Coding Standards
  • Unit Testing basics
  • QA tools: phpcs, phploc, phpmd, continuous integration, and more
  • Team Collaboration tools, such as Skype, IRC, issue trackers, and more

via Talk: PHP Best Practices – Joind.in.

Accessing Bootstrap Resources from Anywhere

Aleksey V. Zapparov posts a very nice solution to a very common question when dealing with Bootstrap resources;

Hello,
You can either register precious resources in registry, e.g.:


protected function _initMyResource()
{
$res = 'foobar';
Zend_Registry::set('myResource', $res);
return $res;
}

Or you can register the whole bootstrap, so you can place in it’s constructor, something like this:


public function __construct($application) {
parent::contstruct($application);
Zend_Registry::set('Bootstrap', $this);
}

So later you’ll be able to access resources via:

$res = Zend_Registry::get('myResource');

or:

$res = Zend_Registry::get('Bootstrap')->getResource('MyResource');

And there is another way to get your bootstrapper from almost
everywhere:

$bootstrap = Zend_Controller_Front::getInstance()->getParam('bootstrap');
$resource = $bootstrap->getResource('MyResource');

Sincerely yours,
Aleksey V. Zapparov A.K.A. ixti

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');
}
}
}

MySQL does support preparing some DDL statements, However…

Bill Karwin gives some insight into some work arounds when creating functions, triggers and procedures using Zend Framework;

MySQL does support preparing some DDL statements, even in older versions. See http://dev.mysql.com/doc/refman/5.1/en/sql-syntax-prepared-statements.html
for lists of what statements can be prepared.

However, some DDL statements are still not supported as prepared statements, for example CREATE FUNCTION, CREATE TRIGGER, CREATE PROCEDURE.

DELIMITER is not supported as an executable statement at all, whether you prepare it or whether you do an immediate execute. Statements like DELIMITER, PAGER, SOURCE, CONNECT, and QUIT and others are builtins of the mysql command-line client. These commands are not recognized by the MySQL server.

You need to set the DELIMITER only if you’re running the CREATE FUNCTION statement in an SQL script. The default API for SQL statements does not support multiple statements per call. So you don’t have to delimit statements and you don’t have to change the delimiter.

So Nils’s solution should be the following:

1. Don’t worry about DELIMITER, you don’t need it.

2. You must DROP and CREATE in two separate statements.

3. Bypass the default ZF query method. Go directly to the
PDO::query() method when you execute a statement that isn’t preparable. You can access the PDO object using the getConnection() method of your ZF Db adapter:

$db->getConnection()->query( $drop_function_statement );
$db->getConnection()->query( $create_function_statement );

Regards,
Bill Karwin

Reporting with Zend_Tool and Zend_

Jon Lebensold posts a continuation to his screencast on Zend_tool; Reporting with Zend_Tool and Zend_Log

This video uses a collection of powerful PHP libraries in order to illustrate how easy it really is to build a command-line tool for reporting against XML files. We start off by logging visitor statistics in the controller into a log file with Zend_Log. Once data has been collected, we’re then able to utilize SimpleXML, Zend_Date and the Zend_Tool component to build out a very simple reporting tool. This is of course just an example of what’s possible. What comes to mind for me is building a cron job for generating reports based on the zf.sh executable, or even just doing backups at the command-line with the help of a fully integrated Zend Framework installation.

I’ve noticed that configuration information isn’t properly loaded into Zend_Tool and am still trying to figure out the design decisions there. You’ll notice that I was having some timezone issues with regards to Zend_Date and it seems that specifying a timezone in my application.ini file didn’t resolve the issue.

Grab a copy of the project or browse the repository.

via Zendcasts.