<?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>Tarotoast's Stuff &#187; code</title>
	<atom:link href="http://blog.tarotoast.com/tag/code/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.tarotoast.com</link>
	<description>Personal blog</description>
	<lastBuildDate>Fri, 04 Mar 2011 21:51:17 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Symfony 筆記 (7): Object-Relational Mapping (ORM) with Propel</title>
		<link>http://blog.tarotoast.com/2008/05/26/449/</link>
		<comments>http://blog.tarotoast.com/2008/05/26/449/#comments</comments>
		<pubDate>Tue, 27 May 2008 02:04:34 +0000</pubDate>
		<dc:creator>tarotoast</dc:creator>
				<category><![CDATA[Symfony]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[note]]></category>
		<category><![CDATA[orm]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[propel]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://blog.tarotoast.com/?p=449</guid>
		<description><![CDATA[總之，ORM 就是可以省下寫 database specific SQL 的麻煩的 abstraction 就是了。Symfony 用的是 Propel，是一個 PHP5 的 database framework，跟 ADOdb 是類似的東西，雖然兩者到底詳細差在哪我也不知道。不過總之 Symfony 的作者們決定用 Propel 來省下許多 code generation 和實作 ORM。 有幾個非常重要的檔案必須編輯好才能使用 Symfony 裡面的 propel 功能。 myproject/config/databases.yml myproject/config/propel.ini myproject/config/schema.yml 老實說 propel.ini 和 schema.yml 為啥要有兩個檔案，我也不知道 (as of now)。總之兩個檔案都得把 database 的設定寫進去就是了。然後 schema.yml 才是整個 ORM 的重點，Symfony 就是讀這個檔案生出所有 database object class 的。習慣直接編輯 schema.yml 的話是會很方便，不過老實說我也還不習慣，所以都用 phpmyadmin 先把 [...]]]></description>
			<content:encoded><![CDATA[<p>總之，ORM 就是可以省下寫 database specific SQL 的麻煩的 abstraction 就是了。Symfony 用的是 <a href="http://propel.phpdb.org/">Propel</a>，是一個 PHP5 的 database framework，跟 <a href="http://adodb.sourceforge.net/">ADOdb</a> 是類似的東西，雖然兩者到底詳細差在哪我也不知道。不過總之 Symfony 的作者們決定用 Propel 來省下許多 code generation 和實作 ORM。</p>
<p>有幾個非常重要的檔案必須編輯好才能使用 Symfony 裡面的 propel 功能。</p>
<ol>
<li>myproject/config/databases.yml</li>
<li>myproject/config/propel.ini</li>
<li>myproject/config/schema.yml</li>
</ol>
<p>老實說 propel.ini 和 schema.yml 為啥要有兩個檔案，我也不知道 (as of now)。總之兩個檔案都得把 database 的設定寫進去就是了。然後 schema.yml 才是整個 ORM 的重點，Symfony 就是讀這個檔案生出所有 database object class 的。習慣直接編輯 schema.yml 的話是會很方便，不過老實說我也還不習慣，所以都用 phpmyadmin 先把 database 生好然後再讓 Symfony 生出 schema.yml。</p>
<p>database.yml</p>
<pre class="xml">
all:
  propel:
    class:          sfPropelDatabase
    param:
      dsn:          mysql://username:password@localhost/database
</pre>
<p>propel.ini (上面)</p>
<pre class="xml">
propel.targetPackage       = lib.model
propel.packageObjectModel  = true
propel.project             = myproject
propel.database            = mysql
propel.database.createUrl  = mysql://username:password@localhost/
propel.database.url        = mysql://username:password@localhost/database
</pre>
<p>大致的生產順序如下:</p>
<ol>
<li>產生 schema.yml (自己編輯或者讓 symfony 照著建好的 database 生)<br />
讓 symfony 照著 database 生出 schema.yml:<br />
<code>symfony propel-build-schema</code></li>
<li>產生 ORM classes<br />
<code>symfony propel-build-model</code></li>
</ol>
<p>用這個 schema.yml 當範例</p>
<pre class="xml">
propel:
  blog_article:
    _attributes: { phpName: Article }
    id:
    title:       varchar(255)
    content:     longvarchar
    created_at:
  blog_comment:
    _attributes: { phpName: Comment }
    id:
    article_id:
    author:      varchar(255)
    content:     longvarchar
    created_at:
</pre>
<p>會生出 8 個檔案，4 個檔案在 lib/model/om/ 下面 (Base Class):</p>
<ol>
<li>BaseArticle.php</li>
<li>BaseArticlePeer.php</li>
<li>BaseComment.php</li>
<li>BaseCommentPeer.php</li>
</ol>
<p>然後另外 4 個檔案在 lib/model/ 下面 (Custom Class):</p>
<ol>
<li>Article.php</li>
<li>ArticlePeer.php</li>
<li>Comment.php</li>
<li>CommentPeer.php</li>
</ol>
<p>生在 lib/model/om/ 下面的檔案只要每次跑 propel-build-model 就會重新被蓋過，所以如果要自己修改 model 增加功能的話，就得修改 lib/model/ 下面的 class。在 Base class 裡面所有 field 的 accessor 都會被自動生出來，也就是說上面這個 yml 生出來的 model 可以這樣使用。</p>
<pre class="php">
// 單純是示範怎麼用 primary key
$articles = ArticlePeer::retrieveByPks(array(123, 124, 125));
// 使用 setter/getter
$article = new Article();
$article->setTitle('My first article');
$article->setContent('This is my very first article.\n Hope you enjoy it!');
$article->save();
$title   = $article->getTitle();
$content = $article->getContent();

// 這才是 ORM 的精華
$comments = $article->getComments();
</pre>
<p>要如何 Query 比較複雜的判斷呢？答案是用 Criteria 這個 class。以下這段的功能:</p>
<pre class="php">
$c = new Criteria();
$c->add(CommentPeer::AUTHOR, 'Steve');
$c->addJoin(CommentPeer::ARTICLE_ID, ArticlePeer::ID);
$c->add(ArticlePeer::CONTENT, '%enjoy%', Criteria::LIKE);
$c->addAscendingOrderByColumn(CommentPeer::CREATED_AT);
$comments = CommentPeer::doSelect($c);
</pre>
<p>其實就等於 SQL 下面的:</p>
<pre class="sql">
SELECT blog_comment.ID, blog_comment.ARTICLE_ID, blog_comment.AUTHOR,
       blog_comment.CONTENT, blog_comment.CREATED_AT
FROM   blog_comment, blog_article
WHERE  blog_comment.AUTHOR = 'Steve'
       AND blog_article.CONTENT LIKE '%enjoy%'
       AND blog_comment.ARTICLE_ID = blog_article.ID
ORDER BY blog_comment.CREATED_AT ASC
</pre>
<p>常用到的 condition 可以參考這個列表:</p>
<table>
<thead>
<tr>
<th>SQL</th>
<th>Criteria</th>
</tr>
</thead>
<tbody>
<tr>
<td>WHERE column = value</td>
<td>-&gt;add(column, value);</td>
</tr>
<tr>
<td>WHERE column &lt;&gt; value</td>
<td>-&gt;add(column, value, Criteria::NOT_EQUAL);</td>
</tr>
<tr>
<td><strong>Other Comparison Operators</strong></td>
<td></td>
</tr>
<tr>
<td>&gt; , &lt;</td>
<td>Criteria::GREATER_THAN, Criteria::LESS_THAN</td>
</tr>
<tr>
<td>&gt;=, &lt;=</td>
<td>Criteria::GREATER_EQUAL, Criteria::LESS_EQUAL</td>
</tr>
<tr>
<td>IS NULL, IS NOT NULL</td>
<td>Criteria::ISNULL, Criteria::ISNOTNULL</td>
</tr>
<tr>
<td>LIKE, ILIKE</td>
<td>Criteria::LIKE, Criteria::ILIKE</td>
</tr>
<tr>
<td>IN, NOT IN</td>
<td>Criteria::IN, Criteria::NOT_IN</td>
</tr>
<tr>
<td><strong>Other SQL Keywords</strong></td>
<td></td>
</tr>
<tr>
<td>ORDER BY column ASC</td>
<td>-&gt;addAscendingOrderByColumn(column);</td>
</tr>
<tr>
<td>ORDER BY column DESC</td>
<td>-&gt;addDescendingOrderByColumn(column);</td>
</tr>
<tr>
<td>LIMIT limit</td>
<td>-&gt;setLimit(limit)</td>
</tr>
<tr>
<td>OFFSET offset</td>
<td>-&gt;setOffset(offset)</td>
</tr>
<tr>
<td>FROM table1, table2 WHERE table1.col1 = table2.col2</td>
<td>-&gt;addJoin(col1, col2)</td>
</tr>
<tr>
<td>FROM table1 LEFT JOIN table2 ON table1.col1 = table2.col2</td>
<td>-&gt;addJoin(col1, col2, Criteria::LEFT_JOIN)</td>
</tr>
<tr>
<td>FROM table1 RIGHT JOIN table2 ON table1.col1 = table2.col2</td>
<td>-&gt;addJoin(col1, col2, Criteria::RIGHT_JOIN)</td>
</tr>
</tbody>
</table>
]]></content:encoded>
			<wfw:commentRss>http://blog.tarotoast.com/2008/05/26/449/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Symfony 筆記 (5): Session &amp; Cookie</title>
		<link>http://blog.tarotoast.com/2008/05/26/447/</link>
		<comments>http://blog.tarotoast.com/2008/05/26/447/#comments</comments>
		<pubDate>Mon, 26 May 2008 17:52:10 +0000</pubDate>
		<dc:creator>tarotoast</dc:creator>
				<category><![CDATA[Symfony]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[cookie]]></category>
		<category><![CDATA[note]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[session]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://blog.tarotoast.com/?p=447</guid>
		<description><![CDATA[Symfony 裡面的 Session 是透過 sfUser 這個 class 來完成的，可以在 action 裡面透過 $this->getUser() 來取得。關於 cookie 本身的設定則是在 apps/myapp/config/factories.yml 下面。Session 的存活時間 (timeout) 則是在 apps/myapp/config/settings.yml 裡面。 class mymoduleActions extends sfActions { public function executeFirstPage() { $nickname = $this->getRequestParameter('nickname'); // Store data in the user session $this->getUser()->setAttribute('nickname', $nickname); } public function executeSecondPage() { // Retrieve data from the user session with [...]]]></description>
			<content:encoded><![CDATA[<p>Symfony 裡面的 Session 是透過 sfUser 這個 class 來完成的，可以在 action 裡面透過 <code>$this->getUser()</code> 來取得。關於 cookie 本身的設定則是在 <code>apps/myapp/config/factories.yml</code> 下面。Session 的存活時間 (timeout) 則是在 <code>apps/myapp/config/settings.yml</code> 裡面。</p>
<pre class="php">
class mymoduleActions extends sfActions
{
  public function executeFirstPage()
  {
    $nickname = $this->getRequestParameter('nickname');

    // Store data in the user session
    $this->getUser()->setAttribute('nickname', $nickname);
  }

  public function executeSecondPage()
  {
    // Retrieve data from the user session with a default value
    $nickname = $this->getUser()->getAttribute('nickname', 'Anonymous Coward');
  }
}
</pre>
<p>除掉 Session 裡面的資料:</p>
<pre class="php">
class mymoduleActions extends sfActions
{
  public function executeRemoveNickname()
  {
    $this->getUser()->getAttributeHolder()->remove('nickname');
  }

  public function executeCleanup()
  {
    $this->getUser()->getAttributeHolder()->clear();
  }
}
</pre>
<p>然後在 Template 裡面則是用 <code>$sf_use</code> 這個預設的物件來存取，沒看 documentation 鬼才知道。</p>
<pre class="php">
&lt;p>
  Hello, &lt;?php echo $sf_user->getAttribute('nickname') ?>
&lt;/p>
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.tarotoast.com/2008/05/26/447/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Symfony 筆記 (4): sfActions</title>
		<link>http://blog.tarotoast.com/2008/05/26/446/</link>
		<comments>http://blog.tarotoast.com/2008/05/26/446/#comments</comments>
		<pubDate>Mon, 26 May 2008 09:38:19 +0000</pubDate>
		<dc:creator>tarotoast</dc:creator>
				<category><![CDATA[Symfony]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[note]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[upload]]></category>

		<guid isPermaLink="false">http://blog.tarotoast.com/?p=446</guid>
		<description><![CDATA[看到這段 Code 的時候真是有種喔原來有這些喔的感覺，趕快記錄下來。這些都是在 Action 裡面可以用的 method，重點是沒有查 API 誰會知道有這些可以用。[sfActions API] class mymoduleActions extends sfActions { public function executeIndex() { // Retrieving request parameters $password = $this->getRequestParameter('password'); // Retrieving controller information $moduleName = $this->getModuleName(); $actionName = $this->getActionName(); // Retrieving framework core objects $request = $this->getRequest(); $userSession = $this->getUser(); // 這個最不像 $response = $this->getResponse(); $controller = $this->getController(); $context [...]]]></description>
			<content:encoded><![CDATA[<p>看到這段 Code 的時候真是有種喔原來有這些喔的感覺，趕快記錄下來。這些都是在 Action 裡面可以用的 method，重點是沒有查 API 誰會知道有這些可以用。[<a href="http://www.symfony-project.org/api/1_0/sfActions">sfActions API</a>]</p>
<pre class="php">
class mymoduleActions extends sfActions
{
  public function executeIndex()
  {
    // Retrieving request parameters
    $password    = $this->getRequestParameter('password');

    // Retrieving controller information
    $moduleName  = $this->getModuleName();
    $actionName  = $this->getActionName();

    // Retrieving framework core objects
    $request     = $this->getRequest();
    $userSession = $this->getUser(); // 這個最不像
    $response    = $this->getResponse();
    $controller  = $this->getController();
    $context     = $this->getContext();

    // Setting action variables to pass information to the template
    $this->setVar('foo', 'bar');
    $this->foo = 'bar';            // Shorter version

  }
}
</pre>
<p>以上的 $this 如果在 Template 裡面要呼叫的話，記得使用 <strong>$sf_context</strong> 這個物件。<br />
sfActions 的不同用法:</p>
<pre class="php">
class mymoduleActions extends sfActions
{
  public function preExecute()
  {
    // The code inserted here <strong>is executed at the beginning of each action call</strong>
    ...
  }

  public function executeIndex()
  {
    ...
  }

  public function executeList()
  {
    ...
    <strong>$this->myCustomMethod();</strong>  // Methods of the action class are accessible
  }

  public function postExecute()
  {
    // The code inserted here <strong>is executed at the end of each action call</strong>
    ...
  }

  protected function myCustomMethod()
  {
    // You can also add your own methods, as long as they don't start with "execute"
    // In that case, it's better to <strong>declare them as protected or private</strong>
    ...
  }
}
</pre>
<p>File Upload 在 Symfony 下面非常簡單就解決，想想看如果指有用 php 寫處理個檔案上傳要寫幾行？</p>
<pre class="php">
class mymoduleActions extends sfActions
{
  public function executeUpload()
  {
    if ($this->getRequest()->hasFiles())
    {
      foreach ($this->getRequest()->getFileNames() as $fileName)
      {
        $fileSize  = $this->getRequest()->getFileSize($fileName);
        $fileType  = $this->getRequest()->getFileType($fileName);
        $fileError = $this->getRequest()->hasFileError($fileName);
        $uploadDir = sfConfig::get('sf_upload_dir');
        $this->getRequest()->moveFile('file', $uploadDir.'/'.$fileName);
      }
    }
  }
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.tarotoast.com/2008/05/26/446/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Symfony 筆記 (3): MVC Demo</title>
		<link>http://blog.tarotoast.com/2008/05/25/444/</link>
		<comments>http://blog.tarotoast.com/2008/05/25/444/#comments</comments>
		<pubDate>Sun, 25 May 2008 15:50:41 +0000</pubDate>
		<dc:creator>tarotoast</dc:creator>
				<category><![CDATA[Symfony]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[mvc]]></category>
		<category><![CDATA[note]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://blog.tarotoast.com/?p=444</guid>
		<description><![CDATA[Model-view-controller (MVC) is an architectural pattern used in software engineering. Successful use of the pattern isolates business logic from user interface considerations, resulting in an application where it is easier to modify either the visual appearance of the application or the underlying business rules without affecting the other. In MVC, the Model represents the information [...]]]></description>
			<content:encoded><![CDATA[<blockquote><p><strong>Model-view-controller</strong> (<strong>MVC</strong>) is an <a title="Architectural pattern (computer science)" href="http://en.wikipedia.org/wiki/Architectural_pattern_%28computer_science%29">architectural pattern</a> used in <a title="Software engineering" href="http://en.wikipedia.org/wiki/Software_engineering">software engineering</a>. Successful use of the pattern isolates <a title="Business logic" href="http://en.wikipedia.org/wiki/Business_logic">business logic</a> from <a title="User interface" href="http://en.wikipedia.org/wiki/User_interface">user interface</a> considerations, resulting in an application where it is easier to modify either the visual appearance of the application or the underlying <a class="mw-redirect" title="Business rules" href="http://en.wikipedia.org/wiki/Business_rules">business rules</a> without affecting the other. In MVC, the Model represents the information (the data) of the application and the business rules used to manipulate the data, the View corresponds to elements of the user interface such as text, checkbox items, and so forth, and the Controller manages details involving the communication to the model of user actions such as keystrokes and <a title="Mouse" href="http://en.wikipedia.org/wiki/Mouse">mouse</a> movements.</p></blockquote>
<p><img class="alignleft alignnone size-full wp-image-445" title="f0201" src="http://blog.tarotoast.com/wp-content/uploads/2008/05/f0201.png" alt="" width="242" height="270" /><br />
在 Symfony 裡面不用 MVC 來寫程式的話那就完全沒有意義。Model 是資料庫的 Layer，View 是 Template Layer，而 Controller 則是運算 Layer。雖然這些觀念不會太難，但是實際上要把舊有的程式分開還是得仔細想想。下面是書裡面的一段 Demo，算是很好的示範。</p>
<p><strong>Flat PHP File</strong><br />
這種大概是最古老的寫作方式，把所有的程式邏輯與資料庫存取通通包在同一個檔案裡面，HTML 和 PHP 還有 SQL 通通混在一起不但不好修改，而且要維護也比較上多很難。</p>
<pre class="php">
&lt;?php

// Connecting, selecting database
$link = mysql_connect('localhost', 'myuser', 'mypassword');
mysql_select_db('blog_db', $link);

// Performing SQL query
$result = mysql_query('SELECT date, title FROM post', $link);

?>

&lt;html>
  &lt;head>
    &lt;title>List of Posts&lt;/title>
  &lt;/head>
  &lt;body>
   &lt;h1>List of Posts&lt;/h1>
   &lt;table>
     &lt;tr>&lt;th>Date&lt;/th>&lt;th>Title&lt;/th>&lt;/tr>
&lt;?php
// Printing results in HTML
while ($row = mysql_fetch_array($result, MYSQL_ASSOC))
{
echo "\t&lt;tr>\n";
printf("\t\t&lt;td> %s &lt;/td>\n", $row['date']);
printf("\t\t&lt;td> %s &lt;/td>\n", $row['title']);
echo "\t&lt;/tr>\n";
}
?>
    &lt;/table>
  &lt;/body>
&lt;/html>

&lt;?php

// Closing connection
mysql_close($link);

?>
</pre>
<p><strong>MVC &#8211; Model</strong><br />
Model 是 Database 的 Abstraction。這裡是一段小 demo，實際上 Symfony 使用的是 <a href="http://propel.phpdb.org">Propel</a>，大部分的 accessor method 都會自動生出來。</p>
<pre class="php">
&lt;?php

function open_connection($host, $user, $password)
{
  return mysql_connect($host, $user, $password);
}

function close_connection($link)
{
  mysql_close($link);
}

function query_database($query, $database, $link)
{
  mysql_select_db($database, $link);

  return mysql_query($query, $link);
}

function fetch_results($result)
{
  return mysql_fetch_array($result, MYSQL_ASSOC);
}

function getAllPosts()
{
  // Connecting to database
  $link = open_connection('localhost', 'myuser', 'mypassword');

  // Performing SQL query
  $result = query_database('SELECT date, title FROM post', 'blog_db', $link);

  // Filling up the array
  $posts = array();
  while ($row = fetch_results($result))
  {
     $posts[] = $row;
  }

  // Closing connection
  close_connection($link);

  return $posts;
}

?>
</pre>
<p><strong>MVC &#8211; Controller</strong><br />
Controller 是邏輯的部份。這個 demo 需要用到的邏輯根本沒有，就只是 &#8220;從資料庫裡面找出所有 post&#8221; 而已，所以基本上只有一行。</p>
<pre class="php">
&lt;?php

// Requiring the model
require_once('model.php');

// Retrieving the list of posts
$posts = getAllPosts();

// Requiring the view
require('view.php');

?>
</pre>
<p><strong>MVC &#8211; View (Template)</strong><br />
Symfony 的 view 大致上可以分為 Template 和 Layout，差別在 Layout 比 Template 大，或者說 Template 在 Layout 裡面。</p>
<pre class="php">
&lt;h1>List of Posts&lt;/h1>
&lt;table>
&lt;tr>&lt;th>Date&lt;/th>&lt;th>Title&lt;/th>&lt;/tr>
&lt;?php foreach ($posts as $post): ?>
  &lt;tr>
    &lt;td>&lt;?php echo $post['date'] ?>&lt;/td>
    &lt;td>&lt;?php echo $post['title'] ?>&lt;/td>
  &lt;/tr>
&lt;?php endforeach; ?>
&lt;/table>
</pre>
<p><strong>MVC &#8211; View (Layout)</strong></p>
<pre class="php">
&lt;?php 

$title = 'List of Posts';
$content = include('mytemplate.php');

?>
&lt;html>
  &lt;head>
    &lt;title>&lt;?php echo $title ?>&lt;/title>
  &lt;/head>
  &lt;body>
    &lt;?php echo $content ?>
  &lt;/body>
&lt;/html>
</pre>
<p>實際在 Symfony 裡面每個檔案所在的地方不同，雖然一開始有點混亂，但是學習後會發現其實 Symfony 把檔案分配的很好，就類似設計很好的<a href="http://www.freebsd.org/">作業</a><a href="http://www.debian.org/">系統</a>或者<a href="http://www.revivalworld.org/rw/opensource">Mudlib</a>之類的感覺吧。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.tarotoast.com/2008/05/25/444/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Symfony 筆記 (2): YAML</title>
		<link>http://blog.tarotoast.com/2008/05/25/443/</link>
		<comments>http://blog.tarotoast.com/2008/05/25/443/#comments</comments>
		<pubDate>Sun, 25 May 2008 15:12:34 +0000</pubDate>
		<dc:creator>tarotoast</dc:creator>
				<category><![CDATA[Symfony]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[note]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[yaml]]></category>

		<guid isPermaLink="false">http://blog.tarotoast.com/?p=443</guid>
		<description><![CDATA[Symfony 的設定檔都是用 YAML 格式來搞定的，當然要用 ini 或者 xml 也是可以，不過 YAML 算是很簡單好用的選擇。選擇使用 YAML 的好處就跟選擇用 Python 寫程式差不多，好讀好編輯然後記得要用 space 不要用 tab。 # Never use tabs all: -> mail: -> -> webmaster: webmaster@example.com # Use blanks instead all: mail: webmaster: webmaster@example.com # All valid formats error1: This field is compulsory error2: ' This field is compulsory ' error3: 'Don''t leave [...]]]></description>
			<content:encoded><![CDATA[<p>Symfony 的設定檔都是用 <a href="http://www.yaml.org/">YAML</a> 格式來搞定的，當然要用 ini 或者 xml 也是可以，不過 YAML 算是很簡單好用的選擇。選擇使用 YAML 的好處就跟選擇用 Python 寫程式差不多，好讀好編輯然後記得要用 space 不要用 tab。</p>
<pre class="xml">
# Never use tabs
all:
-> mail:
-> -> webmaster:  webmaster@example.com

# Use blanks instead
all:
  mail:
    webmaster: webmaster@example.com
</pre>
<pre class="xml">
# All valid formats
error1: This field is compulsory
error2: '  This field is compulsory  '
error3: 'Don''t leave this field blank'   # Single quotes must be doubled
</pre>
<pre class="xml">
# Multiline
# Folded style, introduced by >
# Each line break is folded to a space
# Makes YAML more readable
accomplishment: >
  Mark set a major league
  home run record in 1998.

# Literal style, introduced by |
# All line breaks count
# Indentation doesn't appear in the resulting string
stats: |
  65 Home Runs
  0.278 Batting Average
</pre>
<pre class="xml">
# Shorthand syntax for arrays
players: [ Mark McGwire, Sammy Sosa, Ken Griffey ]

# Expanded syntax for arrays
players:
  - Mark McGwire
  - Sammy Sosa
  - Ken Griffey
</pre>
<pre class="xml">
# <strong>Incorrect</strong> syntax, <strong>blanks</strong> are missing after the colon
mail: {webmaster:webmaster@example.com,contact:contact@example.com}

# Correct shorthand syntax for associative arrays
mail: { webmaster: webmaster@example.com, contact: contact@example.com }

# Expanded syntax for associative arrays
mail:
  webmaster: webmaster@example.com
  contact:   contact@example.com
</pre>
<pre class="xml">
# Boolean Values
true_values:   [ on, 1, true ]
false_values:  [ off, 0, false ]
</pre>
<pre class="xml">
# Header
all:
  .general: # Key starts with . is ignored, 完全是方便閱讀而存在
    tax:        19.6
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.tarotoast.com/2008/05/25/443/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Symfony 筆記 (1): Basics for Converting from PHP</title>
		<link>http://blog.tarotoast.com/2008/05/24/442/</link>
		<comments>http://blog.tarotoast.com/2008/05/24/442/#comments</comments>
		<pubDate>Sun, 25 May 2008 06:29:45 +0000</pubDate>
		<dc:creator>tarotoast</dc:creator>
				<category><![CDATA[Symfony]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[note]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://blog.tarotoast.com/?p=442</guid>
		<description><![CDATA[Constant sfConfig::set('key', 'value'); echo sfConfig::get('key'); Using External PHP Class Place in lib/ directory Provide __autoload() function Symfony will automatically load so include statement is unnecessary. Passing Variables from Action to Template In Action: class mymoduleActions extends sfActions { public function executeMyAction() { $this->hour = $today['hours']; } } In Template: &#60;p>It is already &#60;?php echo $hour [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Constant</strong></p>
<pre class="php">sfConfig::set('key', 'value');
echo sfConfig::get('key');</pre>
<hr />
<strong>Using External PHP Class</strong></p>
<ol>
<li>Place in lib/ directory</li>
<li>Provide __autoload() function</li>
<li>Symfony will automatically load so include statement is unnecessary.</li>
</ol>
<hr />
<strong>Passing Variables from Action to Template</strong><br />
In Action:</p>
<pre class="php">class mymoduleActions extends sfActions
{
  public function executeMyAction()
  {
    $this->hour = $today['hours'];
  }
}
</pre>
<p>In Template:</p>
<pre class="php">&lt;p>It is already &lt;?php echo $hour ?>.&lt;/p></pre>
<hr />
<strong>Form (with helper)</strong><br />
HTML Version:</p>
<pre class="html">&lt;form method="post" action="/myapp_dev.php/mymodule/anotherAction">
  &lt;label for="name">What is your name?&lt;/label>
  &lt;input type="text" name="name" id="name" value="" />
  &lt;select name="cc_type" id="cc_type">
    &lt;option value="VISA">Visa&lt;/option>
    &lt;option value="MAST">MasterCard&lt;/option>
    &lt;option value="AMEX" selected="selected">American Express&lt;/option>
    &lt;option value="DISC">Discover&lt;/option>
  &lt;/select>
  &lt;input type="submit" value="Ok" />
&lt;/form></pre>
<p>Symfony Version:</p>
<pre class="php">&lt;?php echo form_tag('mymodule/anotherAction') ?>
  &lt;?php echo label_for('name', 'What is your name?') ?>
  &lt;?php echo input_tag('name') ?>
  &lt;?php $card_list = array(
    'VISA' => 'Visa',
    'MAST' => 'MasterCard',
    'AMEX' => 'American Express',
    'DISC' => 'Discover');
  echo select_tag('cc_type, options_for_select($card_list, 'AMEX')); ?>
  &lt;?php echo submit_tag('Ok') ?>
&lt;/form></pre>
<p><strong>Hyperlink (with helper)</strong><br />
HTML Version:</p>
<pre class="html">&lt;a class="special_link" onclick="return confirm('Are you sure?');"
    href="http://localhost/myapp_dev.php/mymodule/anotherAction/name/anonymous"&gt;
    I never say my name&lt;/a&gt;</pre>
<p>Symfony Version:</p>
<pre class="php">&lt;?php echo link_to('I never say my name', 'mymodule/anotherAction?name=anonymous',
  'class=special_link confirm=Are you sure? absolute=true') ?></pre>
<hr />
<strong>Post/Get Data</strong><br />
In Action:</p>
<pre class="php">class mymoduleActions extends sfActions
{
  ...

  public function executeAnotherAction()
  {
    $this->name = $this->getRequestParameter('name');
  }
}
</pre>
<p>In Template:</p>
<pre class="php">&lt;?php if ($sf_params->has('name')): ?>
  &lt;p>Hello, &lt;?php echo $sf_params->get('name') ?>!&lt;/p>
&lt;?php else: ?>
  &lt;p>Hello, John Doe!&lt;/p>
&lt;?php endif; ?>
</pre>
<p>or</p>
<pre class="php">&lt;p>Hello, &lt;?php echo $sf_params->get('name', 'John Doe') ?>!&lt;/p></pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.tarotoast.com/2008/05/24/442/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>2-pass ffmpeg ipod video encoding</title>
		<link>http://blog.tarotoast.com/2008/04/04/431/</link>
		<comments>http://blog.tarotoast.com/2008/04/04/431/#comments</comments>
		<pubDate>Fri, 04 Apr 2008 13:47:58 +0000</pubDate>
		<dc:creator>tarotoast</dc:creator>
				<category><![CDATA[BSD+Linux]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[encoding]]></category>
		<category><![CDATA[ffmpeg]]></category>
		<category><![CDATA[ipod]]></category>
		<category><![CDATA[video]]></category>

		<guid isPermaLink="false">http://blog.tarotoast.com/?p=431</guid>
		<description><![CDATA[把檔案存成 ipodconv input_file=$1 output_dir=/home/peter/.ipodvideos ffmpeg -y -i "${input_file}" -an -v 1 -threads auto -vcodec libx264 \ -b 1000k -bt 175k -refs 1 -loop 1 -deblockalpha 0 -deblockbeta 0 \ -parti4x4 1 -partp8x8 1 -me full -subq 1 -me_range 21 -chroma 1 \ -slice 2 -bf 0 -level 30 -g 300 -keyint_min 30 -sc_threshold 40 \ [...]]]></description>
			<content:encoded><![CDATA[<p>把檔案存成 ipodconv</p>
<pre>
input_file=$1
output_dir=/home/peter/.ipodvideos

ffmpeg -y -i "${input_file}" -an -v 1 -threads auto -vcodec libx264 \
  -b 1000k -bt 175k -refs 1 -loop 1 -deblockalpha 0 -deblockbeta 0 \
  -parti4x4 1 -partp8x8 1 -me full -subq 1 -me_range 21 -chroma 1 \
  -slice 2 -bf 0 -level 30 -g 300 -keyint_min 30 -sc_threshold 40 \
  -rc_eq 'blurCplx^(1-qComp)' -qcomp 0.7 -qmax 51 -qdiff 4 \
  -i_qfactor 0.71428572 -maxrate 768k -bufsize 2M -cmp 1 -s 640x480 \
  -f mp4 -pass 1 /dev/null

ffmpeg -y -i "${input_file}" -v 1 -threads auto -vcodec libx264 -b 1000k\
  -bt 175k -refs 1 -loop 1 -deblockalpha 0 -deblockbeta 0 -parti4x4 1 \
  -partp8x8 1 -me full -subq 6 -me_range 21 -chroma 1 -slice 2 -bf 0 \
  -level 30 -g 300 -keyint_min 30 -sc_threshold 40 \
  -rc_eq 'blurCplx^(1-qComp)' -qcomp 0.7 -qmax 51 -qdiff 4 \
  -i_qfactor 0.71428572 -maxrate 768k -bufsize 2M -cmp 1 -s 640x480 \
  -acodec libfaac -ab 192k -ar 48000 -ac 2 -f mp4 \
  -pass 2 "${output_dir}/${input_file}.mov"
</pre>
<p>2 pass encoding 的用意是在於第一次是作 profiling，然後第二次就參照第一次得到的 profile 來分配哪些片段要比較高的 bitrate，這樣整體壓縮起來的效果會好很多。</p>
<p>不過話說回來以上的 h264 + aac 的壓縮實在非常 CPU intensive，速度大概是 mp4 的 4~5 倍.. 囧</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.tarotoast.com/2008/04/04/431/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>python-pycurl on Shared Host</title>
		<link>http://blog.tarotoast.com/2008/03/21/430/</link>
		<comments>http://blog.tarotoast.com/2008/03/21/430/#comments</comments>
		<pubDate>Sat, 22 Mar 2008 00:34:57 +0000</pubDate>
		<dc:creator>tarotoast</dc:creator>
				<category><![CDATA[Footprints + Diary]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[pycurl]]></category>
		<category><![CDATA[shared host]]></category>

		<guid isPermaLink="false">http://blog.tarotoast.com/?p=430</guid>
		<description><![CDATA[編 Python 2.5, MySQLdb 都很輕鬆 就 make &#8211;prefix=~/ 和 python setup.py install 而已 但是 pycurl 讓我浪費了好多個小時的人生 我一直碰到的問題是這樣: # python Python 2.5.2 (r252:60911, Mar 21 2008, 05:12:12) [GCC 3.4.6 20060404 (Red Hat 3.4.6-9)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import pycurl Traceback (most recent call last): File "", line 1, [...]]]></description>
			<content:encoded><![CDATA[<p>編 Python 2.5, MySQLdb 都很輕鬆<br />
就 make &#8211;prefix=~/ 和 python setup.py install 而已<br />
但是 pycurl 讓我浪費了好多個小時的人生</p>
<p>我一直碰到的問題是這樣:<br />
<code><br />
# python<br />
Python 2.5.2 (r252:60911, Mar 21 2008, 05:12:12)<br />
[GCC 3.4.6 20060404 (Red Hat 3.4.6-9)] on linux2<br />
Type "help", "copyright", "credits" or "license" for more information.<br />
>>> import pycurl<br />
Traceback (most recent call last):<br />
  File "<stdin>", line 1, in <module><br />
ImportError: libcurl.so.4: cannot open shared object file: No such file or directory<br />
>>><br />
</code></p>
<p>把浪費的時間跳過，總之就是 pycurl 沒寫好 (怨念總是得目標來發洩)<br />
setup 時候的 &#8211;curl-config 就跟你說在 ~/lib 了，還去 /usr/lib 下面找 libcurl.so.4<br />
好吧或許摸 unix 環境的時間還不夠久，總之最後發現只要這樣子就解決掉了</p>
<p><code>export LD_LIBRARY_PATH=~/lib</code></p>
<p>真是浪費生命</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.tarotoast.com/2008/03/21/430/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Python unescape javascript escapped UTF8 sequence</title>
		<link>http://blog.tarotoast.com/2008/03/16/425/</link>
		<comments>http://blog.tarotoast.com/2008/03/16/425/#comments</comments>
		<pubDate>Sun, 16 Mar 2008 10:19:43 +0000</pubDate>
		<dc:creator>tarotoast</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.tarotoast.com/?p=425</guid>
		<description><![CDATA[尋找這種答案很浪費生命，記錄下來 print "".join([(len(i)&#62;0 and unichr(int(i,16)) or "") for i in url.split('%u')])]]></description>
			<content:encoded><![CDATA[<p>尋找這種答案很浪費生命，記錄下來</p>
<pre class="php">print "".join([(len(i)&gt;0 and unichr(int(i,16)) or "") for i in url.split('%u')])</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.tarotoast.com/2008/03/16/425/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>簡體 UTF8 -&gt; 繁體/正體 UTF8</title>
		<link>http://blog.tarotoast.com/2008/03/15/422/</link>
		<comments>http://blog.tarotoast.com/2008/03/15/422/#comments</comments>
		<pubDate>Sun, 16 Mar 2008 04:08:12 +0000</pubDate>
		<dc:creator>tarotoast</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[chinese]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[utf8]]></category>

		<guid isPermaLink="false">http://blog.tarotoast.com/?p=422</guid>
		<description><![CDATA[Encode-CNmap 是好朋友 雖然字表沒有完整，但是大部份都有轉換成功，而且使用上也不錯簡單 轉換文字檔案: cnmap -u2cb5 utf8.txt &#62; utf8-cntrad.txt 對於懶得在 Python 下面 implement 繁簡轉換的人(me?)實在很好用: import commands s = commands.getoutput("echo '简体中文' &#124; cnmap -ucb5") print s 說真的，這方法最好別用 XD]]></description>
			<content:encoded><![CDATA[<p><a href="http://search.cpan.org/~qjzhou/Encode-CNMap-0.32/">Encode-CNmap</a> 是好朋友<br />
雖然字表沒有完整，但是大部份都有轉換成功，而且使用上也不錯簡單<br />
轉換文字檔案:<br />
<code>cnmap -u2cb5 utf8.txt &gt; utf8-cntrad.txt</code></p>
<p>對於懶得在 Python 下面 implement 繁簡轉換的人(me?)實在很好用:</p>
<pre class="php">import commands
s = commands.getoutput("echo '简体中文' | cnmap -ucb5")
print s</pre>
<p>說真的，這方法最好別用 XD</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.tarotoast.com/2008/03/15/422/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

