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 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.

Ext JS + jQTouch + Raphaël = Sencha

Abraham Elias writes;

Ext JS is now Sencha. Exciting things are happening! Today, we’re combining forces with the jQTouch and Raphaël projects, changing our company name to Sencha, and moving our web address from www.extjs.com to www.sencha.com.

jQTouch and Raphaël are the leading open source projects in their areas, and we’re incredibly excited to have their creators, David Kaneda and Dmitry Baranovskiy, joining with the Ext JS team to form Sencha. We believe these collaborations will lead to some spectacular new things in the weeks and months ahead. Stay tuned for this. You won’t have to wait too long, I promise!

We believe that rich graphics and touch support will become essential Ajax framework components over the next few years. If you’ve been following our recent blog posts on HTML5, you’ll know that not only do HTML5 and CSS3 bring significant capabilities to rich internet applications, but that this is already arriving on mobile devices (in fact, it’s already here).

Sencha is the new name of our company, as well as a variety of Japanese green tea.

Why Sencha?

We’re choosing Sencha as our name because it evokes next-generation software development and it’s easy to remember, spell and pronounce. Sencha — the name of a popular Japanese green tea — is in the tradition of Java, and represents a new level of development. It feels memorable to us. We hope you like it too.

The roadmaps for Ext JS, Ext GWT, Designer, Direct etc. don’t change as a result of this. We’re very excited about the new things in Ext JS 4.0 and the rest of the product line. Some of the individual product names might evolve in the future (for example, we’re thinking of renaming Ext Designer to Sencha Designer), but don’t expect any major or immediate changes here.

via  Sencha Blog — JavaScript Framework and RIA Platform.

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.

Adding Zend_Cache to Flex/Flash Builder 4 Projects

I have som rather large and time consuming queries running in the Statistics screen of an NOC (Network Operations Center) Flex/Flash Builder 4 application i’we been tinkering with, to prevent the database server to be boggen down by multiple queries fired by this app in multiple places I had to implement caching.

And to do this is alot easier than it might sound like especially for the (PHP) Zend_AMF based services.

Once you have setup your Data Centric client/server  connection like it’s described in this Article @ DevZone you begin by editing the gateway.php;

// Store configuration in the registry
Zend_Registry::set("amf-config", $amf);

// Configure Zend_Cache
$frontendOptions = array(
'lifetime' => 12*3600,
'automatic_serialization' => true,
'default_options' => array(
'cache_with_get_variables' => true,
'cache_with_post_variables' => true,
'cache_with_session_variables' => true,
'cache_with_files_variables' => true,
'cache_with_cookie_variables' => true,
'make_id_with_get_variables' => true,
'make_id_with_post_variables' => true,
'make_id_with_session_variables' => true,
'make_id_with_files_variables' => true,
'make_id_with_cookie_variables' => true
)
);
$backendOptions = array(
'cache_dir' => '/tmp/'
);

$cache = Zend_Cache::factory('Core', 'File', $frontendOptions, $backendOptions);

// Store cache configuration in the registry
Zend_Registry::set("cache", $cache);

Then modify your service class to look similar to this;

public function getCustomerStatsByMonth() {
// Get the Cache from Registry
$cache = Zend_Registry::get("cache");
$id = 'getCustomerStatsByMonth';
if(!($rows = $cache->load($id)))
{
// We didnt find anything in the cache so lets get it from DB
$stmt = mysqli_prepare($this->connection, "SELECT
customers.name,
SUBSTR(FROM_UNIXTIME(`cdrs`.`start`),1,7) AS `month`,
outgroups.name_invoices,
ROUND(SUM(`cdrs`.`talktime`)/60) AS `minutes`,
COUNT(`cdrs`.`start`) AS `calls`
FROM
es.outgroups
INNER JOIN es.cdrs
ON (outgroups.id = cdrs.outgroup)
INNER JOIN es.customers
ON (customers.id = cdrs.scustomer)
WHERE (outgroups.name_invoices LIKE 'Sweden%' AND cdrs.start > UNIX_TIMESTAMP('2010-01-01 00:00:00') AND cdrs.status = 'answer' AND cdrs.talktime > 0 AND custome\
rs.parent IN (7,42))
GROUP BY customers.id,SUBSTR(FROM_UNIXTIME(`cdrs`.`start`),1,7),outgroups.name_invoices
ORDER BY SUBSTR(FROM_UNIXTIME(`cdrs`.`start`),1,7),outgroups.name_invoices;");
$this->throwExceptionOnError();

mysqli_stmt_execute($stmt);
$this->throwExceptionOnError();

$rows = array();

mysqli_stmt_bind_result($stmt, $row->name, $row->month, $row->name_invoices, $row->minutes, $row->calls);

while (mysqli_stmt_fetch($stmt)) {
$row->month = new DateTime($row->month.'-01 00:00:00');
$rows[] = $row;
$row = new stdClass();
mysqli_stmt_bind_result($stmt, $row->name, $row->month, $row->name_invoices, $row->minutes, $row->calls);
}

mysqli_stmt_free_result($stmt);
mysqli_close($this->connection);
// Save collected rows into the cache
$cache->save($rows,$id,array('customer_stats'),3*3600);
}
return $rows;
}

Your queries will now be cached after the first time you run them for the specified amount of time (TTL), and boom you’re done. If you require the update function in your service classes to purge the cache simply insert;

// To remove or invalidate in particular cache id, you can use the remove() method :
$cache->remove('idToRemove');

Read more about cache cleaning in the Zend Cache reference.

Hope this little article helps and please comment if you guys have better suggestions.
(Yes I know I can use APC & Memcached, but in this example I didnt have to 🙂 )

Regards
Danny Froberg

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.