<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>How-to PHP</title>
	<atom:link href="http://howtophp.net/index.php/feed" rel="self" type="application/rss+xml" />
	<link>http://howtophp.net</link>
	<description>How-to PHP ::: Make The Easiest PHP!</description>
	<lastBuildDate>Mon, 16 May 2011 10:07:09 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Mysql deadlock và cách xử lý với Zend framework</title>
		<link>http://howtophp.net/index.php/2011/04/mysql-deadlock-va-cach-xu-ly-voi-zend-framework.html</link>
		<comments>http://howtophp.net/index.php/2011/04/mysql-deadlock-va-cach-xu-ly-voi-zend-framework.html#comments</comments>
		<pubDate>Wed, 13 Apr 2011 09:56:10 +0000</pubDate>
		<dc:creator>nonggiatu</dc:creator>
				<category><![CDATA[2 - Vượt trội]]></category>
		<category><![CDATA[Series]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[deadlock]]></category>
		<category><![CDATA[innodb]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[thủ thuật]]></category>
		<category><![CDATA[zend framework]]></category>

		<guid isPermaLink="false">http://howtophp.net/?p=409</guid>
		<description><![CDATA[Transaction deadlock là một vấn đề khá phổ biến đối với những ứng dụng phải xử lý một số lượng lớn các yêu cầu thay đổi dữ liệu. Cách đây vài tháng, khi số lượng người dùng của tôi tăng lên đến hơn 40000 người, hiện tượng deadlock đã thi thoảng xuất hiện: Một số [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://howtophp.net/wp-content/uploads/2011/04/logo-mysql.jpg"><img class="size-full wp-image-421 alignnone" title="logo-mysql" src="http://howtophp.net/wp-content/uploads/2011/04/logo-mysql.jpg" alt="" width="399" height="291" /></a></p>
<p>Transaction deadlock là một vấn đề khá phổ biến đối với những ứng dụng phải xử lý một số lượng lớn các yêu cầu thay đổi dữ liệu. Cách đây vài tháng, khi số lượng người dùng của tôi tăng lên đến hơn 40000 người, hiện tượng deadlock đã thi thoảng xuất hiện: Một số truy vấn nhận được exception “<em>SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction.</em>” Bài viết này nhằm chia sẻ cho mọi người nguyên nhân của hiện tượng Transaction deadlock khi sử dụng InnoDB storage engine và cách thức xử lý nó trong Zend framework.</p>
<p><strong>Transaction deadlock</strong></p>
<p>Như ta đã biết, InnoDB có cơ chế lock table khi thực hiện một transaction theo 4 mức: <code><a href="http://dev.mysql.com/doc/refman/5.0/en/set-transaction.html#isolevel_read-uncommitted">READ UNCOMMITTED</a></code>, <code><a href="http://dev.mysql.com/doc/refman/5.0/en/set-transaction.html#isolevel_read-committed">READ COMMITTED</a></code>, <code><a href="http://dev.mysql.com/doc/refman/5.0/en/set-transaction.html#isolevel_repeatable-read">REPEATABLE READ</a></code>, và <code><a href="http://dev.mysql.com/doc/refman/5.0/en/set-transaction.html#isolevel_serializable">SERIALIZABLE</a></code>. Ở đây để cho đơn giản tôi chỉ trình bày trường hợp sử dụng chế độ lock mặc định của MySql là REPEATABLE READ.</p>
<p>Với chế độ Repeatable read, trong khi thực hiện một transaciton, MySql sẽ lock những row được select và update. Xét trường hợp có 2 transaction A và B được thực hiện cùng lúc:</p>
<p>Transaction A:</p>
<pre class="brush: sql;">UPDATE user SET age = 20 WHERE user_id = 1</pre>
<p>Transaction B:</p>
<pre class="brush: sql;">UPDATE user SET age = 30 WHERE user_id = 1</pre>
<p>Nếu transaction A đựơc thực hiện trước, row chứa dữ liệu của user có user_id = 1 sẽ bị lock lại cho đến khi transaction A được thực hiện xong. Như vậy transaction B sẽ phải đợi cho đến khi row cần update được unlock thì mời có thể thực hiện truy vấn được. Thời gian đợi này dĩ nhiên phải có giới hạn để tránh việc một transaction phải đợi quá lâu dẫn đến tắc nghẽn. Thời gian này có thể được config qua tham số <code><a href="http://dev.mysql.com/doc/refman/5.0/en/innodb-parameters.html#sysvar_innodb_lock_wait_timeout"><em>innodb_lock_wait_timeout</em></a></code></p>
<p>Nếu transaction A được thực hiện quá lâu và vượt mức thời gian giới hạn nói trên thì chúng ta sẽ gặp phải hiện tượng deadlock. Exception sẽ được ném ra với message: <em>“SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction.”</em></p>
<p>Như vậy để tránh gặp phải deadlock, chúng ta cần đảm bảo thời gian thực thi của một transaction luôn nhỏ hơn thời gian giới hạn <code><a href="http://dev.mysql.com/doc/refman/5.0/en/innodb-parameters.html#sysvar_innodb_lock_wait_timeout"><em>innodb_lock_wait_timeout</em></a></code></p>
<p>Tuy nhiên thời gian thực thi một transaction rất khó có thể đảm bảo nhất là khi khối lượng dữ liệu trở nên rất lớn. Chúng ta có thể chấp nhận xảy ra deadlock và sống chung với nó.</p>
<p><strong>Cách thức xử lý</strong></p>
<p>Ý tưởng xử lý deadlock là: Nếu một truy vấn gặp deadlock, chúng ta tạm dừng truy vấn trong một thời gian và thực hiện lại truy vấn đó. Với ví dụ trên, khi transaction B gặp deadlock, việc tạm dừng này có thể giúp tăng thêm thời gian chờ cho đến khi transaction A được thực hiện xong.</p>
<p>Với Zend framework, nếu một truy vấn gặp phải exception, framework sẽ ném exception ra ngoài và kết thúc truy vấn. Do đó để xử lý được deadlock chúng ta phải sửa lại code của Zend framework một chút. Cụ thể chúng ta sẽ sửa lại hàm _execute trong file Zend/Db/Statement/Pdo.php như sau:</p>
<pre class="brush: php;">
&lt;div&gt;&lt;code&gt; public function _execute(array $params = null)
 {
 // begin changes
 $tries = 0;
 do {
 $retry = false;
 try {
 if ($params !== null) {
 return $this-&gt;_stmt-&gt;execute($params);
 } else {
 return $this-&gt;_stmt-&gt;execute();
 }
 } catch (PDOException $e) {
 #require_once 'Zend/Db/Statement/Exception.php';
 if ($tries &lt; 10 and $e-&gt;getMessage()=='SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction') {
 $retry = true;
 } else {
 throw new Zend_Db_Statement_Exception($e-&gt;getMessage());
 }
 $tries++;
 }
 } while ($retry);
 // end changes
 } &lt;/code&gt;&lt;/div&gt;
&lt;pre&gt;
</pre>
<p>Trên đây tôi đã trình bày sơ qua nguyên nhân của deadlock khi thực hiện một transaction. Ngoài cách xử lý cụ thể với Zend framework, các bạn cũng có thể áp dụng ý tưởng đó cho các framework khác.<br />
Rất mong nhận được sự góp ý của các bạn.</p>
</pre>
]]></content:encoded>
			<wfw:commentRss>http://howtophp.net/index.php/2011/04/mysql-deadlock-va-cach-xu-ly-voi-zend-framework.html/feed</wfw:commentRss>
		<slash:comments>2998</slash:comments>
		</item>
		<item>
		<title>Kỳ 3: Factory Pattern và Singleton Pattern</title>
		<link>http://howtophp.net/index.php/2010/08/k%e1%bb%b3-3-factory-pattern-va-singleton-pattern.html</link>
		<comments>http://howtophp.net/index.php/2010/08/k%e1%bb%b3-3-factory-pattern-va-singleton-pattern.html#comments</comments>
		<pubDate>Wed, 25 Aug 2010 09:51:34 +0000</pubDate>
		<dc:creator>banksy</dc:creator>
				<category><![CDATA[1 - Nền tảng]]></category>
		<category><![CDATA[cart]]></category>
		<category><![CDATA[design pattern]]></category>
		<category><![CDATA[oop]]></category>
		<category><![CDATA[php5]]></category>
		<category><![CDATA[shopping]]></category>

		<guid isPermaLink="false">http://howtophp.net/?p=386</guid>
		<description><![CDATA[Ở bài viết trước chúng ta đã làm quen với khái niệm Design Pattern – Mẫu thiết kế trong lập trình PHP, giúp cho việc tổ chức code logic hơn, dễ bảo trì và mở rộng hơn. Adaptor Pattern được lựa chọn để giới thiệu đầu tiên, không vì lý do gì cả. Đơn giản [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><a href="../wp-content/uploads/2010/08/shopping_cart_development.jpg"></a><a href="http://howtophp.net/wp-content/uploads/2010/08/shopping_cart_development.jpg"><img class="aligncenter size-full wp-image-393" title="shopping_cart_development" src="http://howtophp.net/wp-content/uploads/2010/08/shopping_cart_development.jpg" alt="" width="400" height="300" /></a></p>
<p>Ở bài viết trước chúng ta đã làm quen với khái niệm Design Pattern – Mẫu  thiết kế trong lập trình PHP, giúp cho việc tổ chức code logic hơn, dễ  bảo trì và mở rộng hơn. Adaptor Pattern được lựa chọn để giới thiệu đầu  tiên, không vì lý do gì cả. Đơn giản chỉ là vì nó phù hợp nhất với tình  huống mẫu trong chủ đề này – xây dựng một Gian hàng trực tuyến, và rõ  ràng module Thanh toán chính là chức năng quan trọng nhất của một gian  hàng.</p>
<p><strong>1 – Factory Pattern</strong></p>
<p>OK! Chúng ta đã có rất nhiều module thanh toán, mỗi module cài đặt cho một loại phương thức giao dịch khác nhau: Paypal, 2Checkout, Authorize.net, LR… Người dùng có thể tùy ý lựa chọn một loại phương thức giao dịch và ứng dụng phải dễ dàng chấp nhận nó cho thao tác thanh toán. Với mỗi phương thức thanh toán, tiến trình khởi tạo của các đối tượng PaymentGateway (như Paypal, Twoco…) hoàn toàn khác nhau, trong khi chúng ta mong muốn có một handler để nắm giữ một phương thức thanh toán người dùng lựa chọn để sử dụng cho tiến trình thanh toán giao dịch:</p>
<p>Sử dụng Factory Pattern, tức là chúng ta sẽ tạo ra 1 lớp (hoặc một phương thức) dùng để sinh ra các đối tượng khác nhau phụ thuộc vào tham số đầu vào. Điều này là cần thiết khi chúng ta cần tạo ra một đối tượng mà quá tiến trình khởi tạo phải có những bước thiết đặt khác nhau (thực hiện một chuỗi lệnh, hoặc load các objects hỗ trợ khác, hoặc thiết đặt giá trị cho một số biến…).</p>
<pre class="brush: php;">function getPaymentGateway($type)
{
    switch($type) {
       case ‘Paypal’:
          return new Palpay();
       case ‘Twoco’:
          return new Twoco();
       …
    }
}</pre>
<p>Hoặc nếu tên class đã được “chuẩn hóa”, thì đơn giản chỉ là:</p>
<pre class="brush: php;">function getPaymentGateway($type)
{
    return new $type();
}</pre>
<p>Và khi người dùng lựa chọn một phương thức thanh toán của họ, chúng ta chỉ cần gọi hàm getPaymentGateway() để tạo ra một đối tượng nắm giữ module thanh toán của phương thức đó.</p>
<pre class="brush: php;">$paymentHandler = getPaymentGateway(‘Paypal’);</pre>
<p>Chúng ta có thể sử dụng $paymentHandler này cho các chức năng giao dịch khác mà không cần phải quan tâm lựa chọn của người dùng là gì.</p>
<pre class="brush: php;">$paymentHandler-&gt;submitPayment();</pre>
<p><strong>3 – Singleton Pattern và Giỏ hàng</strong></p>
<p>Một chức năng quan trọng khác của một gian hàng, đó là bạn cần tạo ra một Giỏ hàng cho người mua. Giỏ hàng phải có các đặc tính:</p>
<p>- Thêm, loại bỏ, thay đổi số lượng… sản phẩm.<br />
- Tính toán giá thành và thanh toán giỏ hàng.<br />
- Mỗi người mua chỉ có một giỏ hàng.</p>
<p>Giỏ hàng sẽ được lưu lại trên session hoặc lưu trực tiếp vào database, và chúng ta chú ý ở đặc điểm thứ 3 – mỗi người dùng chỉ được cung cấp một Giỏ hàng cho việc lưu giữ các sản phẩm đã lựa chọn. Như vậy trong quá trình khởi tạo Giỏ hàng, chúng ta sẽ phải chuẩn bị các thiết đặt về cấp phát như: thiết đặt các giá trị lên session hoặc khởi tạo kết nối database. Nếu ta định nghĩa Giỏ hàng dưới một class thông thường: Cart, thì mỗi lần sử dụng Giỏ hàng sẽ phải tạo ra một đối tượng Cart khác nhau:</p>
<pre class="brush: php;">$cart1 = new Cart();
$cart2 = new Cart();</pre>
<p>Trong chương trình, $cart1 và $cart2 là hai đối tượng hoàn toàn khác nhau, mặc dù chúng có thể sử dụng cùng một session hoặc database để lưu/đọc thông tin về sản phẩm. Và mỗi lần sử dụng toán tử new, chúng lại phải thực hiện các bước khởi tạo, cấp phát. Chúng ta cũng có thể nghĩ đến chuyện sử dụng biến toàn cục – global variables cho các handler mà không cần phải khởi tạo nhiều lần, tuy nhiên global variables là giải pháp nghèo nàn của PHP4 và nó có những nhược điểm sẽ được nói tới ở cuối bài.</p>
<p>Những điều trên dẫn đến ý tưởng sử dụng Singleton Pattern, cho phép tạo ra và duy trì một instance duy nhất của một class trong chương trình.</p>
<pre class="brush: php;">class Cart
{
    private static $instance = false;
    private $items = array();
    private db_connection;
    public $total = 0;

    private function __construct()
    {
        // Initilizing a database connection
    }

    private function __clone() {}

    public static function getInstance()
    {
        if(self::$instance === false)
        {
            self::$instance = new Cart;
        }
        return self::$instance;
    }

    public function add($item)
    {
        $this-&gt;items[] = $item;
        // Sync to database use db_connection
    }

    public function total()
    {
        foreach ($this-&gt;items as $item)
        {
            $this-&gt;total += $item['price'];
        }
        return $this-&gt;total;
    }
}
</pre>
<p>Và một đoạn mã nhỏ để test Giỏ hàng của chúng ta:</p>
<pre class="brush: php;">
$cart1 = Cart::getInstance();
$cart2 = Cart::getInstance();

$item = array(
 'id'       =&gt; 'sku_123ABC',
 'qty'     =&gt; 1,
 'price'   =&gt; 39.95,
 'name'   =&gt; 'T-Shirt',
 'options' =&gt; array('Size' =&gt; 'L', 'Color' =&gt; 'Red')
);
$cart1-&gt;items[] = $item;
print_r($cart2-&gt;items);
echo &quot;Total: &quot;.$cart2-&gt;total();
</pre>
<p>Kết quả sẽ là:</p>
<p>Array ( [id] =&gt; sku_123ABC [qty] =&gt; 1 [price] =&gt; 39.95 [name] =&gt; T-Shirt [options] =&gt; Array ( [Size] =&gt; L [Color] =&gt; Red ) )<br />
Total: 39.95</p>
<p>Với output như trên chúng ta có thể hiểu là $cart1 và $cart2 trong chương trình là một, chúng sử dụng chung một thuộc tính db_connection để giữ kết nối tới database, và cập nhật thông tin sản phẩm khi người dùng thêm/sửa/xóa giỏ hàng. Ở ví dụ này chú ý rằng các phương thức __construct(), __clone được đặt private, để ngăn chặn việc tạo ra một instance của Cart trực tiếp thông qua toán tử new, hoặc clone thông qua toán tử clone (sinh ra lỗi Fatal Error).</p>
<p><strong>{!} Thay thế biến toàn cục – Global Variables</strong></p>
<p>Trong PHP5, Singleton thường được dùng để thay thế cho việc sử dụng biến toàn cục, bởi vì biến toàn cục có những nhược điểm sau:</p>
<p>- Nó có thể bị thay đổi ở bất cứ chỗ nào trong chương trình, rất khó cho quá trình debug.<br />
- Nó hủy hoại các namespace, bởi vì nếu bạn sử dụng một biến toàn cục trùng tên với biến toàn cục của một namespace nào đó sử dụng trong chương trình, chúng được coi là một và dễ dàng bị xung đột – conflict (sự thay đổi của biến này được áp dụng cho biến kia).</p>
<p>Và rất nhiều tội lỗi khác của Global Variables được kể ra <a href="http://c2.com/cgi/wiki?GlobalVariablesAreBad">ở đây</a>. Sử dụng Singleton có thể giúp thay thế việc sử dụng biến toàn cục trong chương trình và khắc phục các nhược điểm kể trên:</p>
<pre class="brush: php;">class Globals {
    private static $vars = array();
    public function __construct() {}
    public static function __get($name)
    {
        if(array_key_exists($name, self::$vars)) {
            return self::$vars[$name];
        }
    }
    public static function __set($name, $value)
    {
        self::$vars[$name] = $value;
    }
}</pre>
<p>Như vậy khi ở trong chương trình chúng ta muốn có sự xuất hiện của một biến toàn cục, có thể sử dụng cách sau để thay thế:</p>
<pre class="brush: php;">
// Tạo ra một đối tượng Globals
$globals = new Globals;
// Khai báo một biến toàn cục
$globals-&gt;store_name = &quot;Killer Shop&quot;;
// Gọi biến toàn cục
echo $globals-&gt;store_name;
// Kiểm tra tính toàn cục bằng một instance khác
$another = new Globals;
// Output vẫn là “Killer Shop”
echo $another-&gt;store_name; </pre>
]]></content:encoded>
			<wfw:commentRss>http://howtophp.net/index.php/2010/08/k%e1%bb%b3-3-factory-pattern-va-singleton-pattern.html/feed</wfw:commentRss>
		<slash:comments>411</slash:comments>
		</item>
		<item>
		<title>Zend framework – Xây dựng custom controller để lưu thời gian thực thi của action</title>
		<link>http://howtophp.net/index.php/2010/08/zend-framework-xay-dung-custom-controller-de-luu-thoi-gian-thuc-thi-cua-action.html</link>
		<comments>http://howtophp.net/index.php/2010/08/zend-framework-xay-dung-custom-controller-de-luu-thoi-gian-thuc-thi-cua-action.html#comments</comments>
		<pubDate>Tue, 24 Aug 2010 08:00:07 +0000</pubDate>
		<dc:creator>nonggiatu</dc:creator>
				<category><![CDATA[2 - Vượt trội]]></category>
		<category><![CDATA[Series]]></category>
		<category><![CDATA[controller]]></category>
		<category><![CDATA[log]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[thủ thuật]]></category>
		<category><![CDATA[tối ưu]]></category>
		<category><![CDATA[zend framework]]></category>

		<guid isPermaLink="false">http://howtophp.net/?p=355</guid>
		<description><![CDATA[Các ứng dụng web thường sử dụng kiến trúc MVC. Trong Zend framework, các controller thường bao gồm một hoặc nhiều action. Mỗi action thực hiện một công việc nhất định. Để dễ dàng cho việc tìm ra những phần nào của ứng dụng được viết thiếu hiệu quả, hiệu năng thấp, việc ghi lại [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><a href="http://howtophp.net/wp-content/uploads/2010/08/zend_logo.jpg"><img class="aligncenter size-full wp-image-362" title="zend_logo" src="http://howtophp.net/wp-content/uploads/2010/08/zend_logo.jpg" alt="Zend framework's logo" width="429" height="255" /></a></p>
<p>Các ứng dụng web thường sử dụng kiến trúc MVC. Trong Zend framework, các controller thường bao gồm một hoặc nhiều action. Mỗi action thực hiện một công việc nhất định. Để dễ dàng cho việc tìm ra những phần nào của ứng dụng được viết thiếu hiệu quả, hiệu năng thấp, việc ghi lại thời gian thực thi của từng action là rất cần thiết. Bài viết này sẽ giới thiệu cách tự viết một Controller Action của riêng bạn để tự  động ghi lại thời gian thực thi của từng action.</p>
<h2>Ý tưởng</h2>
<p>Lớp Zend_Controller_Action cung cấp cho chúng ta hai phương thức để can thiệp vào quá trình thực thi một action đó là preDispatch() và posDispatch(). preDispatch() sẽ được thực thi trước khi thực hiện action. posDispatch() được thực thi sau khi action được thực hiện. Trong bài viết này, chúng ta sẽ overide hai phương thức này để ghi lại thời gian thực thi của action. Cụ thể, trong phương thức preDispatch() chúng ta sẽ lưu lại thời gian hiện tại của hệ thống. Trong hàm posDispatch() chúng ta lấy thời gian hiện tại trừ đi thời gian đã lưu trước đó để tính ra thời gian thực thi của action. Thông tin này sau đó lưu vào cơ sở dữ liệu để dễ dàng cho việc truy xuất.</p>
<h2>Thực hiện</h2>
<p>Chúng ta tạo ra class My_Action_Controller thừa kế class Zend_Controller_Action như sau</p>
<pre class="brush: php;">

class SaintsRow_Controller_Action extends Zend_Controller_Action
{
 var $startTime = 0;

 public function preDispatch()
 {

 }

 public function postDispatch()
 {

 }
}
</pre>
<p>Để lưu thông tin thực thi của action vào cơ sở dữ liệu, chúng ta tạo table action_log như sau:</p>
<pre class="brush: php;">
CREATE TABLE `actionlist`.`action_log` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`controller` VARCHAR( 50 ) NOT NULL ,
`action` VARCHAR( 50 ) NOT NULL ,
`param` VARCHAR( 200 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci,
`time_execute` INT NOT NULL,
 PRIMARY KEY (`id`)
);
</pre>
<p>Sau đó ta tạo một file ActionLogModel.php để viết các phương thức lưu thông tin vào bảng này:</p>
<pre class="brush: php;">
class ActionLogModel extends Zend_Db_Table_Abstract
{
 protected $_name = 'action_log';

 public function add($controller, $action, $param, $time_execute)
 {
    $data = array(
       'controller'        =&gt;     $controller,
       'action'            =&gt;     $action,
       'param'                =&gt;     $param,
       'time_execute'        =&gt;     $time_execute,
    );
    return $this-&gt;insert($data);
 }
}
</pre>
<p>Công việc còn lại là viết chi tiết hai hàm preDispatch() và posDispatch()</p>
<pre class="brush: php;">
class My_Controller_Action extends Zend_Controller_Action
{
 var $_startTime = 0;
 public function preDispatch()
 {
    $this-&gt;_startTime = microtime(true);
 }

 public function postDispatch()
 {
    $time_execute = microtime(true) - $this-&gt;_startTime;
    $controller = $this-&gt;_request-&gt;getControllerName();
    $action = $this-&gt;_request-&gt;getActionName();
    $param = print_r($this-&gt;_request-&gt;getParams(), true);

    $actionLog = new ActionLogModel();
    $actionLog-&gt;add($controller, $action, $param, $time_execute);
 }
}
</pre>
<p>Mọi thứ chỉ đơn giản có vậy. Công việc còn lại chỉ là tiến hành xây dựng ứng dụng như bình thường. Nhưng thay vì sử dụng Zend_Controller_Action thì bạn sử dụng Action_Controller mà bạn vừa xây dựng. Ví dụ:</p>
<pre class="brush: php;">
class IndexController extends My_Controller_Action
{
 function  indexAction()
 {
 }

}
</pre>
<p>Khi đó, hệ thống sẽ tự động lưu lại thời gian thực thi của action. Danh sách những action có thời gian thực thi lớn nhất sẽ dễ dàng được lấy ra bằng câu lệnh SQL:</p>
<pre class="brush: php;">
SELECT * FROM action_log ORDER BY time_execute DESC
</pre>
<p>Ngoài ra chúng ta cũng có thể lưu thêm những thông tin chi tiết hơn như địa chỉ IP, kết quả trả về &#8230; để dễ dàng tìm ra nguyên nhân vì sao action kém hiệu năng.</p>
<p>Chúc các bạn thành công.</p>
]]></content:encoded>
			<wfw:commentRss>http://howtophp.net/index.php/2010/08/zend-framework-xay-dung-custom-controller-de-luu-thoi-gian-thuc-thi-cua-action.html/feed</wfw:commentRss>
		<slash:comments>1982</slash:comments>
		</item>
		<item>
		<title>SQL Performance Tuning</title>
		<link>http://howtophp.net/index.php/2010/08/sql-performance-tuning-vi.html</link>
		<comments>http://howtophp.net/index.php/2010/08/sql-performance-tuning-vi.html#comments</comments>
		<pubDate>Thu, 19 Aug 2010 06:56:58 +0000</pubDate>
		<dc:creator>nonggiatu</dc:creator>
				<category><![CDATA[3 - Kho báu]]></category>
		<category><![CDATA[Ebooks]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[ebook]]></category>
		<category><![CDATA[optimizing]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[sql]]></category>

		<guid isPermaLink="false">http://howtophp.net/?p=325</guid>
		<description><![CDATA[Tên sách: SQL Performance Tuning Tác giả: Peter Gulutzan, Trudy Pelzer Xuất bản: 2002 Định dạng ebook: CHM/1.39MB Mô tả: SQL Performance Tuning is a handbook of practical solutions for busy database professionals charged with managing an organization’s critically important data. Covering today’s most popular and widely installed database environments, this book is an indispensable [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><a href="http://howtophp.net/wp-content/uploads/2010/08/Sql-performance-tuning2.jpeg"><img class="aligncenter size-full wp-image-335" title="Sql-performance-tuning" src="http://howtophp.net/wp-content/uploads/2010/08/Sql-performance-tuning2.jpeg" alt="" width="372" height="465" /></a></p>
<p><strong>Tên sách:</strong> SQL Performance Tuning</p>
<p><strong>Tác giả:</strong> Peter Gulutzan, Trudy Pelzer</p>
<p><strong>Xuất bản:</strong> 2002</p>
<p><strong>Định dạng ebook:</strong> CHM/1.39MB</p>
<p><strong>Mô tả:</strong></p>
<p><strong><em>SQL Performance Tuning </em></strong>is a handbook of  practical  solutions for busy database professionals charged with  managing an  organization’s critically important data. Covering today’s  most popular  and widely installed database environments, this book is  an  indispensable resource for managing and tuning SQL across multiple   platforms.</p>
<p>Packed with tips, techniques, and best practices, this  hands-on  guide covers SQL commands and queries over a wide range of  conditions  and environments. Every facet of the SQL environment is  covered, from  concurrency control to optimization—and every issue in  between. The  book includes an overview of each of the most widely used  database  management systems (DBMS) and provides tuning tips for common   day-to-day situations.</p>
<p><strong>Download</strong></p>
<p><a href="http://howtophp.net/wp-content/uploads/2010/08/SQL-performance-tuning.zip">SQL-performance-tuning.zip</a></p>
]]></content:encoded>
			<wfw:commentRss>http://howtophp.net/index.php/2010/08/sql-performance-tuning-vi.html/feed</wfw:commentRss>
		<slash:comments>2846</slash:comments>
		</item>
		<item>
		<title>Phần 2 – Sử dụng APD</title>
		<link>http://howtophp.net/index.php/2010/08/ph%e1%ba%a7n-2-s%e1%bb%ad-d%e1%bb%a5ng-apd.html</link>
		<comments>http://howtophp.net/index.php/2010/08/ph%e1%ba%a7n-2-s%e1%bb%ad-d%e1%bb%a5ng-apd.html#comments</comments>
		<pubDate>Wed, 18 Aug 2010 04:47:10 +0000</pubDate>
		<dc:creator>nonggiatu</dc:creator>
				<category><![CDATA[2 - Vượt trội]]></category>
		<category><![CDATA[advanced php]]></category>
		<category><![CDATA[advanced php debugger]]></category>
		<category><![CDATA[APD]]></category>
		<category><![CDATA[cms]]></category>
		<category><![CDATA[debug]]></category>
		<category><![CDATA[lập trình]]></category>
		<category><![CDATA[performance profiling]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[thủ thuật]]></category>
		<category><![CDATA[tối ưu]]></category>

		<guid isPermaLink="false">http://howtophp.net/?p=289</guid>
		<description><![CDATA[Do hoàn cảnh đang phải làm việc trên windows cộng với việc ở Việt Nam nhiều bạn sử dụng windows nên tôi mạn phép trình bày cách sử dụng APD trên môi trường windows. Dĩ nhiên những ai sử dụng linux cũng có thể làm tương tự như trong bài. Trong bài viết này, tôi [...]]]></description>
			<content:encoded><![CDATA[<p>Do hoàn cảnh đang phải làm việc trên windows cộng với việc ở Việt Nam nhiều bạn sử dụng windows nên tôi mạn phép trình bày cách sử dụng APD trên môi trường windows. Dĩ nhiên những ai sử dụng linux cũng có thể làm tương tự như trong bài.<br />
Trong bài viết này, tôi thử áp dụng APD cho một CMS mã nguồn mở made in Vietnam là TomatoCMS. Phiên bản được sử dụng là TomatoCMS ver 2.0.5.</p>
<h2>Cách sử dụng</h2>
<p>Thêm đoạn mã sau vào bất kì nơi nào trong ứng dụng PHP bạn muốn bắt đầu quá trình profiling, dĩ nhiên nếu bạn muốn profiling toàn bộ ứng dụng thì nên đặt nó tại dòng lệnh đầu tiên được thực thi:</p>
<pre class="brush: php;">apd_set_pprof_trace('C:\temp');</pre>
<p>Câu lệnh trên sẽ ra lệnh cho APD bắt đầu việc ghi lại quá trình thực thi của ứng dụng PHP. APD sẽ can thiệp vào trong Zend engine và ghi lại các lời gọi hàm, thời gian thực hiện của chúng, &#8230; Những thông tin này sẽ được ghi vào file tại một thư mục được chỉ định. Trong đoạn mã trên,<strong> &#8216;C:\temp&#8217; </strong>là thư mục mà chúng ta muốn ghi các file đầu ra của APD. Nếu không có đối số truyền vào, các file này sẽ được lưu vào thư mục đã được định nghĩa trong file <strong>php.ini</strong>. Ví dụ, sau khi cài đặt xong APD, chúng ta có thể thêm dòng sau vào file <strong>php.in</strong>:<br />
<em>apd.dumpdir = C:\temp</em></p>
<h2>Sử dụng APD với TomatoCMS</h2>
<p>TomatoCMS là một hệ quản trị nội dung mã nguồn mở được xây dựng trên Zend framework. File đầu tiên trong ứng dụng được gọi đến sẽ là file index.php. Do đó tôi thêm đoạn mã sau vào dòng đầu tiên của file index.php:</p>
<pre class="brush: php;">// Start APD trace
apd_set_pprof_trace('C:\temp');</pre>
<p>Sau đó tôi mở trình duyệt và truy cập vào TomatoCMS như bình thường, tuy nhiên để ý rằng sau mỗi lần truy cập, APD sẽ tạo ra một file mới trong thư mục <strong>C:\temp</strong>. File này ghi lại những thông tin về quá trình thực thi của ứng dụng PHP. Giả sử sau khi truy cập, file được tạo ra là <strong>pprof.02672.0</strong>.<br />
Để đọc được những thông tin hữu ích từ file này, tôi mở <em>Command prompt</em> bằng cách vào <em>Run </em>và gõ <em>cmd</em>. Di chuyển đến thư mục đã cài PHP (thư mục chứa file <strong>php.exe</strong>) và thực thi câu lệnh sau:</p>
<pre class="brush: plain;">php pprofp -u C:\temp\pprof.02672.0</pre>
<p>Kết quả thống kê về quá trình thực thi TomatoCMS được hiển thị ra trên màn hình console. Để ghi kết quả này ra file, giả sử file <strong>C:\temp\output.txt</strong>, tôi sử dụng câu lệnh:</p>
<pre class="brush: plain;">php pprofp -u C:\temp\pprof.02672.0 &gt;C:\temp\output.txt</pre>
<p><strong>[Chú ý]</strong>: Nếu sau khi thực hiện dòng lệnh trên, hệ thống báo lỗi không tìm thấy file <strong>pprofp</strong>, hãy download nó tại <a href="http://howtophp.net/wp-content/uploads/2010/08/pprofp.zip">đây</a>, giải nén và lưu vào cùng thư mục với file <strong>php.exe</strong>. File này include file <strong>Console\Getopt.php</strong> trong thư viện PEAR do đó có thể bạn sẽ phải đổi lại đường dẫn của chúng cho phù hợp.</p>
<p>Trong trường hợp của tôi, kết quả hiển thị trên màn hình sau khi thực thi câu lệnh trên như sau:<br />
Cú pháp của câu lệnh pprofp như sau:</p>
<pre class="brush: plain;">pprofp &lt;option&gt; &lt;tracefile&gt;</pre>
<p>Trong đó &lt;tracefile&gt; là file ghi lại quá trình thực thi PHP script do APD sinh ra. &lt;option&gt; là những lựu chọn. Bạn có thể xem chi tiết những option này bằng cách gõ lệnh</p>
<pre class="brush: plain;">php pprofp</pre>
<p>Trong câu lệnh tôi đã sử dụng, <em>&lt;tracefile&gt;</em> là file <strong>C:\temp\pprof.02672.0</strong>, tôi dùng option<em> </em><strong>-u</strong> vì muốn sắp xếp các lời gọi hàm theo thời gian thực thi từ cao đến thâp.</p>
<p>Nhìn vào kết quả, chúng ta thấy rằng hàm <em>strpos</em> chiếm nhiêu thời gian thực thi nhất và được gọi 3849 lần:<br />
<a href="http://howtophp.net/wp-content/uploads/2010/08/pprofp-screenshot-1.jpg"><img class="aligncenter size-full wp-image-292" title="pprofp-screenshot-1" src="http://howtophp.net/wp-content/uploads/2010/08/pprofp-screenshot-1.jpg" alt="" width="490" height="251" /></a></p>
<p>Ngoài ra chúng ta cũng có thể xem thứ tự thực thi các hàm trong ứng dụng. Sử dụng câu lệnh sau:</p>
<pre class="brush: plain;">php pprofp -t C:\temp\pprof.02672.0</pre>
<p>Chúng ta sẽ thu được kết quả dưới dạng cây, trong đó hiển thị thứ tự thực thi của các hàm trong ứng dụng. Thông tin này sẽ vô cùng hữu ích nếu chúng ta cần biết chi tiết các hàm trong ứng dụng được gọi như thế nào.</p>
<p>Ngoài function <em>apd_set_pprof_trace()</em> trên, APD còn có nhiều function khác để thuận tiện cho việc debug và profile ứng dụng PHP. Các bạn có thể tham khảo những hàm này tại <a title="đây" href="http://www.php.net/manual/en/ref.apd.php" target="_blank">đây</a>.<br />
Bài viết này chỉ mang tính giới thiệu. APD là một công cụ rất mạnh và hữu ích. Tuy nhiên nói gì thì nói, nó cũng chỉ là một công cụ. Vấn đề là sử dụng nó như thế nào sao cho hợp lý và đem lại hiệu quả cao nhất.
</pre>
]]></content:encoded>
			<wfw:commentRss>http://howtophp.net/index.php/2010/08/ph%e1%ba%a7n-2-s%e1%bb%ad-d%e1%bb%a5ng-apd.html/feed</wfw:commentRss>
		<slash:comments>328</slash:comments>
		</item>
		<item>
		<title>Kỳ 2: Design Pattern – Ứng dụng Adaptor Pattern xây dựng module thanh toán cho gian hàng</title>
		<link>http://howtophp.net/index.php/2010/08/k%e1%bb%b3-2-design-pattern-%e1%bb%a9ng-d%e1%bb%a5ng-adapto-pattern-xay-d%e1%bb%b1ng-module-thanh-toan-cho-gian-hang.html</link>
		<comments>http://howtophp.net/index.php/2010/08/k%e1%bb%b3-2-design-pattern-%e1%bb%a9ng-d%e1%bb%a5ng-adapto-pattern-xay-d%e1%bb%b1ng-module-thanh-toan-cho-gian-hang.html#comments</comments>
		<pubDate>Mon, 16 Aug 2010 18:02:27 +0000</pubDate>
		<dc:creator>banksy</dc:creator>
				<category><![CDATA[1 - Nền tảng]]></category>
		<category><![CDATA[adaptor pattern]]></category>
		<category><![CDATA[design pattern]]></category>
		<category><![CDATA[payment]]></category>
		<category><![CDATA[shopping]]></category>

		<guid isPermaLink="false">http://howtophp.net/?p=217</guid>
		<description><![CDATA[“Người ta không phát minh lại cái bánh xe”, bởi vì nó đã được người khác phát minh ra trước đó. Nhưng còn tệ hơn nữa khi chính bạn đã phát minh ra cái bánh xe và sau đó bạn tìm cách phát minh lại nó. Trong lập trình, rất nhiều lúc bạn phải phát [...]]]></description>
			<content:encoded><![CDATA[<p><strong>“Người ta không phát minh lại cái bánh xe”</strong>, bởi vì nó đã được người khác phát minh ra trước đó. Nhưng còn tệ hơn nữa khi chính bạn đã phát minh ra cái bánh xe và sau đó bạn tìm cách phát minh lại nó.</p>
<p>Trong lập trình, rất nhiều lúc bạn phải phát triển một tính năng nào đó cho một sản phẩm phần mềm, và thật may mắn, bạn phát hiện ra một cái tương tự như thế đã được bạn viết ra trước đây. Nhưng vấn đề là những đoạn mã trước đó bạn viết ra chỉ để phục vụ cho công việc của thời điểm đó, và bạn sẽ phải đổ rất nhiều mồ hôi để làm một loạt các thao tác: copy/cut/paste/delete/rename… để sử dụng chúng trong hoàn cảnh mới. Những lúc như vậy, bạn chỉ ước rằng trước đây mình chịu khó dùng cái đầu nhiều hơn một chút, module hóa chức năng đó tốt hơn một tí, code cẩn thận hơn một tẹo… để bây giờ đỡ hao tâm khổ tứ hơn nhiều lần. <strong>Design Pattern</strong> (tạm dịch là Mẫu thiết kế) trong lập trình chính là các giải pháp về thiết kế, tổ chức code cho từng tình huống, vấn đề khác nhau. Mỗi Design Pattern thường được đưa ra với một cặp <strong>“Problem” – “Solution” (Vấn đề &#8211; Giải pháp)</strong>, và được gọi với một cái tên dùng gợi nhớ ý nghĩa của nó.</p>
<p>Trong bài này, chúng ta sẽ lướt qua một số mẫu design pattern phổ biến, sử dụng các kịch bản tình huống xây dựng một gian hàng trực tuyến để thấy rõ các vấn đề và giải pháp trong từng hoàn cảnh.</p>
<h2><strong>Ứng dụng Adaptor Pattern xây dựng module Thanh toán cho gian hàng<br />
</strong></h2>
<p style="text-align: center;"><strong><a href="http://howtophp.net/wp-content/uploads/2010/08/online-payment.jpg"><img class="aligncenter size-full wp-image-229" title="online-payment" src="http://howtophp.net/wp-content/uploads/2010/08/online-payment.jpg" alt="" width="492" height="182" /></a><br />
</strong></p>
<p>Chức năng quan trọng nhất mà mọi gian hàng cần phải xây dựng đó là module thanh toán. Hiện nay có rất nhiều giải pháp cho việc thanh toán trực tuyến, trong đó một vài cái tên quen tai như: Paypal, Liberty Reverse, Visa Card, Master Card, thậm chí là ATM. Thật tuyệt vời nếu chúng ta có thể xây dựng một chức năng thanh toán có thể cho phép người dùng lựa chọn bất cứ loại giao dịch nào thuận tiện nhất đối với họ. Chức năng này sẽ phải cài đặt từng module riêng rẽ cho mỗi loại phương thức giao dịch, nhưng chúng ta muốn module quản lý thanh toán sẽ nhìn từng module kia dưới một hình thức duy nhất, đó chính là lý thuyết Đa hình mà chúng ta đã tìm hiểu ở phần trước. Thật rối rắm! Nhưng bạn sẽ thấy nó rõ ràng hơn sau khi theo dõi các ví dụ được lấy ra từ một thư viện PHP Payment Library đã được xây dựng sẵn:</p>
<p>Trước hết chúng ta sẽ xây dựng một abstraction class, định nghĩa API cho các phương thức giao dịch được chấp nhận.</p>
<pre class="brush: php;">
abstract class PaymentGateway
{
    // Holds the last error encountered
    public $lastError;
    // Field array to submit to gateway
    public $fields = array();
    // Payment gateway URL
    public $gatewayUrl;

    // Initialization constructor
    public function __construct()
    {
        // Some default values of the class
        $this-&gt;lastError = '';
    }

    // Adds a key=&gt;value pair to the fields array
    public function addField($field, $value)
    {
        $this-&gt;fields[&quot;$field&quot;] = $value;
    }

    // Submit Payment Request
    public function submitPayment()
    {
        $this-&gt;prepareSubmit();
        // POST form with some hidden elements to gateway
    }

    // Perform any pre-posting actions
    protected function prepareSubmit()
    {
        // Fill if needed
    }

    /* Some IPN properties and functions definition */
}
</pre>
<p>Tất cả các phương thức giao dịch trực tuyến (Paypal, Authorize.net, 2Checkout…) đều thực hiện những tiến trình thanh toán chung như sau:</p>
<p>1  &#8211; Thiết đặt một số thông tin giao dịch trong các hidden field của form giao dịch.</p>
<p>2 – Người dùng điền thêm một số thông tin tùy biến (phụ thuộc vào từng loại giao dịch) trên form, và bấm submit.</p>
<p>3 – Tiến trình sẽ chuyển sang cổng thanh toán (qua một gateway URL), từ lúc đó cổng thanh toán sẽ thực hiện toàn bộ quá trình còn lại.</p>
<p>4 – Trả về (redirect) website bán hàng một mã xác định trạng thái giao dịch (thành công hay lỗi).</p>
<p>Với tiến trình chung như trên, lớp trừu tượng của chúng ta sẽ có:</p>
<p><strong>- Những thuộc tính cơ bản như: </strong></p>
<p>+ lastError: Lưu lại lỗi cuối cùng.</p>
<p>+ gatewayUrl: url của cổng thanh toán.</p>
<p>+ fields: mảng chứa các trường thiết đặt trong form…</p>
<p><strong>- Những phương thức cơ bản:</strong></p>
<p>+ prepareSubmit(): Các thao tác trước khi bắt đầu giao dịch.</p>
<p>+ addField(): Thêm các trường thiết đặt.</p>
<p>+ submitPayment(): Thực hiện giao dịch.</p>
<p>Và công việc tiếp theo khá rõ ràng, chúng ta sẽ lần lượt xem xét từng giao thức giao dịch và xây dựng module thanh toán cho từng loại dựa trên API của lớp trừu tượng PaymentGateway.</p>
<p><strong>Bắt đầu từ <a href="https://www.paypal.com/">Paypal</a>:</strong></p>
<pre class="brush: php;">
class Paypal extends PaymentGateway
{
    // Initialize the Paypal gateway
    public function __construct()
    {
        parent::__construct();
        // Some default values of the class
        $this-&gt;gatewayUrl = 'https://www.paypal.com/cgi-bin/webscr';
        // Populate $fields array with a few default
        $this-&gt;addField('rm', '2');           // Return method = POST
        $this-&gt;addField('cmd', '_xclick');
    }

    // Validate the IPN notification
    public function validateIpn()
    {
        // Paypal IPN processing
    }
}
</pre>
<p>Với định nghĩa trên, chúng ta đã xây dựng hoàn thành một module thanh toán cho Paypal, chỉ bằng cách thêm một vài trường thiết đặt. Điểm mở rộng lớn nhất từ lớp trừu tượng đó là thực thi phương thức validateIpn(), cài đặt dịch vụ IPN của Paypal vào module thanh toán. Về IPN các bạn có thể tham khảo tại đây &#8211; <a href="http://en.wikipedia.org/wiki/Instant_Payment_Notification">Instant Payment Notification</a>, tuy nhiên nói nôm na thì IPN là dịch vụ của các dịch vụ thanh toán thông báo trạng thái giao dịch realtime cho ứng dụng (và người dùng).</p>
<p><strong>Tiếp đến, giả sử bạn cần cài đặt module thanh toán cho <a href="http://www.2checkout.com/community/">2Checkout</a>:</strong></p>
<pre class="brush: php;">
class TwoCo extends PaymentGateway
{
    // Secret word to be used for IPN verification
    public $secret;

    // Initialize the 2CheckOut gateway
    public function __construct()
    {
        parent::__construct();
        // Some default values of the class
        $this-&gt;gatewayUrl = 'https://www.2checkout.com/checkout/purchase';
        $this-&gt;ipnLogFile = '2co.ipn_results.log';
    }

    // Set the secret word
    public function setSecret($word)
    {
        if (!empty($word))
        {
            $this&gt;secret = $word;
        }
    }

    // Validate the IPN notification
    public function validateIpn()
    {
        // 2Checkout IPN proccessing
    }
}
</pre>
<p>Hoàn toàn tương tự như Paypal, nhưng ở 2Checkout thấy ngay một điểm khác đó là xuất hiện trường $secret, một mã bí mật được sử dụng trong quá trình validate IPN của 2Checkout, và hàm setSecret().</p>
<p>Như vậy rất nhanh chóng, chúng ta xây dựng xong 2 module thanh toán cho 2 dịch vụ thanh toán trực tuyến: Paypal và 2Checkout. Gian hàng của bạn đã có thể chấp nhận được và sẵn sàng cho một cuộc mua bán đậm mùi tiền:</p>
<pre class="brush: php;">
// Include the paypal library
include_once ('Paypal.php');

// Create an instance of the paypal library
$myPaypal = new Paypal();

// Specify your paypal email
$myPaypal-&gt;addField('business', 'YOUR_PAYPAL_EMAIL');

// Specify the currency
$myPaypal-&gt;addField('currency_code', 'USD');

// Specify the url where paypal will send the user on success/failure
$myPaypal-&gt;addField('return', 'http://YOUR_HOST/payment/paypal_success.php');
$myPaypal-&gt;addField('cancel_return', 'http://YOUR_HOST/payment/paypal_failure.php');

// Specify the url where paypal will send the IPN
$myPaypal-&gt;addField('notify_url', 'http://YOUR_HOST/payment/paypal_ipn.php');

// Specify the product information
$myPaypal-&gt;addField('item_name', 'T-Shirt');
$myPaypal-&gt;addField('amount', '9.99');
$myPaypal-&gt;addField('item_number', '001');

// Specify any custom value
$myPaypal-&gt;addField('custom', 'muri-khao');
</pre>
<p>Hoặc với 2Checkout:</p>
<pre class="brush: php;">
// Include the paypal library
include_once ('TwoCo.php');

// Create an instance of the authorize.net library
$my2CO = new TwoCo();

// Specify your 2CheckOut vendor id
$my2CO-&gt;addField('sid', 'YOUR_VENDOR_ID');

// Specify the order information
$my2CO-&gt;addField('cart_order_id', rand(1, 100));
$my2CO-&gt;addField('total', '9.99');

// Specify the url where authorize.net will send the IPN
$my2CO-&gt;addField('x_Receipt_Link_URL', 'http://YOUR_HOST/payment/twoco_ipn.php');
$my2CO-&gt;addField('tco_currency', 'USD');
$my2CO-&gt;addField('custom', 'muri-khao');
</pre>
<p>Với một module thanh toán cross-gateway như thế, chúng ta sẽ có một hàm kiểu như:</p>
<pre class="brush: php;">
function payment($paymentGateway)
{
    $paymentGateway-&gt;submitPayment();
}
</pre>
<p>Một ví dụ tương tự như thế về những chiếc TV và Đa hình đã có ở phần trước. Chúng ta sẽ hiểu với bất cứ một phương thức giao dịch nào sử dụng API của PaymentGateway đều cài đặt hàm submitPayment() và đều có thể sử dụng để thanh toán qua hàm payment() trên.</p>
<p>Lúc này có lẽ giải pháp sử dụng Adaptor Pattern đã rõ ràng hơn. Khi có nhiều classes thực thi cùng 1 dịch vụ và sử dụng chung một API, thì chúng ta có thể sử dụng Adaptor Pattern để tạo ra một giao diện chung và tận dụng sức mạnh của Đa hình để khai thác tối đa sự tiện ích của lập trình hướng đối tượng. Có thể thấy việc phát triển các module cho từng phương thức thanh toán đã tường minh và sáng sủa hơn. Với một thiết kế tốt như thế, chương trình của chúng ta sẽ có thể dễ dàng bảo trì, cải tiến, mở rộng trong tương lai.</p>
<p>Adaptor Pattern cũng có thể hữu dụng trong một số trường hợp khác:</p>
<p><strong>- Problem A:</strong> Khi sử dụng các library mã đóng với API không thể thay đổi, trong khi chúng ta cần một giao diện sử dụng khác, để tương thích với một framework chẳng hạn. Thì chúng ta sẽ định nghĩa một third-party class sử dụng Adaptor Pattern để tạo ra một class mới với giao diện tương thích. Trong trường hợp chúng ta có thể hình dung class đó như một “bộ chuyển đổi” (adaptor), tương tự như các bộ chuyển đổi thường thấy trong thường ngày: chuyển từ phích cắm nguồn 3 chân sang 2 chân, từ cổng mini-USB sang USB 2.0… với mục đích sử dụng cho các thiết bị khác nhau.</p>
<p><strong>- Problem B:</strong> Phần core của PHP được xây dựng từ rất lâu với các thư viện hàm tích hợp vẫn theo hướng thủ tục (chứ không phải hướng đối tượng). Và có rất nhiều thao tác sử dụng cần thiết phải gọi 1 loạt các hàm liên tiếp nhau và được liên kết thông qua một biến, handler. Ví dụ như khi cần làm việc với cơ sở dữ liệu MySQL, chúng ta luôn phải thực hiện việc gọi các hàm tuần tự:</p>
<pre class="brush: php;">
$user=&quot;username&quot;;
$password=&quot;password&quot;;
$database=&quot;database&quot;;
mysql_connect(localhost,$user,$password);
@mysql_select_db($database) or die( &quot;Unable to select database&quot;);
$query=&quot;SELECT * FROM table&quot;;
mysql_query($query);
mysql_close();
</pre>
<p>Chúng ta có thể sử dụng Adaptor Pattern để tạo ra một adaptor, làm nhiệm vụ thực hiện tất cả những tiến trình đó và lưu giữ kết nối với database trên một handler – là một thuộc tính của adaptor class. Ví dụ cho phần này có thể xem thêm ở chương 2, cuốn Advance PHP Programming.</p>
<p><strong>Tham khảo:</strong></p>
<p>Chapter 2, Part 1, Advance PHP Programming.</p>
<p>Toàn bộ phần code minh họa được bóc tách ra từ thư viện PHP Payment Library. Có thể download tại đây -  [<a href="http://howtophp.net/wp-content/uploads/2010/08/payment.zip">PHP Payment Library</a>]</p>
]]></content:encoded>
			<wfw:commentRss>http://howtophp.net/index.php/2010/08/k%e1%bb%b3-2-design-pattern-%e1%bb%a9ng-d%e1%bb%a5ng-adapto-pattern-xay-d%e1%bb%b1ng-module-thanh-toan-cho-gian-hang.html/feed</wfw:commentRss>
		<slash:comments>340</slash:comments>
		</item>
		<item>
		<title>[Sams] Advance PHP Programming</title>
		<link>http://howtophp.net/index.php/2010/08/sams-advance-php-programming.html</link>
		<comments>http://howtophp.net/index.php/2010/08/sams-advance-php-programming.html#comments</comments>
		<pubDate>Mon, 16 Aug 2010 02:39:44 +0000</pubDate>
		<dc:creator>banksy</dc:creator>
				<category><![CDATA[3 - Kho báu]]></category>
		<category><![CDATA[Ebooks]]></category>
		<category><![CDATA[advanced php]]></category>
		<category><![CDATA[ebook]]></category>

		<guid isPermaLink="false">http://howtophp.net/?p=236</guid>
		<description><![CDATA[Tên sách: Advance PHP Programming Tác giả: George Schlossnagle Xuất bản: 2004 Định dạng ebook: CHM/3.16MB Mô tả: Cuốn sách viết về những kỹ thuật lập trình nâng cao và chuyên sâu về ngôn ngữ PHP, yêu cầu bạn phải có những kiến thức lập trình PHP căn bản từ trước khi đọc. Những chủ [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://howtophp.net/wp-content/uploads/2010/08/advance-php-cover.png"><img class="aligncenter size-full wp-image-237" title="advance-php-cover" src="http://howtophp.net/wp-content/uploads/2010/08/advance-php-cover.png" alt="" width="423" height="545" /></a></p>
<p><strong>Tên sách:</strong> Advance PHP Programming</p>
<p><strong>Tác giả:</strong> George Schlossnagle</p>
<p><strong>Xuất bản:</strong> 2004</p>
<p><strong>Định dạng ebook:</strong> CHM/3.16MB</p>
<p><strong>Mô tả:</strong></p>
<p>Cuốn sách viết về những kỹ thuật lập trình nâng cao và chuyên sâu về ngôn ngữ PHP, yêu cầu bạn phải có những kiến thức lập trình PHP căn bản từ trước khi đọc. Những chủ đề thú vị tác giả đưa ra đều hỗ trợ bạn rất nhiều trong việc xây dựng các ứng dụng, hệ thống lớn trên nền web.</p>
<p><strong>Download:</strong></p>
<p><a href="http://howtophp.net/wp-content/uploads/2010/08/Advanced-PHP-Programming-Schlossnagle-Sams-2004.zip">Advanced PHP Programming &#8211; Schlossnagle &#8211; Sams &#8211; 2004</a></p>
]]></content:encoded>
			<wfw:commentRss>http://howtophp.net/index.php/2010/08/sams-advance-php-programming.html/feed</wfw:commentRss>
		<slash:comments>2766</slash:comments>
		</item>
		<item>
		<title>Phần 1 – Cài đặt APD</title>
		<link>http://howtophp.net/index.php/2010/08/ph%e1%ba%a7n-1-cai-dat-apd.html</link>
		<comments>http://howtophp.net/index.php/2010/08/ph%e1%ba%a7n-1-cai-dat-apd.html#comments</comments>
		<pubDate>Wed, 11 Aug 2010 03:54:38 +0000</pubDate>
		<dc:creator>nonggiatu</dc:creator>
				<category><![CDATA[2 - Vượt trội]]></category>
		<category><![CDATA[advanced php debugger]]></category>
		<category><![CDATA[APD]]></category>
		<category><![CDATA[performance profiling]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[thủ thuật]]></category>
		<category><![CDATA[tối ưu]]></category>

		<guid isPermaLink="false">http://howtophp.net/?p=192</guid>
		<description><![CDATA[Trên internet đã có rất nhiều hướng dẫn cài đặt APD trên linux, tuy nhiên lại rất ít hướng dẫn cài đặt APD trên windows. Do đó phần này tôi chủ yếu tập trung vào việc cài đặt APD trên windows. Hệ điều hành tôi sử dụng là windowsXP và chạy xammp server. Tuy nhiên [...]]]></description>
			<content:encoded><![CDATA[<p>Trên internet đã có rất nhiều hướng dẫn cài đặt APD trên linux, tuy  nhiên lại rất ít hướng dẫn cài đặt APD trên windows. Do đó phần này tôi  chủ yếu tập trung vào việc cài đặt APD trên windows. Hệ điều hành tôi sử  dụng là windowsXP và chạy xammp server. Tuy nhiên cách này hoàn toàn có thể áp dụng được nếu bạn sử dụng wamp server hay tự cài đặt thủ công apache và PHP.<img title="More..." src="http://howtophp.net/wp-includes/js/tinymce/plugins/wordpress/img/trans.gif" alt="" /></p>
<h3>Cài đặt</h3>
<h4>Cài đặt APD trên linux</h4>
<p>Bạn có thể cài đặt APD bằng cách sử dụng câu lệnh:</p>
<pre class="brush: php;">pear install apd</pre>
<h4>Cài đặt APD trên windows</h4>
<p>Để sử dụng APD trên môi trường windows chúng ta cần có file <strong>php_apd.dll</strong>. Thông thường sau khi cài đặt PHP trên windows, file này có trong thư mục con<em> ext </em>của thư mục chúng ta cài PHP. (ví dụ <em>C:\php\ext</em>) Nếu không tìm thấy, các bạn có thể tìm nó trong gói <strong>PECL 5.x.x Win32 binaries</strong> tại <a title="đây" href="http://www.php.net/downloads.php" target="_blank">đây</a>, trong đó 5.x.x là tên version. Sau khi download và giải nén, hãy tìm và copy file <strong>php_apd.dll </strong>đưa vào thư mục <em>ext</em> nói trên.</p>
<h3>Cấu hình</h3>
<p>Sau khi đã có file mở rộng, chúng ta cần cấu hình trong file php.ini để chạy nó. Vào php.ini và thêm vào:</p>
<pre class="brush: php;">extension=php_apd.dll</pre>
<p>Sau đó lưu file php.ini lại và khởi động lại apache.<br />
Để kiểm tra APD đã được chạy chưa, chúng ta tạo một trang php chứa câu  lệnh phpinfo();. Nếu thấy xuất hiện thông tin về APD tức là việc cài đặt  đã thành công:</p>
<p style="text-align: center;"><a href="http://howtophp.net/wp-content/uploads/2010/08/apd.jpg"><img class="aligncenter size-full wp-image-207" style="border: 1px solid black;" title="apd installed successfully screenshot" src="http://howtophp.net/wp-content/uploads/2010/08/apd.jpg" alt="apd installed successfully screenshot" width="490" height="304" /></a></p>
<p style="text-align: left;">Tham khảo:</p>
<ul>
<li><a title="APD manual" href="http://php.net/manual/en/book.apd.php">APD manual</a></li>
<li><a title="PHP performance profiling" href="http://www.linuxjournal.com/article/7213">PHP performance profiling</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://howtophp.net/index.php/2010/08/ph%e1%ba%a7n-1-cai-dat-apd.html/feed</wfw:commentRss>
		<slash:comments>384</slash:comments>
		</item>
		<item>
		<title>Kỳ 1: Những chiếc TV mới trong OOP</title>
		<link>http://howtophp.net/index.php/2010/08/k%e1%bb%b3-1-nh%e1%bb%afng-chi%e1%ba%bfc-tv-m%e1%bb%9bi-trong-oop.html</link>
		<comments>http://howtophp.net/index.php/2010/08/k%e1%bb%b3-1-nh%e1%bb%afng-chi%e1%ba%bfc-tv-m%e1%bb%9bi-trong-oop.html#comments</comments>
		<pubDate>Thu, 05 Aug 2010 14:12:28 +0000</pubDate>
		<dc:creator>banksy</dc:creator>
				<category><![CDATA[1 - Nền tảng]]></category>
		<category><![CDATA[oop]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[php5]]></category>

		<guid isPermaLink="false">http://howtophp.net/?p=122</guid>
		<description><![CDATA[Các kiến thức chung về OOP trên PHP sẽ không được đề cập đến trong bài viết này, bởi vì bạn có thể dễ dàng tìm thấy chúng trong bất cứ tài liệu nào về PHP. Tham khảo về OOP một cách đầy đủ ở chương 6, 7 của cuốn &#8220;Beginning PHP and MySQL5 From [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://howtophp.net/wp-content/uploads/2010/08/tv.png"><img class="aligncenter size-full wp-image-173" title="tv" src="http://howtophp.net/wp-content/uploads/2010/08/tv.png" alt="" width="480" height="267" /></a></p>
<p><a href="http://howtophp.net/wp-content/uploads/2010/08/tv.png"></a>Các kiến thức chung về OOP trên PHP sẽ không được đề cập đến trong bài viết này, bởi vì bạn có thể dễ dàng tìm thấy chúng trong bất cứ tài liệu nào về PHP. Tham khảo về OOP một cách đầy đủ ở chương 6, 7 của cuốn &#8220;<a href="http://howtophp.net/index.php/2010/08/apress-beginning-php-and-mysql5-from-novice-to-professional-2nd-edition.html" target="_blank">Beginning PHP and MySQL5 From Novice to Professional – Apress</a>&#8220;, các cú pháp làm việc với đối tượng PHP có tại trang <a href="http://www.php.net/manual/en/language.oop5.php" target="_blank">PHP-Manual</a>. Ở bài viết này sẽ chủ yếu tán gẫu về một vài câu chuyện giúp gợi nhớ những thứ OOP mang lại cho chúng ta.</p>
<p>Trên mọi ngôn ngữ lập trình, mọi lập trình viên theo đuổi kỹ thuật hướng đối tượng luôn nắm trong tay 3 thứ mà nó mang lại cho họ:</p>
<p><strong>1 &#8211; Encapsulation (Đóng gói)</strong></p>
<p>Trong thế giới của bạn, bạn đang sử dụng rất nhiều thứ mà không cần phải quan tâm nó được tạo ra như thế nào, hay cơ chế hoạt động ra sao. Việc duy nhất bạn cần làm là nắm lấy remote, sử dụng một giao diện để điều khiển hoạt động của nó. Những thứ đó như: TV, radio, tủ lạnh, máy giặt… Kỹ thuật lập trình hướng đối tượng cố gắng mô tả chương trình gần với thế giới thực, với các thực thể (đối tượng). Chúng được đóng gói trong các Class, và được che giấu đi những cài đặt bên trong. Người dùng chỉ việc giao tiếp với các đối tượng này thông qua một giao diện nào đó (interface).</p>
<p>VD: Định nghĩa của một chiếc TV:</p>
<pre class="brush: php;">
class TV
{
    protected $screen;
    protected $speaker;
    public function __construct() {
        $this-&gt;screen = new Screen();
        $this-&gt;speaker = new Speaker();
        …
    }

    public turnOn() {
        // some code to turn on TV
    }

    public playChannel($channel) {
        // some code to play a TV channel
    }
}
</pre>
<p>Và khi trong chương trình của bạn muốn xuất hiện một cái TV, bạn chỉ cần làm những việc đơn giản như những việc bạn vẫn làm hằng ngày:</p>
<pre class="brush: php;">
$tv = new TV(); // Mua 1 chiếc TV mới
$tv-&gt;turnOn(); // Bật nó lên
$tv-&gt;playChannel(10); // Mở kênh 10
</pre>
<p>Bạn không cần phải quan tâm nó được tạo ra như thế nào, làm sao để có thể vận hành, và làm sao để xem được kênh bạn chọn. Bởi vì tất cả đã được những tay thợ khác đóng gói trong một cái hộp, mà chúng ta vẫn quen gọi nó là cái “TV”. Và khi nhà sản xuất thay đổi những thứ bên trong cái TV đó, bạn cũng không cần phải thay đổi cách bấm remote.</p>
<p><strong>2 &#8211; Inheritance (Kế thừa)</strong></p>
<p>Những tay thợ đã làm ra một chiếc TV, nhưng bây giờ bọn họ muốn làm ra một chiếc TV màn hình phẳng và được gắn thêm bộ loa công suất lớn để kiếm cớ tăng giá cho cái TV đó trong một Hifi model mới. Tất nhiên rồi, họ không cần phải nghiên cứu, thiết kế lại từ đầu một chiếc TV. Bởi vì đơn giản họ chỉ cần lấy công nghệ chế tạo TV cũ ra, và thay thế một số linh kiện trong đó. Họ được kế thừa những thứ trước đó họ đã làm.</p>
<pre class="brush: php;">
class HifiTV extends TV
{
    public __construct() {
        $this&gt;screen = new HifiScreen();
        $this-&gt;speaker = new HifiSpeaker();
    }
}
</pre>
<p>Kế thừa trong hướng đối tượng cũng như vậy, đó là việc sử dụng lại các đối tượng đã được định nghĩa trong các ứng dụng khác nhằm tiết kiệm công sức cho lập trình viên. Một class được thiết kế tốt có thể được sử dụng trong rất nhiều các ứng dụng liên quan.</p>
<p><strong>Interfaces và Abstraction Class</strong></p>
<p>Trong Kế thừa của OOP, có một điểm cần chú ý: Đó là mỗi class chỉ được kế thừa từ một class cha (cũng như việc mỗi người con chỉ được sinh ra bởi một người cha trong thực tế).</p>
<pre class="brush: php;">class HifiTV extends TV, Radio {…} // Fatal Error</pre>
<p>Tuy nhiên, PHP cũng như hầu hết các ngôn ngữ khác, cung cấp 2 định nghĩa có thể giải quyết vấn đề có nhiều lựa chọn về template hơn khi định nghĩa một đối tượng mới, đó là: Interface và Abstraction.</p>
<p><strong><em>Interface</em></strong></p>
<p>Dịch là Giao diện, trong một interface sẽ không thực thi bất cứ một phương thức nào, nó đơn giản chỉ như là một khuôn mẫu, prototype cho một định nghĩa class khác. Khi một class định nghĩa theo khuôn dạng của một (hoặc nhiều) interface, nó bắt buộc phải cài đặt thực thi cho tất cả các phương thức được khai báo trong các interfaces đó.</p>
<p><strong><em>Abstraction Class</em></strong></p>
<p>Dịch là Lớp trừu tượng, nó nằm giữa một class bình thường và một interface. Tức là trong một class bình thường thì sẽ định nghĩa đầy đủ mọi phương thức của class đó. Trong khi ở một interface, người ta chỉ đưa ra một khuôn mẫu cho các lớp khác tuân theo, không có bất cứ cài đặt thực thi nào trong interface. Còn với lớp trừu tượng, nó sẽ chứa cả các phương thức được cài đặt và các prototype cho các phương thức sẽ phải được cài đặt ở các lớp thừa kế nó.</p>
<p>Các định nghĩa và ví dụ về 2 khái niệm này có thể xem tại Manual ở link đầu bài viết.</p>
<p><strong>3- Polymorphism (Đa hình)</strong></p>
<p>Đa hình là một khái niệm khá trừu tượng, và chúng ta sẽ lại viện dẫn lại ví dụ trên để hiểu rõ nó. Bây giờ những tay thợ đã sản xuất ra 2 mẫu TV, một cái TV đời cũ và một Hifi-TV. Về chức năng thì chúng gần như là giống nhau, nhưng chỉ khác ở chỗ Hifi-TV có màn hình và loa to hơn. Tuy nhiên sẽ bắt đầu xuất hiện khác biệt lớn khi những tay thợ muốn tính ra giá thành của các loại sản phẩm:</p>
<pre class="brush: php;">
class TV
{
    …
    public getPrice() {
        // return product price
    }
}

class HifiTV extends TV
{
    …
    public getPrice() {
        // return product price + 100$ for new model
    }
}

function showPrice($aTV)
{
    echo ‘Price: ‘.$aTV-&gt;getPrice();
}
</pre>
<p>Hàm tính giá getPrice() của hai loại TV này khác nhau do Hifi-TV là một sản phẩm mới, tân tiến hơn, nó phải đi kèm theo các chi phí khác. Tuy nhiên với Đa hình, hàm showPrice() sẽ hiển thị ra giá của sản phẩm phụ thuộc vào việc $aTV là chiếc TV như thế nào. Bạn không cần phải thay đổi hàm đó cho từng loại sản phẩm:</p>
<pre class="brush: php;">
showPrice($old_tv); // Trả về giá của model cũ
showPrice($hifi_tv);  // Trả về giá của Hifi model mới
</pre>
<p><strong>Type Hinting</strong></p>
<p>Như ở ví dụ trên với hàm showPrice(), tham số truyền vào phải là một đối tượng đã định nghĩa hàm getPrice() để trả về giá của nó. Hoặc tường minh hơn, hàm showPrice muốn trả về giá của một chiếc TV. Như vậy lúc một đối tượng được truyền vào làm tham số không phải là một chiếc TV (thuộc class TV hay là một kế thừa của TV) thì hàm showPrice() sẽ hoạt động không như mong muốn, thậm chí gây lỗi.</p>
<p>Type Hinting (hay Type Checking) là một đặc tính mới được PHP5 cung cấp, nó sẽ cực kỳ hữu ích trong các trường hợp thực thi sử dụng Đa hình. Type Hinting sẽ cho phép thêm vào một thành phần xác định kiểu tham số cho đối tượng truyền vào hàm, như hầu hết các ngôn ngữ lập trình khác đang hỗ trợ để tường minh hơn:</p>
<pre class="brush: php;">
function showPrice(TV $aTV)
{
    echo ‘Price: ‘.$aTV-&gt;getPrice();
}
</pre>
<p>Với định nghĩa như trên, khi $aTV là một đối tượng TV hay Hifi-TV (kế thừa từ TV) đều được chấp nhận, những đối tượng không phải là một instance của TV sẽ bị báo lỗi “Fatal Error”.</p>
<p><strong>4 – Các phương thức OOP đặc biệt cung cấp bởi PHP5</strong></p>
<p><strong><em>Accessors:</em></strong></p>
<p>Hay còn gọi là mutators (bộ biến đổi), cung cấp 2 phương thức đặc biệt: __set() và __get() cho phép truy cập và biến đổi thuộc tính của một đối tượng.</p>
<p><strong><em>Autoload:</em></strong></p>
<p>Cung cấp phương thức __autoload(), phương thức này được gọi khi trong chương trình thực hiện khởi tạo một đối tượng dưới một class nào đó.</p>
<p><strong><em>Call:</em></strong></p>
<p>Cung cấp phương thức __call(), phương thức này được gọi khi người dùng truy cập đến một phương thức không được định nghĩa trong class.</p>
<p>Tất cả các phương thức trên đều yêu cầu phải overloading khi muốn sử dụng chúng.</p>
<blockquote><p><strong>[Tips] Các hàm hỗ trợ OOP (Helper Functions)</strong></p>
<p>PHP5 cung cấp một bộ các hàm hỗ trợ OOP cho lập trình viên, chúng ta cũng sẽ lướt qua để ghi nhớ sử dụng lúc cần thiết:</p>
<p><strong>+ boolean class_exists(string class_name):</strong> Kiểm tra một class đã được định nghĩa hay chưa.<br />
<strong> + string get_class(object):</strong> Trả về tên của class định nghĩa object.<br />
<strong> + array get_class_methods(mixed class_name):</strong> Trả về một mảng các phương thức được định nghĩa trong class_name.<br />
<strong> + array get_class_vars(string class_name):</strong> Trả về một mảng tất cả các thuộc tính trong class_name.<br />
<strong> + array get_declared_classes(void):</strong> Trả về một mảng tất cả các class định nghĩa trong script hiện thời.<br />
<strong> + array get_object_vars(object):</strong> Trả về một mảng tất cả các thuộc tính của object.<br />
<strong> + string get_parent_class(mixed object):</strong> Tên class cha của class mà object thuộc về.<br />
<strong> + boolean interface_exists(string interface_name):</strong> Kiểm tra một interface đã tồn tại hay chưa.<br />
<strong> + boolean is_a(object, string class_name):</strong> Kiểm tra một object có thuộc về một class hay không.<br />
<strong> + boolean is_subclass_of(object, string class_name):</strong> Kiểm tra một object có phải là class con của một class_name hay không.<br />
<strong>+ boolean method_exists(object, string method_name):</strong> Kiểm tra xem một phương thức có trong một object hay không.</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://howtophp.net/index.php/2010/08/k%e1%bb%b3-1-nh%e1%bb%afng-chi%e1%ba%bfc-tv-m%e1%bb%9bi-trong-oop.html/feed</wfw:commentRss>
		<slash:comments>3840</slash:comments>
		</item>
		<item>
		<title>[Apress] Beginning PHP5 and MySQL5 From Novice to Professional 2nd Edition</title>
		<link>http://howtophp.net/index.php/2010/08/apress-beginning-php-and-mysql5-from-novice-to-professional-2nd-edition.html</link>
		<comments>http://howtophp.net/index.php/2010/08/apress-beginning-php-and-mysql5-from-novice-to-professional-2nd-edition.html#comments</comments>
		<pubDate>Thu, 05 Aug 2010 02:47:03 +0000</pubDate>
		<dc:creator>banksy</dc:creator>
				<category><![CDATA[3 - Kho báu]]></category>
		<category><![CDATA[Ebooks]]></category>
		<category><![CDATA[ebook]]></category>
		<category><![CDATA[mysql5]]></category>
		<category><![CDATA[novice]]></category>
		<category><![CDATA[php5]]></category>
		<category><![CDATA[professional]]></category>

		<guid isPermaLink="false">http://howtophp.net/?p=98</guid>
		<description><![CDATA[Tên sách: Beginning PHP5 and MySQL5 From Novice to Professional 2nd Edition – Apress Tác giả: W. Jason Gilmore Xuất bản: Apress/2006 Định dạng ebook: PDF/17.5MB Mô tả: Cuốn sách tham khảo khá đầy đủ về PHP, gồm 37 chương, trình bày về hầu hết các nội dung về lập trình web sử dụng ngôn [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://howtophp.net/wp-content/uploads/2010/08/beginning2prof.png"><img class="aligncenter size-full wp-image-101" title="beginning2prof" src="http://howtophp.net/wp-content/uploads/2010/08/beginning2prof.png" alt="" width="379" height="498" /></a></p>
<p><strong>Tên sách: </strong>Beginning PHP5 and MySQL5 From Novice to Professional 2<sup>nd</sup> Edition – Apress</p>
<p><strong>Tác giả:</strong> W. Jason Gilmore</p>
<p><strong>Xuất bản:</strong> Apress/2006</p>
<p><strong>Định dạng ebook:</strong> PDF/17.5MB</p>
<p><strong>Mô tả:</strong></p>
<p>Cuốn sách tham khảo khá đầy đủ về PHP, gồm 37 chương, trình bày về hầu hết các nội dung về lập trình web sử dụng ngôn ngữ PHP. Ở từng mảng nội dung, bạn sẽ được đi từ cơ bản đến nâng cao, giúp nắm bắt tốt hơn, và có thể nâng tầm bản thân từ một Novice lên Professional (nếu học đúng cách).</p>
<p><strong>Download:</strong></p>
<p><a href="http://howtophp.net/wp-content/uploads/2010/08/Apress.Beginning.PHP_.and_.MySQL_.5.From_.Novice.to_.Professional.2nd.Edition.Jan_.2006.pdf">Beginning.PHP5.and.MySQL.5.From.Novice.to.Professional.2nd.Edition</a></p>
]]></content:encoded>
			<wfw:commentRss>http://howtophp.net/index.php/2010/08/apress-beginning-php-and-mysql5-from-novice-to-professional-2nd-edition.html/feed</wfw:commentRss>
		<slash:comments>2824</slash:comments>
		</item>
	</channel>
</rss>
<!-- WP Super Cache is installed but broken. The path to wp-cache-phase1.php in wp-content/advanced-cache.php must be fixed! -->
