Archive for the ‘Zend framework’ Category

Cache Zend_Db_Table MetaData with Zend_Cache

Thursday, February 11th, 2010

In this afternoon, my boss asked me to improving performance of project to release to client before we have Lunar new year holidays. The problem has too many DESCRIBE queries on every page load. I Google-ed & found the Lysender‘s solution, simple & easy to fix this problem:

When you are using Zend_Db_Table (I sometimes only used Zend_Db) you will notice that when you try to retrieve data from the database, the first query called is to DESCRIBE the table. Zend_Db_Table uses the information on DESCRIBE query to do its magic on SELECT.

As I have profiled my queries, I noticed that DESCRIBE query is the longest query (in most cases) which mean a big overhead over you retrieval operation. You have two options:

  1. Don’t use Zend_Db_Table (go for Zend_Db)
  2. Cache the MetaData

On this post, I’ll use the caching of MetaData. On your bootstrap file, put this piece of code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
	//Caching
	$frontendOptions = array(
					'lifetime'				 => 25200,
	    				'automatic_serialization' => true
	    				);
	$backendOptions  = array(
	   					 'cache_dir'  => APPLICATION_PATH . '/tmp'
	    				);
	$cache = Zend_Cache::factory(
				'Core',
	                        'File',
	                        $frontendOptions,
	                        $backendOptions
	                    );
	//Cache table metadata
	Zend_Db_Table_Abstract::setDefaultMetadataCache($cache);

The code simply instructs Zend_Db_Table_Abstract to cache the result of DESCRIBE statement so that next time you retrieve data, the cache is used instead of repeatedly describing tables over and over again.

(But I noticed that INSERT and UPDATE statements don’t have DESCRIBE…)

After several tries with this caching, you will see files on the tmp folder like this: zend_cache—internal-metadatas—5e7576e3cd79114d46850714e998a3b0.

Still there is an overhead on reading the cache file. If you want better caching, use memory based caching like MemCache.

Source: http://lysender.co.cc/2009/03/zend-framework-optimization-tips

Getting Started with Zend Framework

Monday, April 14th, 2008

Nghe nói về Zend Framework (ZF) rất nhiều nhưng không hề muốn động vào nó tý nào :p Cũng chẳng biết tại sao lại thế? Do nó “cồng kềnh” quá chăng? Tôi vẫn khoái dùng CodeIgniter hơn (đã viết xong 1 blog & chạy khá ngon – tuy nhiên giờ thì lại dùng…WP ).

Nhưng sáng nay “bác” PM bắt đầu assign tôi vào dự án của ZF team. Vậy là download ngay latest version, install & ngâm kíu thôi

Bước đầu tra manual + tutorial thì thấy dùng cũng không quá khó (tất nhiên là ko 100% APIs của ZF). “Moi” lại code của dự án thấy vấn đề đầu tiên & khá nổi cộm là việc dùng Smarty kết hợp với ZF. Sẽ không có gì đáng nói nếu như “ai đó” parse template theo kiểu mỗi action ứng với 1 template (html), và mỗi template này lại bê nguyên xi những cái không thay đổi (hoặc rất ít) vào

Cách sửa đơn giản nhất là viết lại template kiểu như:

1
{include file='header.tpl'}

vào đầu mỗi template của action.
Nhưng nếu làm như vậy thì vẫn chưa tiện vì mỗi trang template tôi vẫn phải viết thêm các dòng code ở trên ứng với header, footer, sidebar (những cái luôn xuất hiện). Mà tính tôi thì lười. Đã quen với kiểu nhiều script 1 trang, chứ ko quen kiểu mỗi script một trang.

Đằng nào cũng là ngồi “tự sướng”, vậy là tôi quyết định viết 1 cái class nhỏ xíu, để parse template giống như thằng CodeIgniter (cả Drupal) nữa. Mất cũng hơn nửa tiếng loay hoay vì cứ nghĩ cái method bên dưới là của Smarty:

1
$this->view->render('templateDir/templateFile.html');

hoá ra method render là của thằng Zend_View.

Và class tôi viết lại đơn giản như sau:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/*
 * Created on Apr 14, 2008
 *
 * @author: Do Nam Khanh
 * @email: donamkhanh@gmail.com
 */ 
 
class dnkTemplate extends Smarty_View {
 
    function __contructor() {}
 
    function parseTpl($tplFile,$data) {
        $templates = array('header','content','footer');
        $output = "";
       if(is_array($data)) {
           foreach($data as $dataKey => $dataVal) {
                $this->assign($dataKey,$dataVal);
            }
           foreach ($templates as $file) {
                if ($file <> "content") {
                    $output .= $this->fetch($file . '.html',null,null,false);
                }
                else {
                     $output .= $this->fetch($tplFile. '.html',null,null,false);
                }
             }
             echo $output;
 	}
         else {
             die('Could not parse template');
         }
    }
 }

Thật ra thì ý tưởng này tôi lấy của InkType, giờ chỉ modify lại cho nó tương thích với framework này mà thôi :p
Cách dùng thì rất đơn giản:

1
2
3
4
5
6
7
8
9
10
11
$this->view = new dnkTemplate();
...
$dataRow = array(
                 'title'                 => 'List CDs',
                 'base_url'           => $this->base_url,
                 'list_cd_link'       => $this->list_cd_link,
                 'add_cd_link'      => $this->add_cd_link,
                 'data'                => $data
            );
 
$this->view->parseTpl('list',$dataRow);

Tuy nhiên, muốn áp dụng vào project hiện tại không phải đơn giản, vì các thành viên khác sẽ phải viết lại toàn bộ template & sửa lại PHP code. Một khối lượng không nhỏ

Ngoài lề: Trong Ubuntu, mỗi lần tôi sửa file bằng Gedit thì sau khi save lại thấy xuất hiện 1 file backup kiểu như file_name.txt~. Cứ nghĩ là hệ điều hành có tính năng đó. Hoá ra là tính năng của thằng Gedit => disable ngay, ngứa mắt lắm:

It’s in the preferences. In Gedit, go to to Edit > Preferences and uncheck the option about automatically creating a backup file.