<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[革命演史]]></title>
  <link href="http://revo-skill.frost.tw/atom.xml" rel="self"/>
  <link href="http://revo-skill.frost.tw/"/>
  <updated>2012-05-17T23:33:53+08:00</updated>
  <id>http://revo-skill.frost.tw/</id>
  <author>
    <name><![CDATA[蒼時弦や]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[目標與慾望]]></title>
    <link href="http://revo-skill.frost.tw/blog/2012/05/17/goals-and-desires/"/>
    <updated>2012-05-17T23:13:00+08:00</updated>
    <id>http://revo-skill.frost.tw/blog/2012/05/17/goals-and-desires</id>
    <content type="html"><![CDATA[<p>雖然已經十一點了，但是我還是想先寫完這篇文章啊！</p>

<p>最近的 Diablo 3 (暗黑破壞神三) 非常熱門，原本其實我也只是想玩看看，不過後來還是當作耳邊風。</p>

<p>但，昨天看著許多同學、網友都在討論，難免還是想要玩看看。從同學那邊拿到體驗序號後，我就開始下載、安裝。</p>

<p>雖然亞洲伺服器在很晚才開放，不過我還是玩了一會……</p>

<p>真的，很好玩！</p>

<!-- more -->


<p>以往其實我對於遊戲這些都不怎麼感興趣，但是除了有Mac版本之外，還很不錯玩，真的是令我難以抗拒這股誘惑。</p>

<p>自從開始接案子賺點錢、分擔自己的住宿、伙食費之後，我對許多東西的抗拒力似乎一直在下降。</p>

<p>我個人很注重忍耐跟控制慾望，因為我深知一旦陷進去其實就很難離開。即使過著簡單的生活，也不要被其掌控。</p>

<p>不過，自己住，能夠選擇三餐要吃什麼，有能力提供自己一些娛樂的消費。相較於過去，我真的「有能力」很多，也比以往更加的無法控制自己。</p>

<p>不過，這次不是討論我有多墮落。但我覺得現在的這些「慾望」我還能控制，至少我還不會花費超出我能力所及之外的花費。</p>

<p>回到 Diablo 3 跟慾望這個主題，一款遊戲要價台幣 1499 對於一個完全沒有零用錢的人來說很困難，一週四到五天左右的三餐都控制在一千元以內（大約每餐五十元）如此精細控制，盡可能不要讓父母有多餘花費在自己身上的人，怎麼可能會有這麼多錢呢？</p>

<p>另一方面，雖然自己偶爾會有小案子可以接來做，但是也有不少已經投資到房租、水電費上（畢竟現在已經是一個人住，家裡狀況還沒寬裕到我可以隨意使用這些錢，當然買書之類的是例外）</p>

<p>總而言之，手邊就是沒錢，而且慾望驅使著自己去買下 Diablo 3 這就是現況。
（莫名的是很長的現況說明啊……）</p>

<p>過去，我想要什麼，大概就會想「不要造成爸媽負擔」於是就忍下來，然後不了了之。</p>

<p>但是，現在我知道，要滿足慾望，就定下一個目標，然後去實踐，去獲得達成慾望的條件就好了！</p>

<p>實際上，在我接案子的經驗裡面，往往沒有想像中那麼困難。當然，這只限於一些規模不大的小案子，謹慎執行是必須的，但是往往我低估自己多年的累積。</p>

<p>有時候，你的客戶根本不管這麼多。</p>

<p>所以我知道，如果要滿足慾望，那麼就給自己一個目標，然後「實行」，如此一來，就不會像以往一樣惆悵，然後覺得自己比別人少了什麼。</p>

<p>不過，基於這一切的前提就是「絕不預支」因為那是一切平衡崩潰的開始，自己永遠不會知道這一次的預支會花上多久時間完成，完成前是否有其他的慾望讓你更加的深陷其中。</p>

<p>仔細思考，也是另一個要點，有時候想通了就會覺得沒有必要得到了。</p>

<p>那麼，今年暑假，能夠達成多少呢？PSV, Diablo3, Kindle Fire加起來也不是個小數字，還要盡可能多存一些供下一學期的房租跟伙食、水電費使用呢！</p>

<p>原本在苦惱該做個什麼網站，現在也不用了！就是一個 Todo List 網站，把每個目標與慾望記錄下來，推進自己吧！</p>

<p>而且，我也稍稍想通了為什麼有錢人賺的多，花的也多的理由。</p>

<p>「因為他們為了花錢而賺錢，所以基於能花掉多少，就要賺到多少。」</p>

<p>那麼，我是否也能夠做到這樣的程度嗎？做到能夠盡情的滿足自身的慾望，這樣的程度？</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[我對興趣的看法]]></title>
    <link href="http://revo-skill.frost.tw/blog/2012/05/11/the-idea-which-i-think-of-interest/"/>
    <updated>2012-05-11T20:24:00+08:00</updated>
    <id>http://revo-skill.frost.tw/blog/2012/05/11/the-idea-which-i-think-of-interest</id>
    <content type="html"><![CDATA[<p>其實這是有感而發的一篇文章，我想應該是不會有什麼內容，頂多就是某人分享他那神奇喜好（？）的由來。</p>

<p>最近像是升上大二要選擇分組（多媒體、動畫、遊戲）還有妹妹要選學校這些事情，我又開始想了一些東西，本篇文章就是把東西釋放（？）出來讓腦子舒服點而已～</p>

<!-- more -->


<p>我覺得所謂<strong>興趣</strong>是培養出來的！</p>

<p>也許我的想法可能會把所謂的<strong>興趣</strong>跟<strong>專長</strong>混在一起討論。
但是，有興趣的事物，順利發展成專長的機會不是比較大嗎？我覺得這點應該是很確定的，因為樂於從事，所以久而久之累積了不少相應的技巧與知識。</p>

<p>那麼，為什麼說是<strong>培養</strong>出來的呢？</p>

<p>因為我認為，大家<strong>有興趣</strong>的東西一定很多，那到底什麼可以發展為真正的<strong>興趣</strong>就是一個重要的問題。</p>

<p>基於這點，就<strong>自信</strong>對學習的影響來看，我認為這是影響是否能順利發展的要素。</p>

<p>在學習過程中，難免會想炫耀，但是大家都一樣有何好跟朋友炫耀，當然是不一樣的東西。那麼什麼是你所擅長的？那就一定是一開始有興趣，並且稍微深入的東西。</p>

<p>只要你比你的朋友稍微傑出一點在這方面上，那你的自信就會被建立起來，更喜歡做這件事情。也許這對朋友好像不太禮貌，但是如果不建立自信以及其他能夠讓自己<strong>樂於學習</strong>的要素，那麼怎麼能成為興趣呢？</p>

<p>以自己學程式的例子來看，因為我很小就開始學習，也因此我開始能夠運用的時間點比其他人早很多，即使只是偶爾分享心得與知識，別人也會自然認為你在這方面<strong>很厲害</strong>有需要相關領域的協助時，自然就會請你幫忙。</p>

<p>此時，就會有自信，而且還能夠獲得繼續學習下去的動力。相對的，如果一直被他人唾棄，除非天生就是得學下去，不然我想很難有人可以孤獨的自己把一項技巧繼續學習下去的。</p>

<p>當然，不一定要他人才能夠建立自信。從我進入數媒系開始已經快一年了，素描課雖然無法達到理想的程度，但是扎實的修煉還是呈現出了效果，我很明白，我在喜愛的動漫人物的繪製上，比過去好上很多，這種進步的喜悅讓我更有信心自己可以學好，並且繼續努力。</p>

<p>所以，我認為興趣需要培養。</p>

<p>那麼，有時候真的會有很多喜歡，我認為就去做，那就好了！喜歡的事物，坐再多，也不會累。</p>

<p>不過，物極必反。有時候到達極限的時候，再喜歡的東西也不想做，那就丟到一旁，盡情的玩，玩累了，就會再次把焦點放到興趣上。</p>

<p>不過，有時候所謂的<strong>娛樂</strong>跟<strong>興趣</strong>是不能混為一談的！娛樂是為了紓解壓力，畢竟即使是興趣還是會構成壓力，我想那是來自自我要求與尋求他人肯定時所產生的。</p>

<p>如果把娛樂（看電視、玩遊戲）視為興趣，那麼最後的下場大概就是你很熟悉某某偶像劇劇情，或者在遊戲世界是個大富翁，在現實只是個一事無成的人而已。並非說不能有娛樂，只是要把興趣跟娛樂區分清楚。</p>

<p>教育部的國語辭典給<strong>興趣</strong>的定義是：樂於學習的事物</p>

<p>也因此，興趣是在進行學習，而非純粹的娛樂。娛樂可以紓解壓力，做有興趣的事物也可以，只是興趣所累積的壓力得靠其他東西在將其釋放。</p>

<p>寫程式、學習寫程式、畫畫、學畫畫和設計，我真的很快樂，我也覺得能這樣繼續下去就好，我並不覺得課業上給我的是壓力，反而覺得是一種讓我獲得更多快樂的必備條件。</p>

<p>我想，興趣的終點就是變成專長，但是如果只是純粹的<strong>專長</strong>而不是興趣，那麼一旦學習的誘因消失，那就無法繼續學習了！也會因此而逐漸失去那一項能力，這真的很可惜。</p>

<p>雖然我想了這麼多，我卻無法悟出<strong>為什麼有人沒有興趣</strong>這一件事情，我還是覺得只要活的像個人，應該就會有興趣。那麼為什麼問起一些人<strong>你以後想做什麼</strong>的時候，他們卻不能把最快樂的那件事情說出來，把他的興趣說出來，就好像想要殺掉自己的興趣一般。</p>

<p><strong>興趣</strong>也會是一個人的個性，我覺得因為<strong>興趣</strong>而努力、前進的人，讓人敬佩、尊敬，而且他也很有<strong>個性</strong>因為他不會受到其他人的影響，我行我素的<strong>努力</strong>。這不是一件很棒的事情嗎？</p>

<p>興趣真的需要培養，不要一開始就殺掉他。</p>

<p>也不要把<strong>興趣</strong>限制住，我真的覺得現在的小朋友自由的時間太少，一直被課業框住，父母也沒有讓他們選擇興趣，那麼透過興趣得到的自信以及在升學上可以選擇的方向，不就也相對的消失了嗎？</p>

<p>所以我也很感謝父母，從小就沒有阻止我過，所以我選擇對的學校得到相對優秀的專長，而且<strong>過得很快樂</strong>。</p>

<p>不過，有時候發展太順利反而會不知道不順利的人到底出了什麼問題。所以我也希望還不知道自己<strong>興趣</strong>的朋友們告訴我，為什麼你們不能像我一樣喜歡告訴別人「我喜歡寫程式、做設計」還要硬給他塞一點相關的知識才肯罷休的原因。</p>

<p>我的興趣大概已經被我養到<strong>希望所有人都跟我有一樣的興趣，享受一樣快樂</strong>的程度，但是我覺得這沒有什麼不好，這就是熱愛。</p>

<p>看起來是一篇挺長的文章，如果你可以讀到這裡，我想你的耐力一定超好～～</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[The CSS3 Transition]]></title>
    <link href="http://revo-skill.frost.tw/blog/2012/05/08/the-css3-transition/"/>
    <updated>2012-05-08T21:02:00+08:00</updated>
    <id>http://revo-skill.frost.tw/blog/2012/05/08/the-css3-transition</id>
    <content type="html"><![CDATA[<p>好久沒寫，今天來分享一下應該是我本業的網頁設計相關文章 XDD</p>

<p>前幾天在 Google Reader 上看到 <a href="http://zespia.tw/">Zespia</a> 換了新佈景，原本的佈景也是目前這個網誌用的 <a href="http://zespia.tw/Octopress-Theme-Slash/index_tw.html">Slash</a> 不過因為使用者越來越多，所以站長決定換新佈景～</p>

<p>接著，我看到那中間的 &#8220;Z&#8221; 字 Logo 那透明度緩緩的恢復的效果非常的有興趣，於是，我開始了調查……</p>

<!-- more -->


<p>原本以為是用 JavaScript 所製作的效果（像是 jQuery 就有 Fade IN/OUT 的效果）不過仔細一看原始碼，就發現「我錯了！」</p>

<p>裡面用著一個名為 transition 的屬性，好奇心一來就開始 Google 使用方法。</p>

<p>嘗試幾次後，大概了解使用了！
（中文叫做「漸變」用途大概就是在 CSS 設定值變化時提供一個漸進的變化）</p>

<p>不過以目前瀏覽器大戰的情況來看，用純 CSS 撰寫實在吃力不討好，於是我就用了 <a href="http://compass-style.org">Compass</a> 稍微輔助。</p>

<figure class='code'><figcaption><span>site.css.scss</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
</pre></td><td class='code'><pre><code class='scss'><span class='line'><span class="k">@import</span> <span class="s2">&quot;compass&quot;</span><span class="p">;</span>
</span><span class='line'><span class="k">@import</span> <span class="s2">&quot;compass/reset&quot;</span><span class="p">;</span>
</span><span class='line'><span class="k">@import</span> <span class="s2">&quot;compass/css3&quot;</span><span class="p">;</span> <span class="c1">//屬於 CSS3 的功能</span>
</span><span class='line'>
</span><span class='line'><span class="k">@include</span><span class="nd"> global-reset</span><span class="p">;</span> <span class="c1">//CSS Reset</span>
</span><span class='line'>
</span><span class='line'><span class="nt">body</span> <span class="p">{</span>
</span><span class='line'>  <span class="na">padding</span><span class="o">:</span> <span class="mi">10</span><span class="kt">pxl</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="c1">//漸變方塊</span>
</span><span class='line'><span class="nc">.box</span> <span class="p">{</span>
</span><span class='line'>  <span class="na">background</span><span class="o">:</span> <span class="nf">adjust-lightness</span><span class="p">(</span><span class="nb">blue</span><span class="o">,</span> <span class="mi">30</span><span class="p">);</span>
</span><span class='line'>  <span class="na">width</span><span class="o">:</span> <span class="mi">50</span><span class="kt">px</span><span class="p">;</span>
</span><span class='line'>  <span class="na">height</span><span class="o">:</span> <span class="mi">50</span><span class="kt">px</span><span class="p">;</span>
</span><span class='line'>  <span class="k">@include</span><span class="nd"> opacity</span><span class="p">(</span><span class="mi">0</span><span class="mf">.7</span><span class="p">);</span> <span class="c1">//透明度 30%</span>
</span><span class='line'>  <span class="k">@include</span><span class="nd"> border-radius</span><span class="p">(</span><span class="mi">50</span><span class="kt">%</span><span class="p">);</span> <span class="c1">//呈現球體</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="nc">.box</span><span class="nd">:hover</span> <span class="p">{</span>
</span><span class='line'>  <span class="k">@include</span><span class="nd"> opacity</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="c1">//透明度 0% (不透明)</span>
</span><span class='line'>  <span class="k">@include</span><span class="nd"> transition-duration</span><span class="p">(</span><span class="mi">0</span><span class="mf">.3</span><span class="kt">s</span><span class="p">);</span> <span class="c1">//0.3秒完成漸變</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>之後在業面上套用屬性，游標一過去之後就會發生變化～</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;box&quot;</span><span class="nt">&gt;&lt;/div&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<p>假設漸變設定在 .box 而非 .box:hover 上，那麼漸變的情會如下：</p>

<ol>
<li>瀏覽器初始化元素</li>
<li>瀏覽器套用 CSS 屬性 (第一次漸變，會從 0px * 0px 漸變成 50px * 50 px)</li>
<li>觸碰觸發漸變（透明度 30% > 0% ）</li>
</ol>


<p>假設是如上述程式碼來做，那麼第二步驟（變大）的建變就不會有。
所以依照這個原理，在構成頁面區塊時只要設定上建變，就會出現開打開網頁，內容區塊會放大到相應大小的情況。</p>

<blockquote><p>不過我想只限於內容少於區塊大小的狀態</p></blockquote>

<p>大致上就是這樣摟～</p>

<p>最近感覺繪畫上的能力進步不少，之後應該也會針對 Illustrator 多加努力，希望之後可以有一套自己風格的網頁設計～</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[網站開發之路 - 反思]]></title>
    <link href="http://revo-skill.frost.tw/blog/2012/04/03/the-web-develop-way-reflection/"/>
    <updated>2012-04-03T19:51:00+08:00</updated>
    <id>http://revo-skill.frost.tw/blog/2012/04/03/the-web-develop-way-reflection</id>
    <content type="html"><![CDATA[<p>每當心情不是很好，或是毫無動力時。我就會開始東想西想。</p>

<p>雖然孔子一天都是反省三次，不過我做不來。但是，一個月反省一次還是勉強可以的。</p>

<p>那，這篇文章就是來思考一下我到底在幹嘛。<br />
（總覺得我開始搞不清楚我是碼農還是設計師了……）</p>

<!-- more -->


<p>這幾天弄完老爸的 <a href="http://moho.com.tw/?referral=1">MOHO Cloud Platform</a> 之後，我就一整個毫無動力。</p>

<blockquote><p>基本運行跟套版就花上一個多月（拭淚）之後還有一段慢長的重構之路，還得邊重構邊維護到重構完成。</p></blockquote>

<p>雖然知道還要幫學姊畢製的那堆元件組成一個電子書 APP 而且還是攸關人家能不能順利完成作品畢業，抑或是系上總會在期中考前出現的大量作業（因為期中考不考，所以都以作業替代）我都無心去做。</p>

<p>一句話表達就是——<strong>毫無動力</strong>！</p>

<p>接著，今天翻網站時看到一篇 haml 的介紹文章。<br />
我就開始思考一件事情我到底是往一個「開發者」還是一個「設計師」在發展呢？</p>

<p>雖然我的最終目的是兩者兼顧，但是總該要有個主、有個輔吧？<br />
這就是個難題了！</p>

<p>Q: 我到底「最」喜歡什麼？</p>

<blockquote><p>若要有一個答案，大概就是「漂亮」的東西吧！<br />
以此推測，也許「設計之路」最為符合我的目標</p></blockquote>

<p>Q: 平常最多接觸的是什麼？</p>

<blockquote><p>程式，寫網站居多。也因為這樣，網站開發的經驗不斷累積</p></blockquote>

<p>Q: 學習的目標為何？</p>

<blockquote><p>我想是自己可以完成網站的製作，完全不依靠其他人。<br />
一直以來就不喜歡麻煩別人，最喜歡的網站開發也是如此。</p></blockquote>

<p>Q: 未來希望從事的工作？</p>

<blockquote><p>大概是自己開設計公司，因為也不喜歡被束縛。</p></blockquote>

<p>這樣一直問自己問題，還是找不出個明確的答案。<br />
畢竟，我的「狀態」一直在前端、後端、設計師游移，到底該位於哪個點一直沒有定下來。</p>

<p>不過，也許我不希望會定下來，甚至希望能找出新的道路。<br />
因為不論是寫網站時的心境，或者完成一個視覺設計，都讓我非常愉快。</p>

<p>那麼，之後該怎麼訓練呢？<br />
我猜如果我不給自己暗示一下比例，大概又會偏食吧！<br />
(實際上通常沒有太大意義，但是還是會不時的提醒自己不要忘記)</p>

<p>Q: 網頁設計上到底該不該先用 PhotoShop 或 FireWorks 之類的軟體先設計過呢？</p>

<blockquote><p>其實我還蠻猶豫這點的，不過看了一些網站設計後，還是認為「必要」直接衝 HTML 或用 Middleman 做出 Layout 的其實比較偏 Coder 的感覺。<br />
相較之下，使用 PhotoShop 還是能夠為頁面做不少質感上的強化，這不是先用 Code 就能做到的（因為要切版跟做質感）</p></blockquote>

<p>從這點來看，我似乎還是比較希望靠視覺的部分近一點。<br />
不過最近下來我也很明白，我在 PhotoShop 上還是非常力不從心的。</p>

<p>不過，還是要給自己一些「遊戲規則」</p>

<ul>
<li>質感、基本的美要做到</li>
<li>創意即是創意，但是只在有靈感時記錄下來<br />
  <small>基於這點，主要是因為我大多時候都太過依賴那一瞬的靈感了！</small></li>
<li>要以使用者操作流暢為主</li>
<li>不需要太過在意那些習以為常的 Layout 設計，因為並沒有不好，也不會影響創意</li>
</ul>


<p>再來，就是觸理我前端上的配套。<br />
不過心理已經有底了！</p>

<blockquote><p>Middleman + Jade ( HTML ) + CoffeeScript ( JavaScript ) + Compass ( CSS )</p></blockquote>

<p>很明顯的，我已經沒有過去那個純 HTML/CSS/JS 的堅持了！<br />
因為，既然我希望能夠自己做更多，那就不能把一氣呵成的這口氣吐太久，不然就會斷氣。</p>

<p>即使只能提高產能，也總比一開始無法完成好。</p>

<p>Q: 接觸了 Ruby on Rails 後與 PHP 的抉擇？</p>

<blockquote><p>前幾天聽到 Ruby 成為國際標準了！讓我小小心動了一下。<br />
不過，我認為我對 PHP 的情感不是那麼簡單可以放下的。但，Rails讓我看到了新的世界，而且他的諸多特性讓我無法忘懷。<br />
我會把 Rails 當作我的工具，並且繼續跟 PHP 做朋友。</p></blockquote>

<p>大概就是下定決心了！越了解 Rails 就越清楚以 Rails 開發網站跟 PHP 開發網站的便利性，以及 Heroku 這類 PaaS 可以快速的 Deploy 網站，比起過去要 VPS 才能 Deploy 來看，已經很適合我拿來做一個開發網站的主要工具。（何況我的筆電又剛好是Mac的，很剛好……）</p>

<p>Q: 既然要決定比例，會怎麼分配呢？</p>

<blockquote><p>其實兩者東西都很多，原本我以為程式上的技能已經夠了！但是PHPConf之後加了許多大大的噗浪才知道不是這一回事！<br />
但是我在視覺設計上的能力還很差，至少得補足到我能讓兩者可以平衡的狀態。<br />
所以大致上會是 設計 60% 程式 40% 的狀態吧！</p></blockquote>

<p>好久沒有打長文了！<br />
打完之後自己心理也舒服多了 XDD</p>

<p>之後會先想辦法加強 PhotoShop 在質感上的磨練吧！(雖然我好像迷上了 Illustrator 的簡潔色塊風，或者說我的風格本身就是在那上面)<br />
另一方面會把 Ruby 的能力提升起來，我想一年應該沒問題。</p>

<p>大致上都準備好之後，大概就是跟爸媽說我的目標了吧（苦笑）<br />
因為現在一直都是在老爸下面幫忙，但是我還是希望自己有自己的工作室（設計公司）至於這個部分，我大概會選擇成為老爸公司的子公司吧，以投入部分心力在維護老爸公司網站，另一方面做網站開發這樣！<br /></p>

<p>實際上，比起替客戶做網站，我更喜歡去開發一個新網站出來。</p>

<p>呼！感覺好很多了！也許待會就會有動力做作業之類的 XDD</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[網站開發之路 - Vim (2)]]></title>
    <link href="http://revo-skill.frost.tw/blog/2012/04/01/the-web-develop-way-vim-2/"/>
    <updated>2012-04-01T21:54:00+08:00</updated>
    <id>http://revo-skill.frost.tw/blog/2012/04/01/the-web-develop-way-vim-2</id>
    <content type="html"><![CDATA[<p>自開始使用 Vim 後應該有一週左右了！不過我似乎不怎麼勤勞，沒有練習太多。</p>

<p>但，也不能說是完全沒有練習，至少依靠了 <a href="http://www.vimgolf.com/">VimGolf</a> 這個網站，我也多少又增加了一些操作技巧的知識。</p>

<p>真希望能夠儘快熟練使用啊！</p>

<!-- more -->


<p>不過，先前在噗浪上又看到一篇 程式設計師與IDE 關係的文章，讓我又思考了一下學習 Vim 的理由。其實 Aptana 已經很符合我的需求了，也不需要再學 Vim 才對啊！</p>

<p>但是，仔細想想，其實學習 Vim 也不差，在 IDE 選用上，其實也沒什麼啊！<br />
我對IDE的要求也不外乎就是 Syntax&amp;Hightlight 和 AutoComplete 而已，語法高亮跟自動完成，語法高亮是為了寫程式時能夠清楚區分。而自動完成其實就是自己記性不好，得依賴一下軟體提示吧！</p>

<p>大致上來說，我還是會繼續學習 Vim 畢竟可以不離開鍵盤操作真的很誘人 XDD
(至少我不用按 Command + Tab 切換到 Terminal 打指令又切回 Aptana 繼續撰寫)</p>

<p>我想，大概就是各有好處吧！至少我還希望英打可以更快一點。(這讓我想以以前一位網友說過「IDE好用就用，不用特地在意什麼打字速度的，效率比較重要」)</p>

<p>以上就是 Vim 之路的概況摟 XDD</p>

<p>不過 VimGolf 前幾天練習過的好像又忘了差不多呢（苦笑）</p>

<blockquote><p>w 是向後一個 Word (單字)<br />
f[x] 是搜尋某個字 Ex. fa 會找出 a (但只有該行)<br />
$s/search/replace/ 替換搜尋的字串（只有一次）<br />
%s/search/replace/ 替換搜尋的字串（全文）</p></blockquote>

<p>目前有記起來的似乎就這幾個，還要多加練習拉！
（今天練習才發現可以用 Ctrl + V 選取數行後再一次做 Insert 插入多個同樣的東西呢！）</p>

<p>至於網頁設計的部分，前幾天嘗試做了些質感上的練習。</p>

<p>品質嘛，還需要很多很多的加強，而且整體設計也沒辦法做好……
<img src="http://i.imgur.com/9MrUh.png" alt="質感練習" /></p>

<p>至於之後大概還會加入像是 Coffee + Backbone.js 跟 jade/haml 的練習吧！<br />
多學些，等這學期一大堆事情都處理完畢之後，大二我大概會盡量不管事，專心重新修煉了吧！<br />
簡單說，我想砍掉重練，然後在變更強 XD</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[網站開發之路 - Vim(1)]]></title>
    <link href="http://revo-skill.frost.tw/blog/2012/03/26/the-web-develope-way-vim-1/"/>
    <updated>2012-03-26T21:24:00+08:00</updated>
    <id>http://revo-skill.frost.tw/blog/2012/03/26/the-web-develope-way-vim-1</id>
    <content type="html"><![CDATA[<p>作為起始，我決定先把 Vim 練好。</p>

<p>理由，很簡單。</p>

<blockquote><p>相較於 IDE 來說，使用 VIM 可以盡量避免離開 Terminal 的操作。
基於這點，我覺得可以改善我常常用 Ctrl + Tab 切換視窗來回操作的問題。</p></blockquote>

<!-- more -->


<p>作為起始，我先學習了一些基本操作。</p>

<blockquote><p>:q <strong>離開</strong></p>

<p>:w <strong>儲存</strong></p>

<p>:e 檔名 <strong>編輯</strong></p>

<p>i 插入模式（目前字元）o 新行插入 a 目前字元後插入</p></blockquote>

<p>學會這些後，基本上的編輯就沒什麼問題了！
不過，這樣還是體現不出 Vim 的強大。</p>

<p>於是，花了半天的時間開始安裝一些 Plugin 等等。所謂的 Vim 的強大，這時候才明顯的體現出來！</p>

<p>過去我都不知道一個搭配好的 Vim 可以跟 IDE 一樣好用，而且還是內建的編輯器，許多問題都可以輕鬆的解決。</p>

<p>雖然還不能熟悉使用各種 Vim 的指令、快速鍵。但是我還是盡可能的把一些記起來。</p>

<blockquote><p>:set <strong>設定</strong></p>

<p>G <strong>跳到檔尾</strong></p>

<p>gg <strong>跳到檔首</strong></p>

<p>dd <strong>刪除整行</strong></p>

<p>x <strong>刪除一個字</strong></p>

<p>Ctrl + w > h/j/k/l <strong>切換視窗</strong></p>

<p>h/j/k/l <strong>左/下/上/右</strong></p>

<p>:sp/:vsp <strong>分割新視窗</strong></p>

<p>:tabnew <strong>新增Tab</strong></p>

<p>v <strong>選取</strong></p>

<p>&#8220;[a]y <strong>儲存選取到暫存區a</strong></p>

<p>&#8220;[a]p <strong>貼上暫存區a到文件</strong></p></blockquote>

<p>實際上操作起來真的還有很多需要學習。</p>

<p>經過一番折騰，大致上習慣了 Vim 操作與編輯文件，也稍微配置出了一套自己的常用 Plugin 跟設定檔。</p>

<p><img src="http://i.imgur.com/KDluE.png" alt="http://i.imgur.com/KDluE.png" /></p>

<p>不過，在 Terminal 下的色調總是怪怪的。
怎麼配也是弄不好，在我努力尋找配色方案時，有高手分享他的 Vim 配置。</p>

<p>早上就先照著 Github 上的說明安裝了，步驟也很簡單，就是 git clone 下來後運行 Shell Script 更新 Plugin (從 Github 上) 接著建立連結（.vim / .vimrc / .gvimrc）就完成了！</p>

<p>不愧是高手的配置，用起來不但很順，而且還很合用。
不過因為我自己還有網頁跟寫 PHP 這套比較像是配給 Ruby/Rails 的設定還是不太夠我的需求，經過觀察發現 plugin 的加入方法後，就在加了像是 Zencoding 跟 Neoautocomplcache 的 plugin 進去。</p>

<p>到目前為止，我的 Vim 配置已經告一段落。雖然熟悉使用 Vim 還有很長的一段路，但是至少已經有一套不錯的工具了！</p>

<p><img src="http://i.imgur.com/DXOSK.png" alt="http://i.imgur.com/DXOSK.png" /></p>

<p>也順便給 Terminal 的配色修改了一下，感覺起來自己好像也變威了！
不過，雖然有 Autocomplete 的 Plugin 不過相較 IDE 其實也是遜色很多，希望能夠純熟使用 VIM 之外，也能將許多程式撰寫上該記起來的東西記起來。</p>

<p>趁現在還有本錢，多累積一些實力！</p>

<hr />

<p>我使用的是<strong>高見龍</strong>大大的 Vim 配置。
網址：<a href="https://github.com/kaochenlong/eddie-vim">https://github.com/kaochenlong/eddie-vim</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[我的網站開發之路]]></title>
    <link href="http://revo-skill.frost.tw/blog/2012/03/25/my-web-develop-way/"/>
    <updated>2012-03-25T14:38:00+08:00</updated>
    <id>http://revo-skill.frost.tw/blog/2012/03/25/my-web-develop-way</id>
    <content type="html"><![CDATA[<p>最近，總感覺發生了許多事。</p>

<p>比較值得注意的大概就是我開始學習 Rails 了吧！<br />
過去有很長的一段時間在 PHP 上面，至少也有五、六年了！<br />
這段時間，雖然也知道有 Java, Ruby, Perl 等等可以用來開發網站的語言，但是我就唯獨喜愛著 PHP 這一個老朋友，畢竟，從小到大陪我長大的就是他。</p>

<p>隨著時間增長，我可以說是越來越喜歡製作網站。在學習程式語言到一個程度，我開始思考我希望前進的方向。到底是設計還是程式呢？</p>

<!-- more -->


<p>最後，我做出一個決定「兩個都喜歡，都不該放手！」</p>

<p>所以，一年前左右的學測，我選擇了設計學院。<br />
當時我找了不少老師討論，我最後給老師的結論是「程式的能力已經不差了，但是設計的能力還有待琢磨，所以我決定讀設計」</p>

<p>還好，這個決定沒錯。</p>

<p>學習程式，從小到大就是看書、查資料，自主的學習跟經驗都已經足夠。即使不依靠老師，我也能夠學到足夠的東西。但是，相較於設計能力，沒有老師，這半年多就沒有現在的進步。</p>

<p>所以，這些選擇我都不後悔。</p>

<p>那麼，為什麼我開始接觸 Ruby on Rails 了呢？難道我不愛 PHP 了嗎？<br />
事情發生在大約一個月前，一陣心血來潮我就打開 Rails 教學，然後玩了玩，最後發現「真是個不錯的東西！」</p>

<p>這就是一切事件的開始。</p>

<p>在 PHP 上，我認為快速、簡單的製作小網站 Ex. 留言板、討論版 等等其實很適合，也很習慣。但是每當我想提高製作的規模時，總是有點力不從心。撰寫規則、目錄規劃等等，總是花上我不少時間。</p>

<p>相較之下，使用 Rails 有 CLI 的搭配，就快多了！RESTful的網址結構等等，都讓規模稍大、重新做起的網站製作容易多。</p>

<p>所以我這樣決定：</p>

<blockquote><p>PHP用在製作如 WordPress 的 Plugin/Theme 上吧！站在 WordPress 的肩膀上，製作網站會容易多。
而 Rails 就用於製作一些需要從頭做起、規模稍大、架構稍完整的網站。</p></blockquote>

<p>而且從 Rails 的架構上，我也學到很多東西。</p>

<p><strong>所以，我有了新的目標。</strong></p>

<p>接下來的大學時間 3.5 年，我決定要完成這些事情。<br />
<strong>而且要用一篇篇文章記錄下每個進度</strong></p>

<ul>
<li>學會 Ruby &amp; Rails</li>
<li>保持 PHP 的能力，並且更深入</li>
<li>用 Middleman + Compass 設計網站</li>
<li>找出 CG &amp; Web 的融合方法
  (這是高中寫的一篇小論文，也是我的目標之一)</li>
<li>純熟運用 HTML5/CSS3</li>
<li>熟悉使用 Ajax/jQuery/Backbone.js</li>
<li>有一套自己的開發流程</li>
<li>成為一個優秀的 Web Designer</li>
<li>運用自己的優勢，做到 Designer + Programer 的境界
  (最終目標)</li>
</ul>


<p>我很清楚沒什麼捷徑，之後就是我起步向前前進就對了！<br />
我不覺得我有比別人好多少，但是比努力跟進步，在我選擇的領域裡面我不想輸人。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[製作一個 Hubot 的噗浪 Adapter]]></title>
    <link href="http://revo-skill.frost.tw/blog/2012/03/18/create-a-hubot-plurk-adapter/"/>
    <updated>2012-03-18T14:02:00+08:00</updated>
    <id>http://revo-skill.frost.tw/blog/2012/03/18/create-a-hubot-plurk-adapter</id>
    <content type="html"><![CDATA[<h3>前言</h3>

<hr />

<p>我似乎非常喜歡搞前言這套，所以請大家聽我慢慢說完吧！</p>

<p>大約是三、四個月前的事情，網友向我邀文，我就告訴他最近 HuBot 更新後，將 Adapter 分離出來，以 Module 的形式載入，我想之後的更新會很棒吧！</p>

<p>不過，我卻拖到前幾天，我才心血來潮的在一天飆出機器人（原因不明，而且還被很多地方卡到陰）</p>

<p>這就是，故事的開始（好，請不要打我！）</p>

<p>（本文以 Deploy 到 Heroku 為最終目標）</p>

<!-- more -->


<p></p>

<h3>有雷，要先防護一下！</h3>

<hr />

<p>根據我的經驗，我被雷炸死超多次了！
（把 Adapter 什麼的寫出來一天一定夠，但是除雷讓我用了一半以上的時間 Orz）</p>

<ol>
<li>Hubot 除了內建的兩個 Adapter 之外都要以 Node.js 的 Module 方式才能運作（這代表說你一定得放到 node_modules 才會運作）</li>
<li>Hubot 的 bin/hubot 裡面寫著 npm install 所以不管你怎麼改原始碼也不能改變第一點的狀況</li>
<li>當你 Deploy 到 Heroku 上的時候，不能用 npm link</li>
<li>在 Heroku 上所有 module 都得用 npm 安裝（package.json內設定）</li>
</ol>


<p>其實上述都在討論同一件事情： Node.JS 的模組</p>

<p>而且模組不能設定相對路徑之類的來安裝，一定要透過</p>

<ul>
<li>NPM 官方的檔案</li>
<li>Git</li>
<li>HTTP</li>
</ul>


<p>上述三種方式才能安裝（說實在的 tgz 也是個雷，雖然說可用 tarball 裝，但是用 tar -zcf 壓縮是裝不了的）</p>

<p>被這些雷到可能是我笨（牆角）</p>

<h3>建立 Adapter</h3>

<hr />

<p>只需要兩個檔案</p>

<ul>
<li>package.json</li>
<li>plurk.coffee</li>
</ul>


<p>有這兩個就足以變成 Node.JS 的模組了～</p>

<p>在開始 Coding 之前，先來設定一下 package.json 弄好相依</p>

<pre><code>
{
  "name": "hubot-plurk",
  "version": "0.1.1",
  "main": "./plurk",
  "dependencies":{
    "hubot": ">=2.0.5",
    "oauth": "",
    "cron":""
  }
}

</code></pre>


<p>因為那個 Heroku 的 Cron Add-on 會把運算花費算到裡面，那就乾脆用 Node.JS 的 cron 模組就好了！而登入噗浪還需要 OAuth 才行，也裝上 OAuth 這樣</p>

<blockquote><p>Hubot 在讀取非內建模組時，會自動在前面加上 hubot- 的前置。</p></blockquote>

<h3>建立 Robot 跟 API</h3>

<hr />

<p>基本上程式碼都是參考 Twitter 的 Adapter 來製作，但是實際上竟然只有一樣用 OAuth 這一點而已（昏）</p>

<p>Twitter 有 Streaming 可用而 Plurk 則得用 Comet 方式來達到即時讀取。</p>

<figure class='code'><figcaption><span>plurk.coffee</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
</pre></td><td class='code'><pre><code class='coffeescript'><span class='line'><span class="nv">Robot = </span><span class="nx">require</span><span class="p">(</span><span class="s2">&quot;hubot&quot;</span><span class="p">).</span><span class="nx">robot</span><span class="p">()</span>
</span><span class='line'><span class="nv">Adapter = </span><span class="nx">require</span><span class="p">(</span><span class="s2">&quot;hubto&quot;</span><span class="p">).</span><span class="nx">adapter</span><span class="p">()</span>
</span><span class='line'>
</span><span class='line'><span class="nv">EventEmitter = </span><span class="nx">require</span><span class="p">(</span><span class="s2">&quot;events&quot;</span><span class="p">).</span><span class="nx">EventEmitter</span>
</span><span class='line'>
</span><span class='line'><span class="nv">oauth = </span><span class="nx">require</span><span class="p">(</span><span class="s2">&quot;oauth&quot;</span><span class="p">)</span>
</span><span class='line'><span class="nv">cronJob = </span><span class="nx">require</span><span class="p">(</span><span class="s2">&quot;cron&quot;</span><span class="p">).</span><span class="nx">CronJob</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nx">Plurk</span> <span class="nx">exntends</span> <span class="nx">Adapter</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nx">PlurkStreaming</span> <span class="nx">exnteds</span> <span class="nx">EventEmitter</span>
</span></code></pre></td></tr></table></div></figure>


<p>先弄個基本架構，至於為什麼要叫 PlurkStreaming 只是因為參考的是 Twitter 而已（被拖走）</p>

<p>接著先給 Plurk 這個 Class 放進去幾個Method。
（基本上只要有 run, send, reply 就夠了，而 run 用來做初始化的部分）</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='coffeescript'><span class='line'><span class="k">class</span> <span class="nx">Plurk</span> <span class="nx">entends</span> <span class="nx">Adapter</span>
</span><span class='line'>  <span class="nv">send: </span><span class="nf">(plurk_id, strings…) -&gt;</span>
</span><span class='line'>
</span><span class='line'>  <span class="nv">reply: </span><span class="nf">(plurk_id, strings…) -&gt;</span>
</span><span class='line'>
</span><span class='line'>  <span class="nv">run: </span><span class="o">-&gt;</span>
</span><span class='line'>
</span></code></pre></td></tr></table></div></figure>


<p>看起來有點東西，來弄主要的 API 結合部分。</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
</pre></td><td class='code'><pre><code class='coffeescript'><span class='line'><span class="k">class</span> <span class="nx">PlurkStreaming</span> <span class="k">extends</span> <span class="nx">EventEmitter</span>
</span><span class='line'>
</span><span class='line'>  <span class="nv">consuctor: </span><span class="nf">(options) -&gt;</span>
</span><span class='line'>
</span><span class='line'>  <span class="nv">plurk: </span><span class="nf">(callback) -&gt;</span>
</span><span class='line'>    <span class="c1">#觀察河道</span>
</span><span class='line'>  <span class="nv">getChannel: </span><span class="o">-&gt;</span>
</span><span class='line'>    <span class="c1">#取得 Comet 網址</span>
</span><span class='line'>  <span class="nv">reply: </span><span class="nf">(plurk_id, message) -&gt;</span>
</span><span class='line'>    <span class="c1">#回噗</span>
</span><span class='line'>  <span class="nv">acceptFriends: </span><span class="o">-&gt;</span>
</span><span class='line'>    <span class="c1">#接受好友</span>
</span><span class='line'>  <span class="nv">get: </span><span class="nf">(path, callback) -&gt;</span>
</span><span class='line'>    <span class="c1">#GET 請求</span>
</span><span class='line'>  <span class="nv">post: </span><span class="nf">(path, body, callback)-&gt;</span>
</span><span class='line'>    <span class="c1">#POST 請求（其實是裝飾）</span>
</span><span class='line'>  <span class="nv">request: </span><span class="nf">(method, path, body, callback)-&gt;</span>
</span><span class='line'>    <span class="c1">#主要的 OAuth 請求</span>
</span><span class='line'>  <span class="nv">comet: </span><span class="nf">(server, callback)-&gt;</span>
</span><span class='line'>    <span class="c1">#噗浪的 Comet 傳回是 JavaScript Callback 要另外處理後才會變成 JSON</span>
</span></code></pre></td></tr></table></div></figure>


<p>然後我們先把注意力集中到 constructor 上，先把建構子弄好。</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
</pre></td><td class='code'><pre><code class='coffeescript'><span class='line'>  <span class="nv">constructor: </span><span class="nf">(options) -&gt;</span>
</span><span class='line'>    <span class="k">super</span><span class="p">()</span>
</span><span class='line'>    <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">key</span><span class="o">?</span> <span class="o">and</span> <span class="nx">options</span><span class="p">.</span><span class="nx">secret</span><span class="o">?</span> <span class="o">and</span> <span class="nx">options</span><span class="p">.</span><span class="nx">token</span><span class="o">?</span> <span class="o">and</span> <span class="nx">options</span><span class="p">.</span><span class="nx">token_secret</span><span class="o">?</span>
</span><span class='line'>      <span class="vi">@key = </span><span class="nx">options</span><span class="p">.</span><span class="nx">key</span>
</span><span class='line'>      <span class="vi">@secret = </span><span class="nx">options</span><span class="p">.</span><span class="nx">secret</span>
</span><span class='line'>      <span class="vi">@token = </span><span class="nx">options</span><span class="p">.</span><span class="nx">token</span>
</span><span class='line'>      <span class="vi">@token_secret = </span><span class="nx">options</span><span class="p">.</span><span class="nx">token_secret</span>
</span><span class='line'>      <span class="c1">#建立 OAuth 連接</span>
</span><span class='line'>      <span class="vi">@consumer = </span><span class="k">new</span> <span class="nx">oauth</span><span class="p">.</span><span class="nx">OAuth</span><span class="p">(</span>
</span><span class='line'>        <span class="s2">&quot;http://www.plurk.com/OAuth/request_token&quot;</span><span class="p">,</span>
</span><span class='line'>        <span class="s2">&quot;http://www.plurk.com/OAuth/access_token&quot;</span><span class="p">,</span>
</span><span class='line'>        <span class="nx">@key</span><span class="p">,</span>
</span><span class='line'>        <span class="nx">@secret</span><span class="p">,</span>
</span><span class='line'>        <span class="s2">&quot;1.0&quot;</span><span class="p">,</span>
</span><span class='line'>        <span class="s2">&quot;http://www.plurk.com/OAuth/authorize&quot;</span><span class="p">.</span>
</span><span class='line'>        <span class="s2">&quot;HMAC-SHA1&quot;</span>
</span><span class='line'>      <span class="p">)</span>
</span><span class='line'>      <span class="vi">@domain = </span><span class="s2">&quot;www.plurk.com&quot;</span>
</span><span class='line'>      <span class="c1">#初始化取得Comet網址</span>
</span><span class='line'>      <span class="nx">do</span> <span class="nx">@getChannel</span>
</span><span class='line'>    <span class="k">else</span>
</span><span class='line'>      <span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="s2">&quot;參數不足，需要 Key, Secret, Token, Token Secret&quot;</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>這樣建構子就差不多了！</p>

<p>接著來弄 request 這個 method (comet 很類似，這個寫好複製貼上一下～)</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
</pre></td><td class='code'><pre><code class='coffeescript'><span class='line'>  <span class="nv">request: </span><span class="nf">(method, path, body, callback) -&gt;</span>
</span><span class='line'>    <span class="c1">#記錄一下這次的 Request</span>
</span><span class='line'>    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">&quot;http://#{@domain}#{path}&quot;</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1"># Callback 這邊先不丟進去，要用另一種方式處理</span>
</span><span class='line'>    <span class="nv">request = </span><span class="nx">@consumer</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s2">&quot;http://#{@domain}#{path}&quot;</span><span class="p">,</span> <span class="nx">@token</span><span class="p">,</span> <span class="nx">@token_secret</span><span class="p">,</span> <span class="kc">null</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'>    <span class="nx">request</span><span class="p">.</span><span class="kc">on</span> <span class="s2">&quot;response&quot;</span><span class="p">,</span> <span class="nf">(res) -&gt;</span>
</span><span class='line'>      <span class="nx">res</span><span class="p">.</span><span class="kc">on</span> <span class="s2">&quot;data&quot;</span><span class="p">,</span> <span class="nf">(chunk) -&gt;</span>
</span><span class='line'>        <span class="nx">parseResponse</span><span class="p">(</span><span class="nx">chunk</span><span class="o">+</span><span class="s1">&#39;&#39;</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span>
</span><span class='line'>      <span class="nx">res</span><span class="p">.</span><span class="kc">on</span> <span class="s2">&quot;end&quot;</span><span class="p">,</span> <span class="nf">(data) -&gt;</span>
</span><span class='line'>        <span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="s2">&quot;End Request: #{path}&quot;</span>
</span><span class='line'>      <span class="nx">res</span><span class="p">.</span><span class="kc">on</span> <span class="s2">&quot;error&quot;</span><span class="p">,</span> <span class="nf">(data) -&gt;</span>
</span><span class='line'>        <span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="s2">&quot;Error: &quot;</span> <span class="o">+</span> <span class="nx">data</span>
</span><span class='line'>
</span><span class='line'>    <span class="nx">request</span><span class="p">.</span><span class="nx">end</span><span class="p">()</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1">#處理資料</span>
</span><span class='line'>    <span class="nv">parseResponse = </span><span class="nf">(data, callback) -&gt;</span>
</span><span class='line'>      <span class="k">if</span> <span class="nx">data</span><span class="p">.</span><span class="nx">length</span> <span class="o">&gt;</span> <span class="mi">0</span>
</span><span class='line'>        <span class="c1">#用 Try/Catch 避免處理 JSON 出錯導致整個中斷</span>
</span><span class='line'>        <span class="k">try</span>
</span><span class='line'>          <span class="nx">callback</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span>
</span><span class='line'>        <span class="k">catch</span> <span class="nx">err</span>
</span><span class='line'>          <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">&quot;Error Parse JSON:&quot;</span> <span class="o">+</span> <span class="nx">data</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
</span><span class='line'>          <span class="c1">#繼續執行</span>
</span><span class='line'>          <span class="nx">callback</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">data</span> <span class="o">||</span> <span class="p">{}</span>
</span></code></pre></td></tr></table></div></figure>


<p>大致上就是這樣，根據程式碼，其實是無視 POST 的。
（如果沒有特殊需求其實也不會用到 POST 方式）</p>

<p>而 Comet 的處理方式類似，不過我們要動用到 EventEmitter 的功能。
（避免一個 Request 還未結束又開始新的 Comet, 造成連續讀取兩次相同訊息的問題）</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
</pre></td><td class='code'><pre><code class='coffeescript'><span class='line'>  <span class="nv">comet: </span><span class="nf">(server, callback) -&gt;</span>
</span><span class='line'>    <span class="c1">#在 Callback 裡面會找不到自身，所以設定區域變數</span>
</span><span class='line'>    <span class="nv">self = </span><span class="err">@</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1">#記錄一下這次的 Request</span>
</span><span class='line'>    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">&quot;[Comet] #{server}&quot;</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1"># Callback 這邊先不丟進去，要用另一種方式處理</span>
</span><span class='line'>    <span class="nv">request = </span><span class="nx">@consumer</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s2">&quot;http://#{@domain}#{path}&quot;</span><span class="p">,</span> <span class="nx">@token</span><span class="p">,</span> <span class="nx">@token_secret</span><span class="p">,</span> <span class="kc">null</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'>    <span class="nx">request</span><span class="p">.</span><span class="kc">on</span> <span class="s2">&quot;response&quot;</span><span class="p">,</span> <span class="nf">(res) -&gt;</span>
</span><span class='line'>      <span class="nx">res</span><span class="p">.</span><span class="kc">on</span> <span class="s2">&quot;data&quot;</span><span class="p">,</span> <span class="nf">(chunk) -&gt;</span>
</span><span class='line'>        <span class="nx">parseResponse</span><span class="p">(</span><span class="nx">chunk</span><span class="o">+</span><span class="s1">&#39;&#39;</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span>
</span><span class='line'>      <span class="nx">res</span><span class="p">.</span><span class="kc">on</span> <span class="s2">&quot;end&quot;</span><span class="p">,</span> <span class="nf">(data) -&gt;</span>
</span><span class='line'>        <span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="s2">&quot;End Request: #{path}&quot;</span>
</span><span class='line'>        <span class="c1">#請求結束，發出事件通知可以進行下一次請求</span>
</span><span class='line'>        <span class="nx">self</span><span class="p">.</span><span class="nx">emit</span> <span class="s2">&quot;nextPlurk&quot;</span>
</span><span class='line'>      <span class="nx">res</span><span class="p">.</span><span class="kc">on</span> <span class="s2">&quot;error&quot;</span><span class="p">,</span> <span class="nf">(data) -&gt;</span>
</span><span class='line'>        <span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="s2">&quot;Error: &quot;</span> <span class="o">+</span> <span class="nx">data</span>
</span><span class='line'>
</span><span class='line'>    <span class="nx">request</span><span class="p">.</span><span class="nx">end</span><span class="p">()</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1">#處理資料</span>
</span><span class='line'>    <span class="nv">parseResponse = </span><span class="nf">(data, callback) -&gt;</span>
</span><span class='line'>      <span class="k">if</span> <span class="nx">data</span><span class="p">.</span><span class="nx">length</span> <span class="o">&gt;</span> <span class="mi">0</span>
</span><span class='line'>        <span class="c1">#用 try/catch 避免失敗中斷</span>
</span><span class='line'>        <span class="k">try</span>
</span><span class='line'>          <span class="c1">#去掉 JavaScript 的 Callback</span>
</span><span class='line'>          <span class="nv">data = </span><span class="nx">data</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="sr">/CometChannel.scriptCallback\((.+)\);\s*/</span><span class="p">)</span>
</span><span class='line'>          <span class="nv">jsonData = </span><span class="s2">&quot;&quot;</span>
</span><span class='line'>
</span><span class='line'>          <span class="k">if</span> <span class="nx">data</span><span class="o">?</span>
</span><span class='line'>            <span class="nv">jsonData = </span><span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">data</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
</span><span class='line'>          <span class="k">else</span>
</span><span class='line'>            <span class="c1">#如果沒有任何 Match 嘗試直接 parse</span>
</span><span class='line'>            <span class="nv">jsonData = </span><span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span>
</span><span class='line'>        <span class="k">catch</span> <span class="nx">err</span>
</span><span class='line'>          <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">&quot;[Comet] Error:&quot;</span><span class="p">,</span> <span class="nx">data</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'>        <span class="c1">#用 Try/Catch 避免處理 JSON 出錯導致整個中斷</span>
</span><span class='line'>        <span class="k">try</span>
</span><span class='line'>          <span class="c1">#只傳入 json 的 data 部分</span>
</span><span class='line'>          <span class="nx">callback</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">jsonData</span><span class="p">.</span><span class="nx">data</span>
</span><span class='line'>        <span class="k">catch</span> <span class="nx">err</span>
</span><span class='line'>          <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">&quot;[Comet]Error Parse JSON:&quot;</span> <span class="o">+</span> <span class="nx">data</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
</span><span class='line'>          <span class="c1">#繼續執行</span>
</span><span class='line'>          <span class="nx">callback</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">data</span> <span class="o">||</span> <span class="p">{}</span>
</span></code></pre></td></tr></table></div></figure>


<p>至於為什麼要這樣做呢？因為在測試時竟然因為噗浪 Lag 而沒讀到完整的 Comet 資料，然後就炸掉了！
（這樣至少不會造成運行中斷，睡覺時就不會碰到一個無法用就炸掉）</p>

<p>後面的 get 跟 post 就簡單多了！</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='coffeescript'><span class='line'>  <span class="nv">get: </span><span class="nf">(path, callback) -&gt;</span>
</span><span class='line'>    <span class="nx">@request</span><span class="p">(</span><span class="s2">&quot;GET&quot;</span><span class="p">,</span> <span class="nx">path</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'>  <span class="nv">post: </span><span class="nf">(path, body, callback) -&gt;</span>
</span><span class='line'>    <span class="nx">@request</span><span class="p">(</span><span class="s2">&quot;POST&quot;</span><span class="p">,</span> <span class="nx">path</span><span class="p">,</span> <span class="nx">body</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span>
</span><span class='line'>
</span></code></pre></td></tr></table></div></figure>


<p>接著處理取的 Comet 網址的 getChannel</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='coffeescript'><span class='line'>  <span class="nv">getChannel: </span><span class="o">-&gt;</span>
</span><span class='line'>    <span class="nv">self = </span><span class="err">@</span>
</span><span class='line'>
</span><span class='line'>    <span class="nx">@get</span> <span class="s2">&quot;/APP/Realtime/getUserChannel&quot;</span><span class="p">,</span> <span class="nf">(error, data) -&gt;</span>
</span><span class='line'>      <span class="k">if</span> <span class="o">!</span><span class="nx">error</span>
</span><span class='line'>        <span class="c1">#檢查是否有 comet server</span>
</span><span class='line'>        <span class="k">if</span> <span class="nx">data</span><span class="p">.</span><span class="nx">comet_server</span><span class="o">?</span>
</span><span class='line'>          <span class="nv">self.channel = </span><span class="nx">data</span><span class="p">.</span><span class="nx">comet_server</span>
</span><span class='line'>          <span class="c1">#如果沒有 Channel Ready 就嘗試連接會失敗</span>
</span><span class='line'>          <span class="nx">self</span><span class="p">.</span><span class="nx">emit</span><span class="p">(</span><span class="s1">&#39;channel_ready&#39;</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>接著處理 plurk 這部份</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='coffeescript'><span class='line'>
</span><span class='line'>  <span class="nv">plurk: </span><span class="nf">(callback) -&gt;</span>
</span><span class='line'>    <span class="c1">#其實官方文件是要設定 offset 的，不過目前沒有想到設定的方法，以及即使沒有設定也能正常運作</span>
</span><span class='line'>    <span class="nx">@comet</span> <span class="nx">@channel</span><span class="p">,</span> <span class="nf">(error, data) -&gt;</span>
</span><span class='line'>      <span class="k">if</span> <span class="nx">data</span><span class="o">?</span>
</span><span class='line'>        <span class="c1">#將一筆筆的資料一一遞送</span>
</span><span class='line'>        <span class="k">for</span> <span class="nx">plurk</span> <span class="k">in</span> <span class="nx">data</span>
</span><span class='line'>          <span class="nx">callback</span> <span class="nx">plurk</span>
</span></code></pre></td></tr></table></div></figure>


<p>最後處理回噗跟接受好友就完成 API 的連接了！
（當然，其他部分大家可以自行擴充）</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
</pre></td><td class='code'><pre><code class='coffeescript'><span class='line'>  <span class="nv">reply: </span><span class="nf">(plurk_id, message) -&gt;</span>
</span><span class='line'>    <span class="c1">#設定回噗的參數</span>
</span><span class='line'>    <span class="nv">path = </span><span class="s2">&quot;/APP/Responses/responseAdd?plurk_id=#{plurk_id}&amp;content=&quot;</span> <span class="o">+</span> <span class="nb">encodeURIComponent</span><span class="p">(</span><span class="nx">message</span><span class="p">)</span> <span class="o">+</span> <span class="s2">&quot;&amp;qualifier=says&quot;</span>
</span><span class='line'>    <span class="nx">@get</span> <span class="nx">path</span><span class="p">,</span> <span class="nf">(error, data)-&gt;</span>
</span><span class='line'>      <span class="c1">#啥都不做</span>
</span><span class='line'>
</span><span class='line'>  <span class="nv">acceptFriends: </span><span class="o">-&gt;</span>
</span><span class='line'>    <span class="nv">self = </span><span class="err">@</span>
</span><span class='line'>    <span class="c1">#用 Cron Module 的時候到了！</span>
</span><span class='line'>    <span class="nx">cronJob</span> <span class="s2">&quot;0 0 * * * *&quot;</span><span class="p">,</span> <span class="nf">() -&gt;</span>
</span><span class='line'>      <span class="nx">self</span><span class="p">.</span><span class="nx">get</span> <span class="s2">&quot;/APP/Alerts/addAllAsFriends&quot;</span><span class="p">,</span> <span class="nf">(error, data) -&gt;</span>
</span><span class='line'>        <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">&quot;接受所有好友邀請：&quot;</span><span class="p">,</span> <span class="nx">data</span><span class="p">)</span>
</span><span class='line'>
</span></code></pre></td></tr></table></div></figure>


<p>那麼，先來處理 Plurk Adaper 好處理的部份</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='coffeescript'><span class='line'>  <span class="nv">send: </span><span class="nf">(plruk_id, strings…)-&gt;</span>
</span><span class='line'>    <span class="c1">#跟 Reply 一樣，直接交給 reply 做</span>
</span><span class='line'>    <span class="nx">@reply</span> <span class="nx">plurk_id</span><span class="p">,</span> <span class="nx">strings</span><span class="err">…</span>
</span><span class='line'>
</span><span class='line'>  <span class="nv">reply: </span><span class="nf">(plurk_id, strings…) -&gt;</span>
</span><span class='line'>    <span class="nx">strings</span><span class="p">.</span><span class="nx">forEach</span> <span class="p">(</span><span class="nx">message</span><span class="p">)</span> <span class="o">=&gt;</span>
</span><span class='line'>      <span class="nx">@bot</span><span class="p">.</span><span class="nx">reply</span><span class="p">(</span><span class="nx">plruk_id</span><span class="p">,</span> <span class="nx">message</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>接著把 run 處理好就可以上線運作摟！</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
</pre></td><td class='code'><pre><code class='coffeescript'><span class='line'>  <span class="nv">run: </span><span class="o">-&gt;</span>
</span><span class='line'>    <span class="nv">self = </span><span class="err">@</span>
</span><span class='line'>    <span class="nv">options =</span>
</span><span class='line'>      <span class="nv">key: </span><span class="nx">process</span><span class="p">.</span><span class="nx">env</span><span class="p">.</span><span class="nx">HUBOT_PLURK_KEY</span>
</span><span class='line'>      <span class="nv">secret: </span><span class="nx">process</span><span class="p">.</span><span class="nx">env</span><span class="p">.</span><span class="nx">HUBOT_PLURK_SECRET</span>
</span><span class='line'>      <span class="nv">token: </span><span class="nx">process</span><span class="p">.</span><span class="nx">env</span><span class="p">.</span><span class="nx">HUBOT_PLURK_TOKEN</span>
</span><span class='line'>      <span class="nv">token_secret: </span><span class="nx">process</span><span class="p">.</span><span class="nx">env</span><span class="p">.</span><span class="nx">HUBOT_PLURK_TOKEN_SECRET</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1">#創建剛剛的 API</span>
</span><span class='line'>    <span class="nv">bot = </span><span class="k">new</span> <span class="nx">PlurkStreaming</span><span class="p">(</span><span class="nx">options</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1">#依照 Twitter 的 new Robot.TextMessage 會沒有反應，所以參考 hubot-minecraft 的方式</span>
</span><span class='line'>    <span class="nv">r = </span><span class="nx">@robot</span><span class="p">.</span><span class="nx">constructor</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1">#處理噗浪河道訊息</span>
</span><span class='line'>    <span class="vi">@doPlurk = </span><span class="nf">(data)-&gt;</span>
</span><span class='line'>      <span class="c1">#檢查是否為回噗</span>
</span><span class='line'>      <span class="k">if</span> <span class="nx">data</span><span class="p">.</span><span class="nx">response</span><span class="o">?</span>
</span><span class='line'>        <span class="nv">data.content_raw = </span><span class="nx">data</span><span class="p">.</span><span class="nx">response</span><span class="p">.</span><span class="nx">content_raw</span>
</span><span class='line'>        <span class="nv">data.user_id = </span><span class="nx">data</span><span class="p">.</span><span class="nx">response</span><span class="p">.</span><span class="nx">user_id</span>
</span><span class='line'>      <span class="c1">#確定有噗浪ID跟訊息</span>
</span><span class='line'>      <span class="k">if</span> <span class="nx">data</span><span class="p">.</span><span class="nx">plurk_id</span><span class="o">?</span> <span class="o">and</span> <span class="nx">data</span><span class="p">.</span><span class="nx">content_raw</span>
</span><span class='line'>        <span class="nx">self</span><span class="p">.</span><span class="nx">receive</span> <span class="k">new</span> <span class="nx">r</span><span class="p">.</span><span class="nx">TextMessage</span><span class="p">(</span><span class="nx">data</span><span class="p">.</span><span class="nx">plurk_id</span><span class="p">,</span> <span class="nx">data</span><span class="p">.</span><span class="nx">content_raw</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1">#取得 Comet Server 完成，開始第一次 Comet 連接</span>
</span><span class='line'>    <span class="nx">bot</span><span class="p">.</span><span class="kc">on</span> <span class="s2">&quot;channel_ready&quot;</span><span class="p">,</span> <span class="nf">() -&gt;</span>
</span><span class='line'>      <span class="nx">bot</span><span class="p">.</span><span class="nx">plurk</span> <span class="nx">self</span><span class="p">.</span><span class="nx">doPlurk</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1">#上一次 Comet 完成，繼續 Polling</span>
</span><span class='line'>    <span class="nx">bot</span><span class="p">.</span><span class="kc">on</span> <span class="s2">&quot;nextPlurk&quot;</span><span class="p">,</span> <span class="nf">()-&gt;</span>
</span><span class='line'>      <span class="nx">bot</span><span class="p">.</span><span class="nx">plurk</span> <span class="nx">self</span><span class="p">.</span><span class="nx">doPlurk</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1">#定時接受好友邀請</span>
</span><span class='line'>    <span class="nx">do</span> <span class="nx">bot</span><span class="p">.</span><span class="nx">acceptFriends</span>
</span><span class='line'>
</span><span class='line'>    <span class="vi">@bot = </span><span class="nx">bot</span>
</span></code></pre></td></tr></table></div></figure>


<p>終於，完成 Adapter！</p>

<p>接下來簡單提醒一下 Deploy 到 Heroku 的注意事項。</p>

<ol>
<li>hubot-plurk 已經被我佔在 npm 上了，如果想丟到 npm 安裝可能不能用這個名字</li>
<li>用 npm pack 就會產生 hubot-plurk-0.x.x.tgz 的檔案，丟到 Dropbox 之類的網站後，在 package.json 相依版本的地方設定這個網址就可以安裝（不用透過 npm ）</li>
<li>Procfile 裡面的 web: 建議改成 worker: 因為用 web dyno 會因為沒有人打開頁面而暫停運作（要持續運作得用 worker 但會犧牲掉 Hubot 內建的網頁功能）</li>
<li>在下載下來的 Hubot 用 make package 指令就可以產生 deploy 用的資料夾</li>
<li>scripts 資料夾內是互動部分，不需要像 Adapter 如此大費周章處理（新增檔案並且設計好對白，之後就會回噗了～）</li>
</ol>


<p>我開發用的機器人在此，大家可以去跟他玩玩<br />
<a href="http://plurk.com/elct9620_bot">http://plurk.com/elct9620_bot</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[三天做一個論壇 - Part 1]]></title>
    <link href="http://revo-skill.frost.tw/blog/2012/01/25/create-a-forum-in-3-day-part1/"/>
    <updated>2012-01-25T21:43:00+08:00</updated>
    <id>http://revo-skill.frost.tw/blog/2012/01/25/create-a-forum-in-3-day-part1</id>
    <content type="html"><![CDATA[<h3>前言</h3>

<hr />

<p>上次挑戰三十分鐘完成留言板雖然不幸（？）失敗，不過這次我成功的在三天的限制內完成了（簡易）論壇。</p>

<p>不過，大概也是時間放的比較寬鬆，所以也比較順利在時間內完成。這次跟上次留言板一樣，是使用 PHP + MongoDB 進行開發。</p>

<!--more-->


<h3>規劃結構</h3>

<hr />

<p>其實和上次大致上沒有什麼變化，不過架構稍微又更加的細分了一些。<br />
<a href="http://www.flickr.com/photos/elct9620/6760280007/"><img src="http://farm8.staticflickr.com/7024/6760280007_4e2d76c2bb.jpg" alt="螢幕快照 2012-01-25 下午10.25.44" /></a></p>

<h3>初始化系統</h3>

<hr />

<p>首先先建立 index.php 檔案在根目錄，而其他一些Library檔案就請各位自己複製摟（參考上次的 30 分鐘留言板）</p>

<figure class='code'><figcaption><span>index.php</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="cp">&lt;?php</span>
</span><span class='line'><span class="sd">/**</span>
</span><span class='line'><span class="sd"> * 3Day Fourum</span>
</span><span class='line'><span class="sd"> * </span>
</span><span class='line'><span class="sd"> * @package 3day-fourm</span>
</span><span class='line'><span class="sd"> * @author Aotoki</span>
</span><span class='line'><span class="sd"> * @version 1.0</span>
</span><span class='line'><span class="sd"> */</span>
</span><span class='line'>
</span><span class='line'><span class="cm">/* 載入設定檔 */</span>
</span><span class='line'>
</span><span class='line'><span class="k">require_once</span><span class="p">(</span><span class="s1">&#39;config.inc.php&#39;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'><span class="sd">/**</span>
</span><span class='line'><span class="sd"> * 載入必要函式庫 </span>
</span><span class='line'><span class="sd"> */</span>
</span><span class='line'>
</span><span class='line'><span class="c1">//Slim Framework </span>
</span><span class='line'><span class="k">require_once</span><span class="p">(</span><span class="nx">ABSPATH</span> <span class="o">.</span> <span class="s1">&#39;lib/Slim/Slim.php&#39;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'><span class="c1">//ActiveMongo</span>
</span><span class='line'><span class="k">require_once</span><span class="p">(</span><span class="nx">ABSPATH</span> <span class="o">.</span> <span class="s1">&#39;lib/ActiveMongo/ActiveMongo.php&#39;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'><span class="c1">//Facebook API</span>
</span><span class='line'><span class="k">require_once</span><span class="p">(</span><span class="nx">ABSPATH</span> <span class="o">.</span> <span class="s1">&#39;lib/Facebook/facebook.php&#39;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'><span class="cm">/* 載入起動器 */</span>
</span><span class='line'><span class="k">require_once</span><span class="p">(</span><span class="s1">&#39;bootstrap.php&#39;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'><span class="cp">?&gt;</span><span class="x"></span>
</span></code></pre></td></tr></table></div></figure>


<p>這次的 index.php 我們只針對設定檔、函式庫載入，並且呼叫 bootstrap.php 這個檔案初始畫整個網站。</p>

<p>接下來，我們來看看 bootstrap.php 檔案</p>

<figure class='code'><figcaption><span>bootstrap.php</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="cp">&lt;?php</span>
</span><span class='line'><span class="sd">/**</span>
</span><span class='line'><span class="sd"> * Bootstrap</span>
</span><span class='line'><span class="sd"> * </span>
</span><span class='line'><span class="sd"> * @package 3day-forum</span>
</span><span class='line'><span class="sd"> * @author Aotoki</span>
</span><span class='line'><span class="sd"> * @version 1.0</span>
</span><span class='line'><span class="sd"> */</span>
</span><span class='line'>
</span><span class='line'><span class="cm">/* 修正時區 */</span>
</span><span class='line'><span class="nx">date_default_timezone_set</span><span class="p">(</span><span class="s2">&quot;Asia/Taipei&quot;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'><span class="cm">/* 初始化 Slim Framework */</span>
</span><span class='line'><span class="nv">$app</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Slim</span><span class="p">(</span><span class="k">array</span><span class="p">(</span>
</span><span class='line'>  <span class="s1">&#39;mode&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;development&#39;</span><span class="p">,</span>
</span><span class='line'>  <span class="s1">&#39;http.version&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;1.1&#39;</span><span class="p">,</span>
</span><span class='line'>  <span class="s1">&#39;debug&#39;</span> <span class="o">=&gt;</span> <span class="nx">DEBUG</span><span class="p">,</span>
</span><span class='line'>  <span class="s1">&#39;templates.path&#39;</span> <span class="o">=&gt;</span> <span class="nx">ABSPATH</span> <span class="o">.</span> <span class="s1">&#39;vendor/themes&#39;</span><span class="p">,</span>
</span><span class='line'>  <span class="s1">&#39;cookies.secret_key&#39;</span> <span class="o">=&gt;</span> <span class="nx">COOKIE_SECRET_KEY</span><span class="p">,</span>
</span><span class='line'><span class="p">));</span>
</span><span class='line'>
</span><span class='line'><span class="cm">/* 初始化資料庫 */</span>
</span><span class='line'><span class="k">if</span><span class="p">(</span><span class="nx">DB_USER</span> <span class="o">||</span> <span class="nx">DB_PASS</span><span class="p">){</span>
</span><span class='line'>  <span class="nx">ActiveMongo</span><span class="o">::</span><span class="na">connect</span><span class="p">(</span><span class="nx">DB_NAME</span><span class="p">,</span> <span class="nx">DB_HOST</span><span class="p">,</span> <span class="nx">DB_USER</span><span class="p">,</span> <span class="nx">DB_PASS</span><span class="p">);</span>
</span><span class='line'><span class="p">}</span><span class="k">else</span><span class="p">{</span>
</span><span class='line'>  <span class="nx">ActiveMongo</span><span class="o">::</span><span class="na">connect</span><span class="p">(</span><span class="nx">DB_NAME</span><span class="p">,</span> <span class="nx">DB_HOST</span><span class="p">);</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="cm">/* 載入基本資訊 */</span>
</span><span class='line'><span class="nv">$basePath</span> <span class="o">=</span> <span class="nb">str_replace</span><span class="p">(</span><span class="s1">&#39;/index.php&#39;</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">,</span> <span class="nv">$app</span><span class="o">-&gt;</span><span class="na">request</span><span class="p">()</span><span class="o">-&gt;</span><span class="na">getRootUri</span><span class="p">())</span> <span class="o">.</span> <span class="s1">&#39;/&#39;</span><span class="p">;</span>
</span><span class='line'><span class="nv">$baseURL</span> <span class="o">=</span> <span class="s2">&quot;http://</span><span class="si">{</span><span class="nv">$_SERVER</span><span class="p">[</span><span class="s1">&#39;HTTP_HOST&#39;</span><span class="p">]</span><span class="si">}</span><span class="s2">/</span><span class="si">{</span><span class="nv">$basePath</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="nv">$app</span><span class="o">-&gt;</span><span class="na">view</span><span class="p">()</span><span class="o">-&gt;</span><span class="na">setData</span><span class="p">(</span><span class="s1">&#39;basePath&#39;</span><span class="p">,</span> <span class="nv">$basePath</span><span class="p">);</span>
</span><span class='line'><span class="nv">$app</span><span class="o">-&gt;</span><span class="na">view</span><span class="p">()</span><span class="o">-&gt;</span><span class="na">setData</span><span class="p">(</span><span class="s1">&#39;baseURL&#39;</span><span class="p">,</span> <span class="nv">$baseURL</span><span class="p">);</span>
</span><span class='line'><span class="nv">$app</span><span class="o">-&gt;</span><span class="na">view</span><span class="p">()</span><span class="o">-&gt;</span><span class="na">setData</span><span class="p">(</span><span class="s1">&#39;app&#39;</span><span class="p">,</span> <span class="nv">$app</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'><span class="cm">/* 讀取  App 邏輯 */</span>
</span><span class='line'><span class="k">require_once</span><span class="p">(</span><span class="nx">ABSPATH</span> <span class="o">.</span> <span class="s1">&#39;app/Template.php&#39;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'><span class="cm">/* 讀取 App 模型 */</span>
</span><span class='line'><span class="k">require_once</span><span class="p">(</span><span class="nx">ABSPATH</span> <span class="o">.</span> <span class="s1">&#39;app/models/Users.php&#39;</span><span class="p">);</span>
</span><span class='line'><span class="k">require_once</span><span class="p">(</span><span class="nx">ABSPATH</span> <span class="o">.</span> <span class="s1">&#39;app/models/Forums.php&#39;</span><span class="p">);</span>
</span><span class='line'><span class="k">require_once</span><span class="p">(</span><span class="nx">ABSPATH</span> <span class="o">.</span> <span class="s1">&#39;app/models/Thread.php&#39;</span><span class="p">);</span>
</span><span class='line'><span class="k">require_once</span><span class="p">(</span><span class="nx">ABSPATH</span> <span class="o">.</span> <span class="s1">&#39;app/models/Posts.php&#39;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'><span class="cm">/* 讀取 App 介面 */</span>
</span><span class='line'><span class="k">require_once</span><span class="p">(</span><span class="nx">ABSPATH</span> <span class="o">.</span> <span class="s1">&#39;app/web/Post.php&#39;</span><span class="p">);</span>
</span><span class='line'><span class="k">require_once</span><span class="p">(</span><span class="nx">ABSPATH</span> <span class="o">.</span> <span class="s1">&#39;app/web/User.php&#39;</span><span class="p">);</span>
</span><span class='line'><span class="k">require_once</span><span class="p">(</span><span class="nx">ABSPATH</span> <span class="o">.</span> <span class="s1">&#39;app/web/Home.php&#39;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'><span class="cm">/* 運行 */</span>
</span><span class='line'><span class="nv">$app</span><span class="o">-&gt;</span><span class="na">run</span><span class="p">();</span>
</span></code></pre></td></tr></table></div></figure>


<p>首先，為了避免時間顯示不正確，先將時區設定為 亞洲/台北 （各位可以依照自己的需求設定時區）</p>

<p>接下來，就是初始化 Slim Framework 以及 ActiveMongo 了！<br />
基本上和上一次無異，不過在 Slim Framework 的 Mode 部分，因為弦也忘記定義一個常數，所以各位務必記得在 Deploy 的時候將其改為 production 以免錯誤訊息露出來了！</p>

<blockquote><p>在 Slim Framework 會統一處理錯誤訊息，所以會有統一錯誤頁面。而 DEBUG + Development 的狀況下，則可以看到詳細的錯誤訊息，但在 Production 下，則只會顯示 Error 以及一段訊息說明發生錯誤了！</p></blockquote>

<p>不過，在這之外，還是要注意「在非 Slim Framework 作用區外的錯誤還是會被顯示」</p>

<p>接下來，我稍微設定了幾個常用的數值，並且以 $app->view()->setData() 的方式設定，往後所有使用 render() 方法的佈景都可以使用這些預置的變數。</p>

<p>接著，我們依序載入 App, Model, Web App 的部份。</p>

<blockquote><p>APP 這邊是指原生屬於系統，而非之後以 Plugin 加入的部份。</p></blockquote>

<p>另外，我們要注意 app/web/Home.php 是最後一個，一開始可能不會發現有什麼問題，不過當我們製作 Profile 頁面讓使用者修改 暱稱 時，就會發現 Router 在處理網址時發生了判斷問題。</p>

<h3>建立Model</h3>

<hr />

<p>因為 MongoDB 不需要另外建立資料表，所以我們就安心的直接建立 Model 檔案。</p>

<p>因為是論壇，所以會需要有記錄會員用的Model(Users.php)還有討論版（Forums.php）以及主題(Thread.php)跟文章(Posts.php)</p>

<p>首先，我們先來看會員的 Model 長怎樣。</p>

<figure class='code'><figcaption><span>app/models/Users.php</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="cp">&lt;?php</span>
</span><span class='line'><span class="sd">/**</span>
</span><span class='line'><span class="sd"> * User Model</span>
</span><span class='line'><span class="sd"> * </span>
</span><span class='line'><span class="sd"> * @package 3day-forum</span>
</span><span class='line'><span class="sd"> * @author Aotoki</span>
</span><span class='line'><span class="sd"> * @version 1.0</span>
</span><span class='line'><span class="sd"> */</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nc">Users</span> <span class="k">extends</span> <span class="nx">ActiveMongo</span>
</span><span class='line'><span class="p">{</span>
</span><span class='line'>  <span class="c1">//資料表欄位</span>
</span><span class='line'>  <span class="k">public</span> <span class="nv">$userID</span><span class="p">;</span> <span class="c1">//使用者編號(Facebook ID)</span>
</span><span class='line'>  <span class="k">public</span> <span class="nv">$Nickname</span><span class="p">;</span> <span class="c1">//使用者膩稱</span>
</span><span class='line'>  <span class="k">public</span> <span class="nv">$Type</span><span class="p">;</span> <span class="c1">//使用者類型（1 = Admin, 0 = User）</span>
</span><span class='line'>  
</span><span class='line'>  <span class="sd">/**</span>
</span><span class='line'><span class="sd">  * Get User</span>
</span><span class='line'><span class="sd">  * </span>
</span><span class='line'><span class="sd">  * @author Aotoki</span>
</span><span class='line'><span class="sd">  * @return object|bool 成功傳回 User 物件，失敗則傳回 FALSE</span>
</span><span class='line'><span class="sd">  */</span>
</span><span class='line'>  
</span><span class='line'>  <span class="k">static</span> <span class="k">public</span> <span class="k">function</span> <span class="nf">getUser</span><span class="p">(</span> <span class="nv">$fromUserID</span> <span class="o">=</span> <span class="k">NULL</span> <span class="p">)</span>
</span><span class='line'>  <span class="p">{</span>
</span><span class='line'>      <span class="nv">$userID</span> <span class="o">=</span> <span class="nv">$fromUserID</span><span class="p">;</span>
</span><span class='line'>      <span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="nv">$userID</span><span class="p">){</span>
</span><span class='line'>          <span class="nv">$FB</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Facebook</span><span class="p">(</span><span class="k">array</span><span class="p">(</span>
</span><span class='line'>              <span class="s1">&#39;appId&#39;</span> <span class="o">=&gt;</span> <span class="nx">FB_APP_ID</span><span class="p">,</span>
</span><span class='line'>              <span class="s1">&#39;secret&#39;</span> <span class="o">=&gt;</span> <span class="nx">FB_SECRET</span><span class="p">,</span>
</span><span class='line'>          <span class="p">));</span>
</span><span class='line'>          
</span><span class='line'>          <span class="nv">$userID</span> <span class="o">=</span> <span class="nv">$FB</span><span class="o">-&gt;</span><span class="na">getUser</span><span class="p">();</span>
</span><span class='line'>      <span class="p">}</span>
</span><span class='line'>      
</span><span class='line'>      <span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="nv">$userID</span><span class="p">){</span>
</span><span class='line'>          <span class="nv">$app</span> <span class="o">=</span> <span class="nx">Slim</span><span class="o">::</span><span class="na">getInstance</span><span class="p">();</span>
</span><span class='line'>          <span class="nv">$app</span><span class="o">-&gt;</span><span class="na">redirect</span><span class="p">(</span><span class="nv">$FB</span><span class="o">-&gt;</span><span class="na">getLoginUrl</span><span class="p">());</span>
</span><span class='line'>      <span class="p">}</span><span class="k">else</span><span class="p">{</span>
</span><span class='line'>          <span class="nv">$user</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Users</span><span class="p">;</span>
</span><span class='line'>          <span class="nv">$user</span><span class="o">-&gt;</span><span class="na">findOne</span><span class="p">(</span><span class="k">array</span><span class="p">(</span><span class="s1">&#39;userID&#39;</span> <span class="o">=&gt;</span> <span class="nv">$userID</span><span class="p">));</span>
</span><span class='line'>          <span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="nv">$user</span><span class="o">-&gt;</span><span class="na">valid</span><span class="p">()){</span>
</span><span class='line'>              <span class="nv">$user</span><span class="o">-&gt;</span><span class="na">userID</span> <span class="o">=</span> <span class="nv">$userID</span><span class="p">;</span>
</span><span class='line'>              <span class="nv">$user</span><span class="o">-&gt;</span><span class="na">save</span><span class="p">();</span>
</span><span class='line'>          <span class="p">}</span>
</span><span class='line'>          
</span><span class='line'>          <span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="nv">$fromUserID</span><span class="p">){</span>
</span><span class='line'>              <span class="nv">$app</span> <span class="o">=</span> <span class="nx">Slim</span><span class="o">::</span><span class="na">getInstance</span><span class="p">();</span>
</span><span class='line'>              <span class="nv">$app</span><span class="o">-&gt;</span><span class="na">view</span><span class="p">()</span><span class="o">-&gt;</span><span class="na">setData</span><span class="p">(</span><span class="s1">&#39;user&#39;</span><span class="p">,</span> <span class="nv">$user</span><span class="p">);</span>
</span><span class='line'>          <span class="p">}</span>
</span><span class='line'>          <span class="k">return</span> <span class="nv">$user</span><span class="p">;</span>
</span><span class='line'>      <span class="p">}</span>    
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>欄位很簡單，只有 會員編號、暱稱、類型 三個。而類型部分，因為並沒有安裝論壇的部份，需要手動操作資料庫去設定會員類型，該如何初始化，以及如何處理，就交給各位發揮創意摟！<del>某人超懶所以就變成這樣</del></p>

<p>接下來，會看到一個 static 的方法叫做 getUser() 這是用於取得使用者的方法。</p>

<blockquote><p>為什麼要用 static 方法呢？因為弦也認為這些方法都是直接產生一個實例傳回，而非改動物件設定值後一併傳回，所以決定以 static 的方法來做處理。</p></blockquote>

<p>這個 getUser 的方法也非常簡單，如果有指定 userID 那麼就跳過 Facebook 登入並且繼續執行，反之則進行 Facebook 登入，取得 Facebook 的使用者編號，並且查詢系統內使用者，如果無使用者，則新建一個。</p>

<p>最後，再將使用者物件傳回。</p>

<p>接下來是 Forums.php 這個檔案，我想是全部 Model 中最為複雜的部份，也是整個論壇最複雜的檔案。</p>

<figure class='code'><figcaption><span>app/models/Forums.php</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
<span class='line-number'>58</span>
<span class='line-number'>59</span>
<span class='line-number'>60</span>
<span class='line-number'>61</span>
<span class='line-number'>62</span>
<span class='line-number'>63</span>
<span class='line-number'>64</span>
<span class='line-number'>65</span>
<span class='line-number'>66</span>
<span class='line-number'>67</span>
<span class='line-number'>68</span>
<span class='line-number'>69</span>
<span class='line-number'>70</span>
<span class='line-number'>71</span>
<span class='line-number'>72</span>
<span class='line-number'>73</span>
<span class='line-number'>74</span>
<span class='line-number'>75</span>
<span class='line-number'>76</span>
<span class='line-number'>77</span>
<span class='line-number'>78</span>
<span class='line-number'>79</span>
<span class='line-number'>80</span>
<span class='line-number'>81</span>
<span class='line-number'>82</span>
<span class='line-number'>83</span>
<span class='line-number'>84</span>
<span class='line-number'>85</span>
<span class='line-number'>86</span>
<span class='line-number'>87</span>
<span class='line-number'>88</span>
<span class='line-number'>89</span>
<span class='line-number'>90</span>
<span class='line-number'>91</span>
<span class='line-number'>92</span>
<span class='line-number'>93</span>
<span class='line-number'>94</span>
<span class='line-number'>95</span>
<span class='line-number'>96</span>
<span class='line-number'>97</span>
<span class='line-number'>98</span>
<span class='line-number'>99</span>
<span class='line-number'>100</span>
<span class='line-number'>101</span>
<span class='line-number'>102</span>
<span class='line-number'>103</span>
<span class='line-number'>104</span>
<span class='line-number'>105</span>
<span class='line-number'>106</span>
<span class='line-number'>107</span>
<span class='line-number'>108</span>
<span class='line-number'>109</span>
<span class='line-number'>110</span>
<span class='line-number'>111</span>
<span class='line-number'>112</span>
<span class='line-number'>113</span>
<span class='line-number'>114</span>
<span class='line-number'>115</span>
<span class='line-number'>116</span>
<span class='line-number'>117</span>
<span class='line-number'>118</span>
<span class='line-number'>119</span>
<span class='line-number'>120</span>
<span class='line-number'>121</span>
<span class='line-number'>122</span>
<span class='line-number'>123</span>
<span class='line-number'>124</span>
<span class='line-number'>125</span>
<span class='line-number'>126</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="cp">&lt;?php</span>
</span><span class='line'><span class="sd">/**</span>
</span><span class='line'><span class="sd"> * Fourums</span>
</span><span class='line'><span class="sd"> * </span>
</span><span class='line'><span class="sd"> * @package 3day-forum</span>
</span><span class='line'><span class="sd"> * @author Aotoki</span>
</span><span class='line'><span class="sd"> * @version 1.0</span>
</span><span class='line'><span class="sd"> */</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nc">Forums</span> <span class="k">extends</span> <span class="nx">ActiveMongo</span>
</span><span class='line'><span class="p">{</span>
</span><span class='line'>  <span class="c1">//資料表欄位</span>
</span><span class='line'>  <span class="k">public</span> <span class="nv">$Name</span><span class="p">;</span> <span class="c1">//論壇名稱</span>
</span><span class='line'>  <span class="k">public</span> <span class="nv">$Parent</span><span class="p">;</span> <span class="c1">//父論壇</span>
</span><span class='line'>  
</span><span class='line'>  <span class="sd">/**</span>
</span><span class='line'><span class="sd">  * Get Forum</span>
</span><span class='line'><span class="sd">  * </span>
</span><span class='line'><span class="sd">  * @author Aotoki</span>
</span><span class='line'><span class="sd">  * @param string 論壇ID</span>
</span><span class='line'><span class="sd">  * @return object|bool</span>
</span><span class='line'><span class="sd">  */</span>
</span><span class='line'>  
</span><span class='line'>  <span class="k">static</span> <span class="k">public</span> <span class="k">function</span> <span class="nf">getForum</span><span class="p">(</span> <span class="nv">$ID</span><span class="p">,</span> <span class="nv">$forumArgs</span> <span class="o">=</span> <span class="k">array</span><span class="p">()</span> <span class="p">)</span>
</span><span class='line'>  <span class="p">{</span>
</span><span class='line'>      <span class="nv">$forum</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Forums</span><span class="p">;</span>
</span><span class='line'>      <span class="nv">$forum</span><span class="o">-&gt;</span><span class="na">findOne</span><span class="p">(</span><span class="k">new</span> <span class="nx">MongoId</span><span class="p">(</span><span class="nv">$ID</span><span class="p">));</span>
</span><span class='line'>      
</span><span class='line'>      <span class="nb">array_push</span><span class="p">(</span><span class="nv">$forumArgs</span><span class="p">,</span> <span class="nv">$forum</span><span class="p">);</span>
</span><span class='line'>      <span class="k">if</span><span class="p">(</span><span class="nb">isset</span><span class="p">(</span><span class="nv">$forum</span><span class="o">-&gt;</span><span class="na">Parent</span><span class="p">)){</span>
</span><span class='line'>          <span class="nv">$forumArgs</span> <span class="o">=</span> <span class="nx">self</span><span class="o">::</span><span class="na">getForum</span><span class="p">(</span><span class="nv">$forum</span><span class="o">-&gt;</span><span class="na">Parent</span><span class="p">,</span> <span class="nv">$forumArgs</span><span class="p">);</span>
</span><span class='line'>      <span class="p">}</span>
</span><span class='line'>      <span class="nb">sort</span><span class="p">(</span><span class="nv">$forumArgs</span><span class="p">,</span> <span class="nx">SORT_DESC</span><span class="p">);</span>
</span><span class='line'>      <span class="k">return</span> <span class="nv">$forumArgs</span><span class="p">;</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>  
</span><span class='line'>  <span class="sd">/**</span>
</span><span class='line'><span class="sd">  * Get Forums</span>
</span><span class='line'><span class="sd">  * </span>
</span><span class='line'><span class="sd">  * @author Aotoki</span>
</span><span class='line'><span class="sd">  * @param string 父論壇ID</span>
</span><span class='line'><span class="sd">  * @return object|bool 成功傳回 Forum 物件，失敗傳回 FALSE</span>
</span><span class='line'><span class="sd">  */</span>
</span><span class='line'>  
</span><span class='line'>  <span class="k">static</span> <span class="k">public</span> <span class="k">function</span> <span class="nf">getForums</span><span class="p">(</span> <span class="nv">$parentID</span> <span class="o">=</span> <span class="k">NULL</span><span class="p">)</span>
</span><span class='line'>  <span class="p">{</span>
</span><span class='line'>      <span class="nv">$forums</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Forums</span><span class="p">;</span>
</span><span class='line'>      <span class="nv">$forums</span><span class="o">-&gt;</span><span class="na">find</span><span class="p">(</span><span class="k">array</span><span class="p">(</span><span class="s1">&#39;Parent&#39;</span> <span class="o">=&gt;</span> <span class="nv">$parentID</span><span class="p">));</span>
</span><span class='line'>      
</span><span class='line'>      <span class="nv">$result</span> <span class="o">=</span> <span class="k">array</span><span class="p">();</span>
</span><span class='line'>      
</span><span class='line'>      <span class="k">foreach</span> <span class="p">(</span><span class="nv">$forums</span> <span class="k">as</span> <span class="nv">$ID</span> <span class="o">=&gt;</span> <span class="nv">$forum</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>          <span class="nv">$lastPost</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Thread</span><span class="p">;</span>
</span><span class='line'>          <span class="nv">$lastPost</span><span class="o">-&gt;</span><span class="na">sort</span><span class="p">(</span><span class="s1">&#39;timestamp DESC&#39;</span><span class="p">);</span>
</span><span class='line'>          <span class="nv">$lastPost</span><span class="o">-&gt;</span><span class="na">where</span><span class="p">(</span><span class="s1">&#39;forumID&#39;</span><span class="p">,(</span><span class="nx">string</span><span class="p">)</span> <span class="nv">$forum</span><span class="o">-&gt;</span><span class="na">getID</span><span class="p">());</span>
</span><span class='line'>          <span class="nv">$lastPost</span><span class="o">-&gt;</span><span class="na">limit</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
</span><span class='line'>          
</span><span class='line'>          <span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="nv">$lastPost</span><span class="o">-&gt;</span><span class="na">valid</span><span class="p">()){</span>
</span><span class='line'>              <span class="nv">$lastPost</span> <span class="o">=</span> <span class="k">array</span><span class="p">();</span>
</span><span class='line'>          <span class="p">}</span><span class="k">else</span><span class="p">{</span>
</span><span class='line'>              <span class="nv">$lastPost</span> <span class="o">=</span> <span class="nv">$lastPost</span><span class="o">-&gt;</span><span class="na">getArray</span><span class="p">();</span>
</span><span class='line'>          <span class="p">}</span>
</span><span class='line'>          
</span><span class='line'>          <span class="nv">$result</span><span class="p">[]</span> <span class="o">=</span> <span class="k">array</span><span class="p">(</span>
</span><span class='line'>              <span class="s1">&#39;forum&#39;</span> <span class="o">=&gt;</span> <span class="nv">$forum</span><span class="o">-&gt;</span><span class="na">getArray</span><span class="p">(),</span>
</span><span class='line'>              <span class="s1">&#39;lastPost&#39;</span> <span class="o">=&gt;</span> <span class="nv">$lastPost</span><span class="p">,</span>
</span><span class='line'>          <span class="p">);</span>
</span><span class='line'>          
</span><span class='line'>          <span class="nb">unset</span><span class="p">(</span><span class="nv">$lastPost</span><span class="p">);</span>
</span><span class='line'>      <span class="p">}</span>
</span><span class='line'>      
</span><span class='line'>      <span class="k">return</span> <span class="nv">$result</span><span class="p">;</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>  
</span><span class='line'>  <span class="sd">/**</span>
</span><span class='line'><span class="sd">  * Create Forum</span>
</span><span class='line'><span class="sd">  * </span>
</span><span class='line'><span class="sd">  * @author Aotoki</span>
</span><span class='line'><span class="sd">  * @param string 論壇名稱</span>
</span><span class='line'><span class="sd">  */</span>
</span><span class='line'>  
</span><span class='line'>  <span class="k">static</span> <span class="k">public</span> <span class="k">function</span> <span class="nf">createForum</span><span class="p">(</span><span class="nv">$Name</span><span class="p">,</span> <span class="nv">$Parent</span> <span class="o">=</span> <span class="k">NULL</span><span class="p">)</span>
</span><span class='line'>  <span class="p">{</span>
</span><span class='line'>      <span class="nv">$forum</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Forums</span><span class="p">;</span>
</span><span class='line'>      <span class="nv">$forum</span><span class="o">-&gt;</span><span class="na">Name</span> <span class="o">=</span> <span class="nv">$Name</span><span class="p">;</span>
</span><span class='line'>      <span class="k">if</span><span class="p">(</span><span class="nv">$Parent</span><span class="p">){</span>
</span><span class='line'>          <span class="nv">$forum</span><span class="o">-&gt;</span><span class="na">Parent</span> <span class="o">=</span> <span class="nv">$Parent</span><span class="p">;</span>
</span><span class='line'>      <span class="p">}</span>
</span><span class='line'>      <span class="nv">$forum</span><span class="o">-&gt;</span><span class="na">save</span><span class="p">();</span>
</span><span class='line'>      <span class="nb">unset</span><span class="p">(</span><span class="nv">$forum</span><span class="p">);</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>  
</span><span class='line'>  <span class="sd">/**</span>
</span><span class='line'><span class="sd">  * Delete Forum</span>
</span><span class='line'><span class="sd">  * </span>
</span><span class='line'><span class="sd">  * @author Aotoki</span>
</span><span class='line'><span class="sd">  * @param string 論壇ID</span>
</span><span class='line'><span class="sd">  */</span>
</span><span class='line'>  
</span><span class='line'>  <span class="k">static</span> <span class="k">public</span> <span class="k">function</span> <span class="nf">deleteForum</span><span class="p">(</span><span class="nv">$forumID</span><span class="p">)</span>
</span><span class='line'>  <span class="p">{</span>
</span><span class='line'>      
</span><span class='line'>      <span class="nv">$parentID</span> <span class="o">=</span> <span class="k">NULL</span><span class="p">;</span>
</span><span class='line'>      
</span><span class='line'>      <span class="nv">$forum</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Forums</span><span class="p">;</span>
</span><span class='line'>      <span class="nv">$forum</span><span class="o">-&gt;</span><span class="na">findOne</span><span class="p">(</span><span class="k">new</span> <span class="nx">MongoId</span><span class="p">(</span><span class="nv">$forumID</span><span class="p">));</span>
</span><span class='line'>      <span class="k">if</span><span class="p">(</span><span class="nb">isset</span><span class="p">(</span><span class="nv">$forum</span><span class="o">-&gt;</span><span class="na">Parent</span><span class="p">)){</span>
</span><span class='line'>          <span class="nv">$parentID</span> <span class="o">=</span> <span class="nv">$forum</span><span class="o">-&gt;</span><span class="na">Parent</span><span class="p">;</span>
</span><span class='line'>      <span class="p">}</span>
</span><span class='line'>      <span class="nv">$forum</span><span class="o">-&gt;</span><span class="na">delete</span><span class="p">();</span>
</span><span class='line'>      
</span><span class='line'>      <span class="nv">$subForums</span> <span class="o">=</span> <span class="nx">self</span><span class="o">::</span><span class="na">getForums</span><span class="p">(</span><span class="nv">$forumID</span><span class="p">);</span>
</span><span class='line'>      <span class="k">foreach</span><span class="p">(</span><span class="nv">$subForums</span> <span class="k">as</span> <span class="nv">$ID</span> <span class="o">=&gt;</span> <span class="nv">$forum</span><span class="p">){</span>
</span><span class='line'>          <span class="nx">self</span><span class="o">::</span><span class="na">deleteForum</span><span class="p">(</span><span class="nv">$ID</span><span class="p">);</span>
</span><span class='line'>      <span class="p">}</span>
</span><span class='line'>      
</span><span class='line'>      <span class="nv">$topics</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Thread</span><span class="p">;</span>
</span><span class='line'>      <span class="nv">$topics</span><span class="o">-&gt;</span><span class="na">find</span><span class="p">(</span><span class="k">array</span><span class="p">(</span><span class="s1">&#39;forumID&#39;</span> <span class="o">=&gt;</span> <span class="nv">$forumID</span><span class="p">));</span>
</span><span class='line'>      <span class="k">foreach</span><span class="p">(</span><span class="nv">$topics</span> <span class="k">as</span> <span class="nv">$ID</span> <span class="o">=&gt;</span> <span class="nv">$topic</span><span class="p">){</span>
</span><span class='line'>          <span class="nx">Thread</span><span class="o">::</span><span class="na">deleteTopic</span><span class="p">(</span><span class="nv">$ID</span><span class="p">);</span>
</span><span class='line'>      <span class="p">}</span>
</span><span class='line'>      
</span><span class='line'>      <span class="k">return</span> <span class="nv">$parentID</span><span class="p">;</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>  
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>欄位非常簡單，就只有 Name 以及 Parent 兩個值。代表的意義就是 討論版 的名字，以及其父討論版的 ID (如果沒有父討論版則是 NULL)</p>

<p>接下來，就是本次最複雜的部分，論壇的各個方法。選用 static 的理由已經說明了，因此先從 getForum() 開始介紹起。</p>

<h4>getForum</h4>

<p>從原始碼可以得知，這是一個遞迴函式，每當所在論壇層級越低，遞迴次數就會越多（不斷的追溯父論壇）</p>

<p>首先，我們要先找出目前論壇，與 MySQL 這類關聯式資料庫不同，在 MongoDB 下沒有可以自動遞增的欄位屬性，所以我們只好借用每個物件都會存在的 _id 欄位，來當做識別標準。</p>

<blockquote><p>在 MongoDB 內儲存的是名為 ObjectId 物件的格式，無法直接以字串方式查詢，但是 ActiveMongo 也沒有自動轉換的方式，所以我們使用 Mongo 的 PHP Driver 內建的 MongoId 物件來轉換（不過直接輸出他，是會自動轉換回字串格式的）因為操作中有兩種查詢方式（字串跟物件）希望大家不會搞混。</p></blockquote>

<p>找到論壇後，則塞入 $forumArgs 變數，並且檢查是否有父論壇，如果有，那麼就繼續遞迴，反之則傳回整理好的 $forumArgs 函式。</p>

<blockquote><p>傳回前做 sort(排序) 處理的原因主要是因為 FIFO (First Input First Output) 會讓原本是最低層級的論壇出現在第一個，違反常理，應該是要 Parent > Child 才會正確，所以才這樣處理。</p></blockquote>

<p>說實在的，把這個函式叫做 getForumTree() 搞不好會比較貼切。</p>

<h4>getForums</h4>

<p>接著，是 getForums 這個方法。邏輯上就比起前面的還簡單多了！</p>

<p>假設沒有 Parent 的傳入，那麼就單純查詢論壇（無 Parent 的論壇，也就是最頂層的論壇）假設有，則查詢 Parent 與之相符的論壇。</p>

<blockquote><p>這邊的 Parent 因為在儲存時已經以 string(字串) 方式儲存，所以不需要用 MongoId 物件來轉換成 ObjectId</p></blockquote>

<p>實際上，其實只要這樣就足夠了！不過我們還希望得知這個討論版最後一次有新文章是什麼時候，所以決定對 Thread 查詢。</p>

<blockquote><p>後面會提到 Thread 這個 Model 我們用來儲存每篇主題與討論版的關聯性，以及這篇主題是什麼時候被建立的。</p></blockquote>

<p>因為不單純只有一個討論版，所以放入迴圈，依序取出每個討論版後，在做查詢。首先，我們先用 sort 這個方法指定依照時間排序，接著用 where 方法找出在該討論版的主題，最後用 limit 限制只傳回一筆資料。</p>

<blockquote><p>扣除 sort 方法，其實可以直接用 findOne() 方法，但是我們需要排序，所以改用這樣的方式查詢（也許我們可以用關聯式的查詢，不過弦也對這部份操作還不清楚，所以土法煉鋼一下～）</p></blockquote>

<p>接著，我們將其放入 $result 陣列中，傳回。</p>

<blockquote><p>$result[] = array() 是讓陣列自動產生 Key 和 array_psuh() 類似，而為什麼要對 $forum 進行 getArray() 指令產出陣列呢？這是因為弦也開發時發現如果直接傳入物件，取出時會變回空的 Forums 物件而非一個指定某個討論版的物件，為了保持資料，所以就這樣做處理。</p></blockquote>

<h4>createForum</h4>

<p>這個方法相較之下，就筆其他簡單許多。</p>

<p>僅是單純的建立一個 Forums 物件，並且將 Name 以及 Parent 存入而已。最後的 unset() 動作是釋放記憶體，雖然函式呼叫完應該也會自動釋放，不過還是手動釋放避免該擾吧！</p>

<blockquote><p>其實 getForums 的迴圈釋放 $lastPost 用意也一樣，但是這個動作可以確保下次迴圈運行時不會不小心用到上一筆資料。</p></blockquote>

<h4>deleteForum</h4>

<p>終於，我們到了最後一個方法，這個方法可以視為 getForum 跟 getForums 混合後的修改版。</p>

<p>首先找出應該刪除的討論版，並且加以刪除（順便記錄其父討論版）
接著找出子討論版，並且刪除（使用遞迴方式，確保子討論版下的子討論版也都會被刪除）</p>

<p>接著刪除討論版下的所有主題（這邊使用 Thread 的 deleteTopic 方法，是為了一併刪除相關的文章）
最後傳回父論壇的 ID 以方便重新定向時可以轉跳到其父討論版，而不會跳回首頁。</p>

<h3>總結</h3>

<hr />

<p>我想一次吸收這麼多資訊應該很難消化，所以先在這邊做一個段落。<br />
（不是因為我想偷懶喔，因為之後的 Thread Model 也有不少於 Forums Model 的方法要解釋）</p>

<p>下一篇文章除了將剩下的 Model 解釋完之外，還會繼續解說其餘的 Web App 部分。</p>

<ul>
<li>Github 原始碼：<a href="https://github.com/elct9620/3Day-Forum/zipball/1.0">https://github.com/elct9620/3Day-Forum/zipball/1.0</a></li>
<li>線上範例 ：<a href="http://the-3day-forum.herokuapp.com/">http://the-3day-forum.herokuapp.com/</a></li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[我的第一個 Backbone.js - TODO List (無儲存功能)]]></title>
    <link href="http://revo-skill.frost.tw/blog/2012/01/08/my-first-backbonejs-the-todo-list-without-store/"/>
    <updated>2012-01-08T21:49:00+08:00</updated>
    <id>http://revo-skill.frost.tw/blog/2012/01/08/my-first-backbonejs-the-todo-list-without-store</id>
    <content type="html"><![CDATA[<h3><del>湊字數的</del> 前言</h3>

<hr />

<p>盧了好久，終於開始實做 Backbone.js 拉！之前聽演講時知道這很威，但是實做成功之後就深刻體會，這東西超威的！！（果然是要湊字數）</p>

<p>因為是做個紀錄，所以我就不浪費時間從啥建立目錄什麼的去做摟～<br />
（如果你很懶，可以從文章最後的 Github 裡面的 Develop Branch 下載我做好的基礎結構）</p>

<!-- more -->


<h3>建立 Model</h3>

<hr />

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">var</span> <span class="nx">TODO</span> <span class="o">=</span> <span class="nx">Backbone</span><span class="p">.</span><span class="nx">Model</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
</span><span class='line'>  
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>好！就這樣結束！！<br />
（太精簡了吧？）</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">var</span> <span class="nx">TODO</span> <span class="o">=</span> <span class="nx">Backbone</span><span class="p">.</span><span class="nx">Model</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
</span><span class='line'>  <span class="nx">defaults</span><span class="o">:</span> <span class="p">{</span><span class="nx">data</span> <span class="o">:</span> <span class="s1">&#39;因為有人忘記輸入，所以我就自動出現了！&#39;</span><span class="p">}</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>這樣總行了吧？其實 Model 在目前情況有點類似規劃資料表格，不過因為我啥都不需要，所以就啥都沒用拉！</p>

<h3>建立 Collection</h3>

<hr />

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">var</span> <span class="nx">TODOCollection</span> <span class="o">=</span> <span class="nx">Backbone</span><span class="p">.</span><span class="nx">Collection</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
</span><span class='line'>  <span class="nx">model</span> <span class="o">:</span> <span class="nx">TODO</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>完畢！<br />
因為目前也沒有要對 Collection 做什麼事，所以也就先這樣摟！</p>

<h3>建立 View ( App )</h3>

<p>這次會建立兩個 View 原因嘛，其實只是弦也看著官方文件不小心弄成這樣的（羞 (>///&lt;) <br />
不過話說回來，把整個頁面都用一個 View 捕捉起來其實會比較好（弦也腦補理論）因為可以透過 Backbone 捕捉各種使用者操作事件，比起用 jQuery 一個一個抓，還不如用 Backbone 件一個 events 來列出全部事件還方便～</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">var</span> <span class="nx">AppView</span> <span class="o">=</span> <span class="nx">Backbone</span><span class="p">.</span><span class="nx">View</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
</span><span class='line'>  <span class="nx">el</span> <span class="o">:</span> <span class="nx">$</span><span class="p">(</span><span class="s1">&#39;#app&#39;</span><span class="p">),</span> <span class="c1">//搭配的是 jQuery 所以用 jQuery 選擇器選取</span>
</span><span class='line'>  <span class="nx">events</span> <span class="o">:</span> <span class="p">{</span>
</span><span class='line'>      <span class="s1">&#39;click #add-todo&#39;</span> <span class="o">:</span> <span class="s1">&#39;add&#39;</span><span class="p">,</span> <span class="c1">//就這樣 click 事件，對 id=&quot;add-todo&quot; 這個元素發生反應</span>
</span><span class='line'>  <span class="p">},</span>
</span><span class='line'>  <span class="nx">add</span> <span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">e</span><span class="p">){</span>
</span><span class='line'>      <span class="kd">var</span> <span class="nx">input</span> <span class="o">=</span> <span class="nx">$</span><span class="p">(</span><span class="s1">&#39;input[name=todo]&#39;</span><span class="p">);</span>
</span><span class='line'>      <span class="nx">TODOList</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="k">new</span> <span class="nx">TODO</span><span class="p">({</span><span class="nx">data</span> <span class="o">:</span> <span class="nx">input</span><span class="p">.</span><span class="nx">val</span><span class="p">()}));</span> <span class="c1">//後面做解釋</span>
</span><span class='line'>      <span class="kd">var</span> <span class="nx">input</span><span class="p">.</span><span class="nx">val</span><span class="p">(</span><span class="s1">&#39;&#39;</span><span class="p">);</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>好！這樣所謂的 App View 就完成拉！<br />
首先是設定 el 來指定對應的 元素 （這邊選取的是 #app）<br />
接著設定 events 列出全部要偵測的事件<br />
最後把事件發生對應的函式設定進去（這邊加入 add 事件對應函式）</p>

<blockquote><p>TODOList 最後會提到，這是 TODOCollection 的實做。</p></blockquote>

<h3>建立 View (TODOView)</h3>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">var</span> <span class="nx">TODOView</span> <span class="o">=</span> <span class="nx">Backbone</span><span class="p">.</span><span class="nx">View</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
</span><span class='line'>  <span class="nx">tagName</span> <span class="o">:</span> <span class="s1">&#39;div&#39;</span><span class="p">,</span>
</span><span class='line'>  <span class="nx">className</span> <span class="o">:</span> <span class="s1">&#39;alert-message block-message info&#39;</span><span class="p">,</span> <span class="c1">//Bootstarp 的 Class Name 直接套用 Bootstrap 的 UI</span>
</span><span class='line'>  <span class="nx">render</span> <span class="o">:</span> <span class="kd">function</span><span class="p">(){</span>
</span><span class='line'>      <span class="nx">$</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">el</span><span class="p">).</span><span class="nx">html</span><span class="p">(</span><span class="s1">&#39;&lt;a href=&quot;#&quot; class=&quot;remove&quot;&gt;×&lt;/a&gt;&lt;p&gt;&#39;</span> <span class="o">+</span> <span class="k">this</span><span class="p">.</span><span class="nx">model</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;data&#39;</span><span class="p">)</span> <span class="o">+</span> <span class="s1">&#39;&lt;/p&gt;&#39;</span><span class="p">);</span>
</span><span class='line'>      <span class="k">return</span> <span class="k">this</span><span class="p">;</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>  <span class="nx">events</span> <span class="o">:</span> <span class="p">{</span>
</span><span class='line'>      <span class="s1">&#39;click remove&#39;</span> <span class="o">:</span> <span class="s1">&#39;remove&#39;</span><span class="p">,</span>
</span><span class='line'>  <span class="p">},</span>
</span><span class='line'>  <span class="nx">initialize</span> <span class="o">:</span> <span class="kd">function</span><span class="p">(){</span>
</span><span class='line'>      <span class="k">this</span><span class="p">.</span><span class="nx">model</span><span class="p">.</span><span class="nx">bind</span><span class="p">(</span><span class="s1">&#39;destroy&#39;</span><span class="p">,</span> <span class="k">this</span><span class="p">.</span><span class="nx">destroy</span><span class="p">,</span> <span class="k">this</span><span class="p">);</span>
</span><span class='line'>  <span class="p">},</span>
</span><span class='line'>  <span class="nx">remove</span> <span class="o">:</span> <span class="kd">function</span><span class="p">(){</span>
</span><span class='line'>      <span class="k">this</span><span class="p">.</span><span class="nx">model</span><span class="p">.</span><span class="nx">destroy</span><span class="p">();</span>
</span><span class='line'>  <span class="p">},</span>
</span><span class='line'>  <span class="nx">destroy</span> <span class="o">:</span> <span class="kd">function</span><span class="p">(){</span>
</span><span class='line'>      <span class="nx">$</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">el</span><span class="p">).</span><span class="nx">remove</span><span class="p">();</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>因為這次不是作為一個 View 使用，而是要被多次使用，所以沒有設定 el 去指定特定的元素。<br />
而是另外設定了 tagName 來決定被產生實例時該用什麼 tagName 來呈現（className 用法類似，可以多個）</p>

<p>在這之中 this.model 是產生 View 時一起傳入的屬性。<br />
同時在這個 View 初始化時，也一併監聽（Bind） Model 的情況，如果被 Destroy 則呼叫函式（destroy）不過這邊指定函式時不能單純用字串，這樣會找不到，要特別指定 this.destory 表示是這一個 View 物件裡面的 destroy （因為 this.model 是外部傳入的 TODO Model 而不是 View 內部的屬性）</p>

<h3>建立必須物件</h3>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">var</span> <span class="nx">App</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">ViewApp</span><span class="p">;</span>
</span><span class='line'><span class="kd">var</span> <span class="nx">TODOList</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">TODOCollection</span><span class="p">;</span>
</span><span class='line'><span class="nx">TODOList</span><span class="p">.</span><span class="nx">bind</span><span class="p">(</span><span class="s1">&#39;add&#39;</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">Model</span><span class="p">){</span>
</span><span class='line'>  <span class="kd">var</span> <span class="nx">view</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">TODOView</span><span class="p">({</span><span class="nx">model</span> <span class="o">:</span> <span class="nx">Model</span><span class="p">});</span>
</span><span class='line'>  <span class="nx">$</span><span class="p">(</span><span class="s1">&#39;#todo-list&#39;</span><span class="p">).</span><span class="nx">append</span><span class="p">(</span><span class="nx">view</span><span class="p">.</span><span class="nx">render</span><span class="p">().</span><span class="nx">el</span><span class="p">);</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>最後就是把全域的 ViewApp 產生實例，還有前面提到的 TODOList 也一起產生出來。<br />
然後再給 TODOList 新增監聽事件，檢查是否有新的 Model 被加進去，如果有的話，則產生新的 TODOView 加到 #todo-list 裡面，讓他顯示。</p>

<h3>總結</h3>

<hr />

<p>好吧！其實這篇文章根本沒寫到什麼重點阿！！</p>

<p>Github 網址 ： <a href="https://github.com/elct9620/Aotoki-Backbone.js">https://github.com/elct9620/Aotoki-Backbone.js</a></p>

<p>其實我放在上面的也沒有跟文章完全一樣，不過實做結果倒是一樣。<br />
不過別像弦也忘記把 JavaScript 都 Load 完喔！至少要有 Underscore.js + jQuery + Backbone.js 才能運作。</p>

<p>下一次要挑戰 PHP 後端 + Backbone.js 的資料庫存取了！<br />
（然後還要更加搞清楚運作模式，這篇文章還沒有說夠詳細，因為有一些我也還不是很確定！）</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[三十分鐘做一個留言板 Part 2]]></title>
    <link href="http://revo-skill.frost.tw/blog/2012/01/03/create-a-guestbook-in-30-minutes-part-2/"/>
    <updated>2012-01-03T18:31:00+08:00</updated>
    <id>http://revo-skill.frost.tw/blog/2012/01/03/create-a-guestbook-in-30-minutes-part-2</id>
    <content type="html"><![CDATA[<h3>前言（<del>廢話</del>）</h3>

<hr />

<p>又到了快樂的 Part 2 摟！（<del>相隔時間可能只有幾小時而已</del>）這樣馬拉松寫文章還真是刺激，不過各位不用跟我一樣馬拉松式的把他做完阿！！</p>

<!-- more -->


<h3>建立模型（Model）</h3>

<hr />

<p>基本上，就是產生一個物件，讓自己方便做一些特殊（？）的操作就是了！不過在 ActiveMongo 其實也就是先去定義一下有哪些欄位，然後就結束了！（當然，還有很多很神奇的技巧，不過還是先別探討了！）</p>

<p>首先，在 app/models 資料夾新增一個 Commetn.php 檔案，然後建立一個 Model</p>

<figure class='code'><figcaption><span>Comment.php</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="cp">&lt;?php</span>
</span><span class='line'><span class="sd">/**</span>
</span><span class='line'><span class="sd"> * Comment Model</span>
</span><span class='line'><span class="sd"> * </span>
</span><span class='line'><span class="sd"> * @author Aotoki</span>
</span><span class='line'><span class="sd"> * @version 1.0</span>
</span><span class='line'><span class="sd"> */</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nc">Comment</span> <span class="k">extends</span> <span class="nx">ActiveMongo</span>
</span><span class='line'><span class="p">{</span>
</span><span class='line'>  <span class="k">public</span> <span class="nv">$nickname</span> <span class="o">=</span> <span class="s1">&#39;Unknow&#39;</span><span class="p">;</span>
</span><span class='line'>  <span class="k">public</span> <span class="nv">$content</span><span class="p">;</span>
</span><span class='line'>  <span class="k">public</span> <span class="nv">$timestamp</span><span class="p">;</span>    
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>沒錯，不要懷疑，就只有這樣！<br />
在 Active Mongo 建立一個Model只要繼承 ActiveMongo 這個物件，接著將欄位設定上去即可。<br />
因為目前留言板只需要紀錄 暱稱（Nickname） 以及 留言內容（Content） 和 時間（Timestamp） 即可，而且還不需要其他多餘的功能，因此保持這個狀態就完成 Model 了！</p>

<h3>讀取留言（簡易）</h3>

<hr />

<p>我們回到 index.php 檔案，在連接資料庫的語法下方（上一篇文章提到的 ActiveMongo::connect() 區段下方），加入讀取 Model 的程式。</p>

<figure class='code'><figcaption><span>index.php</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="x">//載入 Model</span>
</span><span class='line'><span class="x">require_once(ABSPATH . &#39;models/Comment.php&#39;);</span>
</span></code></pre></td></tr></table></div></figure>


<p>位置會在第一個 $app->get(); 之前，因為我們必須先把 Model 引入，不然是無法使用這個 Model 的。</p>

<p>接著，我們編輯上一篇文章 $app->get(); 的部份，大致上改成這樣。</p>

<figure class='code'><figcaption><span>index.php</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="x">$app-&gt;get(&#39;/&#39;, function() use ($app){</span>
</span><span class='line'><span class="x">  $comments = new Comment(); //產生模型實例</span>
</span><span class='line'><span class="x">  $totalComments = $comments-&gt;count(); //取得留言總數</span>
</span><span class='line'><span class="x">  $comments-&gt;reset(); //清除指標，避免影響結果</span>
</span><span class='line'>
</span><span class='line'><span class="x">  $app-&gt;render(&#39;home.php&#39;, </span>
</span><span class='line'><span class="x">      array(</span>
</span><span class='line'><span class="x">          &#39;comments&#39; =&gt; $comments,</span>
</span><span class='line'><span class="x">          &#39;totalComments&#39; =&gt; $totalComments,</span>
</span><span class='line'><span class="x">      )</span>
</span><span class='line'><span class="x">  );</span>
</span><span class='line'><span class="x">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>剛剛，我們新增了一個 Comment 物件，因為 Active Mongo 會自動幫我們處理好一開始的查詢，所以我們只要直接讀取 $comments 就可以得知所有的留言了！<br />
為了要讓我們的佈景檔（home.php）得知 $comments 這筆資料，我們使用 Slim Framework 的 render 方法的第二個參數，將 $comments 以 comments 這個識別名稱傳給 home.php 讓他可以使用。</p>

<p>現在，編輯 views/home.php 加入迴圈（Loop）將留言顯示出來（當然，目前還沒有任何留言，不會顯示任何東西）</p>

<figure class='code'><figcaption><span>home.php</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="cp">&lt;!DOCTYPE html&gt;</span>
</span><span class='line'><span class="nt">&lt;html</span> <span class="na">lang=</span><span class="s">&quot;zh-tw&quot;</span><span class="nt">&gt;</span>
</span><span class='line'><span class="nt">&lt;head&gt;</span>
</span><span class='line'>  <span class="nt">&lt;meta</span> <span class="na">charset=</span><span class="s">&quot;utf-8&quot;</span> <span class="nt">/&gt;</span>
</span><span class='line'>
</span><span class='line'>  <span class="nt">&lt;meta</span> <span class="na">http-equiv=</span><span class="s">&quot;X-UA-Compatible&quot;</span> <span class="na">content=</span><span class="s">&quot;IE=edge,chrome=1&quot;</span> <span class="nt">/&gt;</span>
</span><span class='line'>
</span><span class='line'>  <span class="nt">&lt;title&gt;</span>My 30min Guest Book<span class="nt">&lt;/title&gt;</span>
</span><span class='line'>  <span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">&quot;description&quot;</span> <span class="na">content=</span><span class="s">&quot;&quot;</span> <span class="nt">/&gt;</span>
</span><span class='line'>  <span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">&quot;author&quot;</span> <span class="na">content=</span><span class="s">&quot;Aotoki&quot;</span> <span class="nt">/&gt;</span>
</span><span class='line'>
</span><span class='line'>  <span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">&quot;viewport&quot;</span> <span class="na">content=</span><span class="s">&quot;width=device-width; initial-scale=1.0&quot;</span> <span class="nt">/&gt;</span>
</span><span class='line'>  <span class="nt">&lt;link</span> <span class="na">rel=</span><span class="s">&quot;stylesheet&quot;</span> <span class="na">href=</span><span class="s">&quot;http://twitter.github.com/bootstrap/1.4.0/bootstrap.min.css&quot;</span> <span class="nt">/&gt;</span>
</span><span class='line'>  <span class="nt">&lt;style&gt;</span>
</span><span class='line'>      <span class="nc">.container</span><span class="p">{</span>
</span><span class='line'>          <span class="k">margin</span><span class="o">:</span><span class="m">15px</span> <span class="k">auto</span><span class="p">;</span>
</span><span class='line'>      <span class="p">}</span>
</span><span class='line'>      
</span><span class='line'>      <span class="nc">.comment-count</span><span class="p">{</span>
</span><span class='line'>          <span class="k">margin-bottom</span><span class="o">:</span> <span class="m">10px</span><span class="p">;</span>
</span><span class='line'>      <span class="p">}</span>
</span><span class='line'>      
</span><span class='line'>  <span class="nt">&lt;/style&gt;</span>
</span><span class='line'><span class="nt">&lt;/head&gt;</span>
</span><span class='line'>
</span><span class='line'><span class="nt">&lt;body&gt;</span>
</span><span class='line'>  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;container&quot;</span><span class="nt">&gt;</span>
</span><span class='line'>      <span class="nt">&lt;header&gt;</span>
</span><span class='line'>          <span class="nt">&lt;h1&gt;</span>Guest Book<span class="nt">&lt;/h1&gt;</span>
</span><span class='line'>      <span class="nt">&lt;/header&gt;</span>
</span><span class='line'>      <span class="nt">&lt;nav&gt;</span>
</span><span class='line'>          <span class="c">&lt;!--- 選單 --&gt;</span>
</span><span class='line'>      <span class="nt">&lt;/nav&gt;</span>
</span><span class='line'>
</span><span class='line'>      <span class="nt">&lt;div&gt;</span>
</span><span class='line'>          <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;comment-count&quot;</span><span class="nt">&gt;</span>
</span><span class='line'>              <span class="nt">&lt;span</span> <span class="na">class=</span><span class="s">&quot;label notice&quot;</span><span class="nt">&gt;</span>Notice<span class="nt">&lt;/span&gt;</span>
</span><span class='line'>              System has <span class="cp">&lt;?php echo intval($totalComments); ?&gt;</span> comments.
</span><span class='line'>          <span class="nt">&lt;/div&gt;</span>
</span><span class='line'>          <span class="cp">&lt;?php foreach($comments as $c){ ?&gt;</span>
</span><span class='line'>          <span class="nt">&lt;blockquote&gt;</span>
</span><span class='line'>              <span class="nt">&lt;p&gt;</span><span class="cp">&lt;?php echo $c-&gt;content; ?&gt;</span><span class="nt">&lt;/p&gt;</span> <span class="c">&lt;!-- 顯示留言內容 --&gt;</span>
</span><span class='line'>              <span class="nt">&lt;small&gt;</span><span class="cp">&lt;?php echo $c-&gt;nickname; ?&gt;</span>, <span class="cp">&lt;?php echo date(&#39;Y-m-d H:i:s&#39;, $c-&gt;timestamp); ?&gt;</span><span class="nt">&lt;/small&gt;</span> <span class="c">&lt;!-- 顯示暱稱以及輸出留言時間 --&gt;</span>
</span><span class='line'>          <span class="nt">&lt;/blockquote&gt;</span>
</span><span class='line'>          <span class="cp">&lt;?php } ?&gt;</span>
</span><span class='line'>      <span class="nt">&lt;/div&gt;</span>
</span><span class='line'>
</span><span class='line'>      <span class="nt">&lt;footer&gt;</span>
</span><span class='line'>       <span class="nt">&lt;p&gt;</span><span class="ni">&amp;copy;</span> Copyright by Aotoki<span class="nt">&lt;/p&gt;</span>
</span><span class='line'>      <span class="nt">&lt;/footer&gt;</span>
</span><span class='line'>  <span class="nt">&lt;/div&gt;</span>
</span><span class='line'><span class="nt">&lt;/body&gt;</span>
</span><span class='line'><span class="nt">&lt;/html&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<p>因為有了初步的畫面顯示，所以就直接將 Bootstrap 的 CSS 用 Link 的方式直接導入（官方網站上的快速引用）這樣一來，原本單調的畫面也稍微變得豐富一點，目前可以看到畫面上顯示著之前設定的 Guest Book 標題以及 [Notice] System has 0 comments. 的字樣。</p>

<h3>新增留言</h3>

<hr />

<p>既然輸出留言完成了，但是無法留言還是沒有辦法讓留言板發揮作用，所以打開 index.php 檔案，繼續編輯。</p>

<p>我們將位置移動到 $app->get(&#8216;/&#8217;, function() use ($app){}); 區塊的下方，加入新的區塊。</p>

<figure class='code'><figcaption><span>index.php</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="x">$app-&gt;post(&#39;/new&#39;, function() use ($app){</span>
</span><span class='line'><span class="x">  //Save Comment</span>
</span><span class='line'><span class="x">  $comment = new Comment;</span>
</span><span class='line'><span class="x">  $comment-&gt;nickname = $app-&gt;request()-&gt;post(&#39;nickname&#39;);</span>
</span><span class='line'><span class="x">  $comment-&gt;content = $app-&gt;request()-&gt;post(&#39;content&#39;);</span>
</span><span class='line'><span class="x">  $comment-&gt;timestamp = time();</span>
</span><span class='line'><span class="x">  $comment-&gt;save();</span>
</span><span class='line'><span class="x">  </span>
</span><span class='line'><span class="x">  $app-&gt;redirect($app-&gt;urlFor(&#39;home&#39;));</span>
</span><span class='line'><span class="x">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>咦，怎麼跟之前讀取的有點像，但是這次？<br />
沒錯，起始的動作還是一樣建立一個 Model 接著，我們設定 $comment->nickname 為 $app->requrest()->post(&#8216;nickname&#8217;); 來讀取暱稱。<br />
不過，大家一定有疑問，是怎麼讀取呢？ $app->requrest(); 會負責處理有關 HTTP 請求得部份，而留言都會以 POST 方式傳輸資料，所以就要以 $app->requrest()->post(&#8216;資料名稱&#8217;); 來接收。<br />
那麼為什麼 timestamp 不用接收呢？那是因為時間總不能由使用者自己決定，所以由我們產生（time() 會給出一組秒數，是從 1970 年 1 月 1 日到今天的秒數。）</p>

<p>不過還是會有人對於 $app->post() 和 $app->get() 的差異有所疑惑吧！對，這個差異就在於 $app->post() 只接受 POST 傳輸資料，所以直接打開 http://網址/new 是會出現找不到頁面的喔！（這也是 Slim Framework的特性，在之後的文章會簡單介紹。）</p>

<p>好，現在已經完成儲存留言的機制了！但是打開網頁卻出現了錯誤？</p>

<p>其實是 $app->redirect() （轉跳網頁）裡面的數值 $app->urlFor() 有問題！
使用 urlFor 這個方法前，得先將目標命名才行，所以我們回到 $app->get(&#8216;/&#8217;, function() use ($app) {}) 區段 稍微修改結尾部份。</p>

<figure class='code'><figcaption><span>index.php</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="x">$app-&gt;get(&#39;/&#39;, function() use ($app){</span>
</span><span class='line'><span class="x">  //略</span>
</span><span class='line'><span class="x">})-&gt;name(&#39;home&#39;);</span>
</span></code></pre></td></tr></table></div></figure>


<p>這樣一來，就可以正常使用摟！而使用 urlFor 的理由就是確保網址格式不會發生問題（像是把留言板放在 http://網址/gb/ 下，如果網址設定為 / 那就會跑去 http://網址/ 而非 http://網址/gb 摟！）</p>

<p>那麼，我們也該幫 $app->post(&#8216;/new&#8217;, function() use ($app){}); 設定一下，以備不實之需。</p>

<figure class='code'><figcaption><span>index.php</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="x">$app-&gt;post(&#39;/new&#39;, function() use ($app){</span>
</span><span class='line'><span class="x">  //略</span>
</span><span class='line'><span class="x">})-&gt;name(&#39;new&#39;);</span>
</span></code></pre></td></tr></table></div></figure>


<p>那麼，最後就是加入表單了！</p>

<p>打開之前的 home.php 加入表單部份</p>

<figure class='code'><figcaption><span>home.php</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="c">&lt;!-- 前略 --&gt;</span>
</span><span class='line'>          <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;row&quot;</span><span class="nt">&gt;</span>
</span><span class='line'>              <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;span16&quot;</span><span class="nt">&gt;</span>
</span><span class='line'>                  <span class="nt">&lt;form</span> <span class="na">method=</span><span class="s">&quot;post&quot;</span> <span class="na">action=</span><span class="s">&quot;&lt;?php echo $app-&gt;urlFor(&#39;new&#39;); ?&gt;&quot;</span><span class="nt">&gt;</span>
</span><span class='line'>                      <span class="nt">&lt;fieldset&gt;</span>
</span><span class='line'>                          <span class="nt">&lt;legend&gt;</span>Leave a Comment<span class="nt">&lt;/legend&gt;</span>
</span><span class='line'>                          <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;clearfix&quot;</span><span class="nt">&gt;</span>
</span><span class='line'>                              <span class="nt">&lt;label&gt;</span>Nickname<span class="nt">&lt;/label&gt;</span>
</span><span class='line'>                              <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;input&quot;</span><span class="nt">&gt;&lt;input</span> <span class="na">name=</span><span class="s">&quot;nickname&quot;</span> <span class="na">type=</span><span class="s">&quot;text&quot;</span> <span class="na">class=</span><span class="s">&quot;xlarge&quot;</span> <span class="nt">/&gt;&lt;/div&gt;</span>
</span><span class='line'>                          <span class="nt">&lt;/div&gt;</span>
</span><span class='line'>                          <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;clearfix&lt;?php if($errorStatus){ echo &#39; error&#39;; } ?&gt;&quot;</span><span class="nt">&gt;</span>
</span><span class='line'>                              <span class="nt">&lt;label</span> <span class="na">for=</span><span class="s">&quot;textarea&quot;</span><span class="nt">&gt;</span>Content<span class="nt">&lt;/label&gt;</span>
</span><span class='line'>                              <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;input&quot;</span><span class="nt">&gt;</span>
</span><span class='line'>                                  <span class="nt">&lt;textarea</span> <span class="na">name=</span><span class="s">&quot;content&quot;</span> <span class="na">class=</span><span class="s">&quot;xlarge&lt;?php if($errorStatus){ echo &#39; error&#39;; } ?&gt;&quot;</span><span class="nt">&gt;&lt;/textarea&gt;</span>
</span><span class='line'>                                  <span class="cp">&lt;?php if($errorStatus){ ?&gt;</span><span class="nt">&lt;span</span> <span class="na">class=</span><span class="s">&quot;help-block&quot;</span><span class="nt">&gt;</span>You must enter some content.<span class="nt">&lt;/span&gt;</span> <span class="cp">&lt;?php } ?&gt;</span>
</span><span class='line'>                              <span class="nt">&lt;/div&gt;</span>
</span><span class='line'>                          <span class="nt">&lt;/div&gt;</span>
</span><span class='line'>                          <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;actions&quot;</span><span class="nt">&gt;</span>
</span><span class='line'>                              <span class="nt">&lt;button</span> <span class="na">class=</span><span class="s">&quot;btn primary&quot;</span> <span class="na">type=</span><span class="s">&quot;submit&quot;</span><span class="nt">&gt;</span>Add Comment<span class="nt">&lt;/button&gt;</span>
</span><span class='line'>                          <span class="nt">&lt;/div&gt;</span>
</span><span class='line'>                      <span class="nt">&lt;/fieldset&gt;</span>
</span><span class='line'>                  <span class="nt">&lt;/form&gt;</span>
</span><span class='line'>              <span class="nt">&lt;/div&gt;</span>
</span><span class='line'>          <span class="nt">&lt;/div&gt;</span>
</span><span class='line'><span class="c">&lt;!-- 後略 --&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<p>不過，打開網頁又發生錯誤了！到底是怎麼一回事？原來是表單的 action 指向了 $app 但是我們並沒有把 $app 傳給 home.php 使用！</p>

<p>回到 index.php 稍微修改一下</p>

<figure class='code'><figcaption><span>index.php</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="x">$app-&gt;get(&#39;/&#39;, function() use ($app){</span>
</span><span class='line'><span class="x">  //略   </span>
</span><span class='line'><span class="x">  $app-&gt;render(&#39;home.php&#39;,</span>
</span><span class='line'><span class="x">      $app-&gt;render(&#39;home.php&#39;, </span>
</span><span class='line'><span class="x">      array(</span>
</span><span class='line'><span class="x">          &#39;comments&#39; =&gt; $comments,</span>
</span><span class='line'><span class="x">          &#39;totalComments&#39; =&gt; $totalComments,</span>
</span><span class='line'><span class="x">          &#39;app&#39; =&gt; $app,</span>
</span><span class='line'><span class="x">      )</span>
</span><span class='line'><span class="x">  );</span>
</span><span class='line'><span class="x">})-&gt;name(&#39;home&#39;);</span>
</span></code></pre></td></tr></table></div></figure>


<p>呼！這次終於成功運行了！</p>

<h3>小結</h3>

<hr />

<p>好，這次教學就到這邊告一段落！（<del>其實是寫到累了，想偷懶</del>）<br />
如果善用工具如 Aptana, Dreamweaver 會更快的完成喔！</p>

<p>如果對於範例的完整原始碼有興趣，可以到 Github 上面看看。<br />
(V1.0版有加上分頁功能和簡易的檢查機制，而V1.0.1版則是修正了程式碼的Bug各位所看到的都是V1.0.1的程式碼)</p>

<ul>
<li>Source Code : <a href="https://github.com/elct9620/30minGuestBook">https://github.com/elct9620/30minGuestBook</a></li>
<li>Demo : <a href="http://the-30min-gb.herokuapp.com/">http://the-30min-gb.herokuapp.com/</a> - 之後教學更新範例網站也會更新，可能不會和目前的一樣。</li>
</ul>


<p>分頁完成後大致上會長這樣：<br />
<a href="http://www.flickr.com/photos/elct9620/6627445927/"><img src="http://farm8.staticflickr.com/7174/6627445927_b4cc17ff2a.jpg" alt="2012-01-03 20-04-16" /></a></p>

<p><del>但是實際上會跟你想像的落差很大！</del></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[三十分鐘做一個留言板 Part 1]]></title>
    <link href="http://revo-skill.frost.tw/blog/2012/01/03/create-a-guestbook-in-30-mintues-part-1/"/>
    <updated>2012-01-03T16:10:00+08:00</updated>
    <id>http://revo-skill.frost.tw/blog/2012/01/03/create-a-guestbook-in-30-mintues-part-1</id>
    <content type="html"><![CDATA[<h3>前言</h3>

<hr />

<p>其實我自己也不確定是不是三十分鐘完成，畢竟弦也在製作時花了數倍的時間做 Debug 和架構的動作，不過如果再做一次，我想就有信心三十分鐘完成的！</p>

<!--more-->


<h3>規劃架構</h3>

<hr />

<p><a href="http://www.flickr.com/photos/elct9620/6626625299/"><img src="http://farm8.staticflickr.com/7159/6626625299_e19bab872e.jpg" alt="2012-01-03 16-22-15" /></a></p>

<p>這是弦也在完成後的架構，不過也有先替之後的更新做了準備。<br />
這次我們只需要用到這樣的結構就可以。</p>

<pre>
+ app/
    + models/
        - Comment.php
    + config.inc.php
+ lib/
    + ActiveMongo/ - ORM
    + Slim/ - Framework
+ views/
    - home.php
- .htaccess
- index.php
</pre>


<p>除了 lib 資料夾裡面的東西是使用外部的函式庫之外，其餘都是自己撰寫的（.htaccess則是從 Slim Framework 預設給的檔案複製過來的）</p>

<p>這個架構是參考 Slim Framework 官方網站的說明，針對規模比較大的網站所建議的架構，雖然現在規模不大，不過要是有一天要擴大規模時，這個架構就會變得非常方便。</p>

<h3>下載 Library 放置</h3>

<hr />

<p>首先，我們要先下載 Slim Framework 以及 ActiveMongo 然後放到 lib 資料夾，這樣之後才能夠使用。</p>

<ul>
<li>Slim Framework - <a href="http://www.slimframework.com/">http://www.slimframework.com/</a></li>
<li>ActiveMongo - <a href="https://github.com/crodas/ActiveMongo">https://github.com/crodas/ActiveMongo</a></li>
<li>Bootstrap - <a href="http://twitter.github.com/bootstrap">http://twitter.github.com/bootstrap</a></li>
</ul>


<p>雖然這次會使用到 Twitter 的 Bootstrap 不過我們採用直接連結的方式引入 CSS 檔，因為目前留言板還不需要做太多美化，只要介面看起來簡潔乾淨即可。</p>

<h4>Slim Framework</h4>

<p>解壓縮 Slim Framework 打開後，應該會看到這樣的畫面。<br /></p>

<p><a href="http://www.flickr.com/photos/elct9620/6626669915/"><img src="http://farm8.staticflickr.com/7017/6626669915_4368aa2f0d.jpg" alt="2012-01-03 16-37-19" /></a></p>

<p>我們只需要 Slim 資料夾以及 .htaccess 檔而已，所以將 Slim 資料夾放到專案的 lib 資料夾裡面，並且把 .htaccess 檔放到專案的根目錄。</p>

<blockquote><p>.htaccess 檔可以讓我們啟用 Rewrite 功能，有興趣可以到網路上搜尋看看。 <br /></p></blockquote>

<h4>ActiveMongo</h4>

<p>解壓縮 ActiveMongo 打開後，應該會發現只看到 lib 資料夾而沒有 ActiveMongo 資料夾，請先別急。<br />
<a href="http://www.flickr.com/photos/elct9620/6626669973/"><img src="http://farm8.staticflickr.com/7172/6626669973_d6a1e3d0a7.jpg" alt="2012-01-03 16-37-29" /></a></p>

<p>因為開發者不一樣的關係，所以習慣也不一樣。打開 lib 資料夾後馬上就發現直接就是檔案，為了方便自己整理，弦也決定重新命名 lib 為 ActiveMongo 並且複製到自己專案的 lib 資料夾內。<br /></p>

<br />


<p>現在，專案的 lib 資料夾應該會長成這樣：<br /></p>

<pre>
+ lib/
    + ActiveMongo/
    + Slim/
</pre>


<p>完成後，就要開始來撰寫留言板摟！</p>

<h3>設定檔</h3>

<hr />

<p>首先，先來對程式的一些基本設定做好準備吧！<br />
我們會使用到資料庫，所以一定要有連接資訊等等，所以先在 app 資料夾下新增 config.inc.php 來紀錄一些設定吧！<br /></p>

<p>習慣性的註解一下（其實每次 Version 弦也都會忘記改）</p>

<figure class='code'><figcaption><span>config.inc.php</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="cp">&lt;?php</span>
</span><span class='line'><span class="sd">/**</span>
</span><span class='line'><span class="sd"> * Conifg</span>
</span><span class='line'><span class="sd"> * </span>
</span><span class='line'><span class="sd"> * @author Aotoki</span>
</span><span class='line'><span class="sd"> * @version 1.0</span>
</span><span class='line'><span class="sd"> */</span>
</span></code></pre></td></tr></table></div></figure>


<p>接著放入資料庫資訊</p>

<figure class='code'><figcaption><span>config.inc.php</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="cp">&lt;?php</span>
</span><span class='line'><span class="sd">/**</span>
</span><span class='line'><span class="sd"> * Conifg</span>
</span><span class='line'><span class="sd"> * </span>
</span><span class='line'><span class="sd"> * @author Aotoki</span>
</span><span class='line'><span class="sd"> * @version 1.0</span>
</span><span class='line'><span class="sd"> */</span>
</span><span class='line'>
</span><span class='line'><span class="c1">//資料庫資訊</span>
</span><span class='line'><span class="nb">define</span><span class="p">(</span><span class="s1">&#39;DB_HOST&#39;</span><span class="p">,</span> <span class="s1">&#39;localhost&#39;</span><span class="p">);</span> <span class="c1">//伺服器</span>
</span><span class='line'><span class="nb">define</span><span class="p">(</span><span class="s1">&#39;DB_NAME&#39;</span><span class="p">,</span> <span class="s1">&#39;30min-GB-V1&#39;</span><span class="p">);</span> <span class="c1">//資料庫名稱</span>
</span><span class='line'><span class="nb">define</span><span class="p">(</span><span class="s1">&#39;DB_USER&#39;</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">);</span> <span class="c1">//使用者名稱</span>
</span><span class='line'><span class="nb">define</span><span class="p">(</span><span class="s1">&#39;DB_PASS&#39;</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">);</span> <span class="c1">//使用者密碼</span>
</span></code></pre></td></tr></table></div></figure>


<p>最後把一些常數放進去</p>

<figure class='code'><figcaption><span>config.inc.php</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="cp">&lt;?php</span>
</span><span class='line'><span class="sd">/**</span>
</span><span class='line'><span class="sd"> * Conifg</span>
</span><span class='line'><span class="sd"> * </span>
</span><span class='line'><span class="sd"> * @author Aotoki</span>
</span><span class='line'><span class="sd"> * @version 1.0</span>
</span><span class='line'><span class="sd"> */</span>
</span><span class='line'>
</span><span class='line'><span class="c1">//資料庫資訊</span>
</span><span class='line'><span class="nb">define</span><span class="p">(</span><span class="s1">&#39;DB_HOST&#39;</span><span class="p">,</span> <span class="s1">&#39;localhost&#39;</span><span class="p">);</span> <span class="c1">//伺服器</span>
</span><span class='line'><span class="nb">define</span><span class="p">(</span><span class="s1">&#39;DB_NAME&#39;</span><span class="p">,</span> <span class="s1">&#39;30min-GB-V1&#39;</span><span class="p">);</span> <span class="c1">//資料庫名稱</span>
</span><span class='line'><span class="nb">define</span><span class="p">(</span><span class="s1">&#39;DB_USER&#39;</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">);</span> <span class="c1">//使用者名稱</span>
</span><span class='line'><span class="nb">define</span><span class="p">(</span><span class="s1">&#39;DB_PASS&#39;</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">);</span> <span class="c1">//使用者密碼</span>
</span><span class='line'>
</span><span class='line'><span class="c1">//設定基準路徑</span>
</span><span class='line'><span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="nb">defined</span><span class="p">(</span><span class="s1">&#39;ABSPATH&#39;</span><span class="p">)){</span>
</span><span class='line'>  <span class="nb">define</span><span class="p">(</span><span class="s1">&#39;ABSPATH&#39;</span><span class="p">,</span> <span class="nb">dirname</span><span class="p">(</span><span class="k">__FILE__</span><span class="p">)</span> <span class="o">.</span> <span class="s1">&#39;/&#39;</span><span class="p">);</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="c1">//設定除錯模式</span>
</span><span class='line'><span class="nb">define</span><span class="p">(</span><span class="s1">&#39;DEBUG&#39;</span><span class="p">,</span> <span class="k">TRUE</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>


<p>這樣一來，就完成設定檔了！<br />
（說實話，其實弦也平常都是邊寫邊加的，不一定要一開始就全部設定上去。）</p>

<h3>建立基礎</h3>

<p>現在，我們先在根目錄下新增一個 index.php 檔案，他就像 Router (路由) 一樣，全部的請求都會經過他處理（因為 Rewrite 被開啟的關係，伺服器會相關的處理都丟給 index.php 處理）</p>

<br />


<p>一開始，我們先把一些必要得檔案引用進來（像是 Slim Framework, Active Mongo, 設定檔等等）</p>

<figure class='code'><figcaption><span>index.php</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="cp">&lt;?php</span>
</span><span class='line'><span class="sd">/**</span>
</span><span class='line'><span class="sd"> * 30Min Guest Book</span>
</span><span class='line'><span class="sd"> * </span>
</span><span class='line'><span class="sd"> * @author Aotoki</span>
</span><span class='line'><span class="sd"> * @version 1.0</span>
</span><span class='line'><span class="sd"> */</span>
</span><span class='line'>
</span><span class='line'><span class="c1">//載入 Slim Framework</span>
</span><span class='line'><span class="k">require_once</span><span class="p">(</span><span class="s1">&#39;lib/Slim/Slim.php&#39;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'><span class="c1">//載入 Active Mongo (ORM)</span>
</span><span class='line'><span class="k">require_once</span><span class="p">(</span><span class="s1">&#39;lib/ActiveMongo/ActiveMongo.php&#39;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'><span class="c1">//載入設定檔</span>
</span><span class='line'><span class="k">require_once</span><span class="p">(</span><span class="s1">&#39;app/config.inc.php&#39;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'><span class="cp">?&gt;</span><span class="x"></span>
</span></code></pre></td></tr></table></div></figure>


<p>接下來，我們要初始化 Slim Framework 讓他可以運行，接著加入以下的程式碼</p>

<figure class='code'><figcaption><span>index.php (續)</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="x">//初始化 Slim Framework</span>
</span><span class='line'><span class="x">$app = new Slim(</span>
</span><span class='line'><span class="x">  array(</span>
</span><span class='line'><span class="x">      //&#39;http.version&#39; =&gt; &#39;1.0&#39;, //在PHPFog或不支援 HTTP 1.1 的伺服器上使用這個設定</span>
</span><span class='line'><span class="x">      &#39;templates.path&#39; =&gt; &#39;views&#39;, //設定 View 資料夾（視圖層）</span>
</span><span class='line'><span class="x">      &#39;debug&#39; =&gt; DEBUG, //從設定檔讀取是否啟用除錯</span>
</span><span class='line'><span class="x">  )</span>
</span><span class='line'><span class="x">);</span>
</span></code></pre></td></tr></table></div></figure>


<p>這樣，我們就可以用 $app 來做相關 Slim Framework 的操作了！</p>

<blockquote><p>上面這段程式碼，是取得物件的實例並且存在名叫 app 的變數內。<br />
$app 是一個變數，請想像他是一個萬用箱子，可以放入任何東西，但是一次只能有一種東西。<br />
Slim 是一個物件，但是他還未產生實例之前就跟設計圖一樣，裡面紀錄很多關於他的能力。<br />
$app = new Slim(); 這就是我們用 new 產生一個新的物件，叫做 $app 而且他是以 Slim 這個設計圖為基礎製作的。<br />
而在建立時我們會給他一些參數，就像是 templates.path 等等，以上的動作我們可以參考牙膏的製作。<br />
黑人牙膏 = 牙膏（一組秘密配方） 所以黑人牙膏會是黑人牙膏！</p></blockquote>

<p>然後，我們要先連接好資料庫，不然之後的存取就沒辦法使用了！<br />
一樣，接著前面放入這些程式碼</p>

<figure class='code'><figcaption><span>index.php (續)</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="x">//連接資料庫（MongoDB）</span>
</span><span class='line'><span class="x">if(DB_USER &amp;&amp; DB_PASS){</span>
</span><span class='line'><span class="x">  ActiveMongo::connect(DB_NAME, DB_HOST, DB_USER, DB_PASS); //從設定檔讀取資料庫資訊</span>
</span><span class='line'><span class="x">}else{</span>
</span><span class='line'><span class="x">  ActiveMongo::connect(DB_NAME, DB_HOST); //因為ActiveMongo沒有動態設定使用者名稱/密碼的功能，所以另外檢查</span>
</span><span class='line'><span class="x">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>為什麼要用 if(DB_USER &amp; DB_PASS){} 呢？這是因為 Active Mongo 如果不需要帳號密碼時，還是設定進去，會發生錯誤，所以只好這樣設計。（也許我們可以在設定檔將 &#8221; 改為 NULL）<br /></p>

<p>然後，要定義對應的位址，這樣 Framework 才知道什麼時候該顯示什麼！</p>

<figure class='code'><figcaption><span>index.php (續)</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="x">$app-&gt;get(&#39;/&#39;, function() use ($app){</span>
</span><span class='line'><span class="x">  $app-&gt;render(&#39;home.php&#39;);</span>
</span><span class='line'><span class="x">});</span>
</span><span class='line'>
</span><span class='line'><span class="x">$app-&gt;run(); //啟動 Slim Framework</span>
</span></code></pre></td></tr></table></div></figure>


<blockquote><p>$app->get(); 的 get 就是所謂的方法，就像牙膏可以有「擠」這個動作一樣。</p>

<p>function() use ($app) 是 PHP 5.3 之後的功能，要這樣使用請注意自己的 PHP 版本是 5.3 之後，這個功能關係 namespace 暫時不討論</p></blockquote>

<p>到此為止，我們已經對 index.php 做好簡單的設定，現在我們要建立剛剛 render 進來的 home.php 好讓留言板能顯示出畫面。</p>

<h3>第一個樣板</h3>

<p>首先，我們先建立一個空白的網頁，大致建立其基礎。</p>

<figure class='code'><figcaption><span>home.php</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="cp">&lt;!DOCTYPE html&gt;</span>
</span><span class='line'><span class="nt">&lt;html</span> <span class="na">lang=</span><span class="s">&quot;zh-tw&quot;</span><span class="nt">&gt;</span>
</span><span class='line'><span class="nt">&lt;head&gt;</span>
</span><span class='line'>  <span class="nt">&lt;meta</span> <span class="na">charset=</span><span class="s">&quot;utf-8&quot;</span> <span class="nt">/&gt;</span>
</span><span class='line'>
</span><span class='line'>  <span class="nt">&lt;meta</span> <span class="na">http-equiv=</span><span class="s">&quot;X-UA-Compatible&quot;</span> <span class="na">content=</span><span class="s">&quot;IE=edge,chrome=1&quot;</span> <span class="nt">/&gt;</span>
</span><span class='line'>
</span><span class='line'>  <span class="nt">&lt;title&gt;</span>My 30min Guest Book<span class="nt">&lt;/title&gt;</span>
</span><span class='line'>  <span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">&quot;description&quot;</span> <span class="na">content=</span><span class="s">&quot;&quot;</span> <span class="nt">/&gt;</span>
</span><span class='line'>  <span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">&quot;author&quot;</span> <span class="na">content=</span><span class="s">&quot;Aotoki&quot;</span> <span class="nt">/&gt;</span>
</span><span class='line'>
</span><span class='line'>  <span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">&quot;viewport&quot;</span> <span class="na">content=</span><span class="s">&quot;width=device-width; initial-scale=1.0&quot;</span> <span class="nt">/&gt;</span>
</span><span class='line'><span class="nt">&lt;/head&gt;</span>
</span><span class='line'>
</span><span class='line'><span class="nt">&lt;body&gt;</span>
</span><span class='line'>  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;container&quot;</span><span class="nt">&gt;</span>
</span><span class='line'>      <span class="nt">&lt;header&gt;</span>
</span><span class='line'>          <span class="nt">&lt;h1&gt;</span>Guest Book<span class="nt">&lt;/h1&gt;</span>
</span><span class='line'>      <span class="nt">&lt;/header&gt;</span>
</span><span class='line'>      <span class="nt">&lt;nav&gt;</span>
</span><span class='line'>          <span class="c">&lt;!--- 選單 --&gt;</span>
</span><span class='line'>      <span class="nt">&lt;/nav&gt;</span>
</span><span class='line'>
</span><span class='line'>      <span class="nt">&lt;div&gt;</span>
</span><span class='line'>          <span class="c">&lt;!-- 內容 --&gt;</span>
</span><span class='line'>      <span class="nt">&lt;/div&gt;</span>
</span><span class='line'>
</span><span class='line'>      <span class="nt">&lt;footer&gt;</span>
</span><span class='line'>       <span class="nt">&lt;p&gt;</span><span class="ni">&amp;copy;</span> Copyright by Aotoki<span class="nt">&lt;/p&gt;</span>
</span><span class='line'>      <span class="nt">&lt;/footer&gt;</span>
</span><span class='line'>  <span class="nt">&lt;/div&gt;</span>
</span><span class='line'><span class="nt">&lt;/body&gt;</span>
</span><span class='line'><span class="nt">&lt;/html&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<p>我選擇了 HTML5 的方式建立，現在打開瀏覽器，連上留言板應該會看到一個粗體字寫著&#8221;Guest Book&#8221;然後就沒了！<br />
不過，這也是正常的。</p>

<h3>小結</h3>

<hr />

<p>好吧，我承認對初次接觸的大家來說做到這樣可能已經花上三十分鐘了！<br />
所以，先休息一下，待會 Part 2 就會繼續解說關於讀取留言的部份，雖然有點抽象，但是等留言功能完成的時候，就會發現非常的感動喔！</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[在PHPFog上架設WordPress(中文版)]]></title>
    <link href="http://revo-skill.frost.tw/blog/2011/12/13/let-wordpress-on-phpfog/"/>
    <updated>2011-12-13T20:05:00+08:00</updated>
    <id>http://revo-skill.frost.tw/blog/2011/12/13/let-wordpress-on-phpfog</id>
    <content type="html"><![CDATA[<h3>前言</h3>

<hr />

<p>你還在默默的找免空嗎？別再耗費精力啦！<br />
在PHPFog上安裝一個WordPress是非常簡單又容易的，趕緊申請一個帳號，開始你的「雲端網誌」吧！</p>

<!--more-->


<h3>申請帳號</h3>

<hr />

<p>首先，我們打開 <a href="https://phpfog.com">PHPFog</a> 官方網站。<br />
稍微往下捲動就會發現有三個輸入框，依序輸入信箱、密碼、確認密碼即可。<br />
<a href="http://www.flickr.com/photos/elct9620/6504679843/"><img src="http://farm8.staticflickr.com/7035/6504679843_9b48808e6c.jpg" alt="螢幕快照 2011-12-13 下午7.07.35" /></a></p>

<p>點擊Get Started後，就會出現 Create new App 的畫面（第一次會這樣）<br />
<a href="http://www.flickr.com/photos/elct9620/6504679987/"><img src="http://farm8.staticflickr.com/7017/6504679987_49a8694545.jpg" alt="螢幕快照 2011-12-13 下午7.08.04" /></a></p>

<h3>安裝</h3>

<hr />

<p>既然我們是要 WordPress Application 就選擇 WordPress<br />
<a href="http://www.flickr.com/photos/elct9620/6504680061/"><img src="http://farm8.staticflickr.com/7154/6504680061_5773351807.jpg" alt="螢幕快照 2011-12-13 下午7.08.13" /></a></p>

<p>接著會要我們輸入一些資本資訊（管理員帳號、密碼、網址）<br />
<a href="http://www.flickr.com/photos/elct9620/6504680155/"><img src="http://farm8.staticflickr.com/7015/6504680155_67bde8968f.jpg" alt="螢幕快照 2011-12-13 下午7.08.37" /></a></p>

<blockquote><p>如果你的帳號是 Beta 時就申請的，那麼 Custom Domain 是 Free 的，但是如果你是新用戶，想要 Custom Domain 就得支付每月 $5 的費用。</p></blockquote>

<p>點選 Create App 之後，會進入該 Application 的管理畫面，此時會看到亮紅燈，寫著 Starting, Preparing App 之類的訊息。<br />
<a href="http://www.flickr.com/photos/elct9620/6504680281/"><img src="http://farm8.staticflickr.com/7033/6504680281_2df5c56394.jpg" alt="螢幕快照 2011-12-13 下午7.09.05" /></a></p>

<h3>安裝Git</h3>

<hr />

<blockquote><p>Mac OS, Linux 的使用者我想應該都非常熟悉了，所以特地為 Windows 的使用者撰寫這部份的使用教學。<br /></p></blockquote>

<p>首先，到 <a href="http://git-scm.com/">Git官方網站</a> 下載Git來安裝。<br />
<a href="http://www.flickr.com/photos/elct9620/6504680553/"><img src="http://farm8.staticflickr.com/7013/6504680553_7fb16c0491.jpg" alt="螢幕快照 2011-12-13 下午7.12.13" /></a></p>

<p><a href="http://www.flickr.com/photos/elct9620/6504680645/"><img src="http://farm8.staticflickr.com/7170/6504680645_3d7173b3e0.jpg" alt="螢幕快照 2011-12-13 下午7.12.35" /></a></p>

<p>下載好安裝檔後，直接執行並且安裝。<br /></p>

<blockquote><p>基本上只要不斷 Next 即可。</p></blockquote>

<p><a href="http://www.flickr.com/photos/elct9620/6504680727/"><img src="http://farm8.staticflickr.com/7168/6504680727_542a7f3b7c.jpg" alt="螢幕快照 2011-12-13 下午7.13.50" /></a></p>

<p><a href="http://www.flickr.com/photos/elct9620/6504680813/"><img src="http://farm8.staticflickr.com/7004/6504680813_f221e74250.jpg" alt="螢幕快照 2011-12-13 下午7.14.13" /></a></p>

<p><a href="http://www.flickr.com/photos/elct9620/6504680881/"><img src="http://farm8.staticflickr.com/7024/6504680881_b586d314f0.jpg" alt="螢幕快照 2011-12-13 下午7.21.02" /></a></p>

<h3>設定SSH Key</h3>

<hr />

<p>此時，我們的WordPress應該已經安裝好，呈現 Running 的狀態。<br />
<a href="http://www.flickr.com/photos/elct9620/6504680377/"><img src="http://farm8.staticflickr.com/7162/6504680377_8008996209.jpg" alt="螢幕快照 2011-12-13 下午7.10.36" /></a></p>

<blockquote><p>建議各位先打開來看看，因為弦也中文化完畢後卻發生 404 找不到的錯誤，可能是 PHPFog 有問題，因此建議先檢查好在繼續動作。</p></blockquote>

<p>如果你的帳號沒有任何SSH Key系統會提醒你新增一個（每台電腦都不同，也可以重新新增，類似鑰匙和鑰匙孔的關係）<br />
<a href="http://www.flickr.com/photos/elct9620/6504680463/"><img src="http://farm8.staticflickr.com/7169/6504680463_a6f3784357.jpg" alt="螢幕快照 2011-12-13 下午7.11.42" /></a></p>

<p>打開你的 Git Bash<br />
<a href="http://www.flickr.com/photos/elct9620/6504680937/"><img src="http://farm8.staticflickr.com/7018/6504680937_02fb1a3322_t.jpg" alt="螢幕快照 2011-12-13 下午7.22.01" /></a></p>

<blockquote><p>弦也教同學時使用 Git GUI 結果無法正常 Clone 檔案，因此建議還是用 Command Line 這種優良的傳統用法吧！（而且還可以耍帥讓同學覺得你很威！）</p></blockquote>

<p><a href="http://www.flickr.com/photos/elct9620/6504681027/"><img src="http://farm8.staticflickr.com/7023/6504681027_53e28807e3.jpg" alt="螢幕快照 2011-12-13 下午7.23.34" /></a></p>

<p>輸入指令產生 SSH Key</p>

<pre><code>$ ssh-keygen -t rsa</code></pre>


<p><a href="http://www.flickr.com/photos/elct9620/6504681111/"><img src="http://farm8.staticflickr.com/7008/6504681111_6e1861f7ae.jpg" alt="螢幕快照 2011-12-13 下午7.24.02" /></a></p>

<p>會出現詢問，問你要將 SSH Key 存在哪裡（預設不用改動）<br />
<a href="http://www.flickr.com/photos/elct9620/6504681193/"><img src="http://farm8.staticflickr.com/7160/6504681193_6c0e6c0e33.jpg" alt="螢幕快照 2011-12-13 下午7.24.11" /></a></p>

<p>接下來會問你是否設定密碼，可以不填寫按下Enter跳過（第一次輸入，第二次確認）<br />
<a href="http://www.flickr.com/photos/elct9620/6504681263/"><img src="http://farm8.staticflickr.com/7024/6504681263_cfc2ee4282.jpg" alt="螢幕快照 2011-12-13 下午7.24.18" /></a></p>

<p><a href="http://www.flickr.com/photos/elct9620/6504681369/"><img src="http://farm8.staticflickr.com/7145/6504681369_049d280698.jpg" alt="螢幕快照 2011-12-13 下午7.24.26" /></a></p>

<p><a href="http://www.flickr.com/photos/elct9620/6504681467/"><img src="http://farm8.staticflickr.com/7171/6504681467_42d7a8449a.jpg" alt="螢幕快照 2011-12-13 下午7.24.32" /></a></p>

<p>完成後打開所在目錄</p>

<blockquote><p>弦也的是 C:/Users/Adminstrator/.ssh (Windows7 會把 Users 顯示成 「使用者」)</p></blockquote>

<p><a href="http://www.flickr.com/photos/elct9620/6504681583/"><img src="http://farm8.staticflickr.com/7162/6504681583_2a239da451.jpg" alt="螢幕快照 2011-12-13 下午7.25.16" /></a></p>

<p>雙擊 id_rsa.pub 檔案開啟（或者用 Notepad++ 之類的軟體開啟都可以）<br />
<a href="http://www.flickr.com/photos/elct9620/6504681655/"><img src="http://farm8.staticflickr.com/7035/6504681655_6a8942e06d.jpg" alt="螢幕快照 2011-12-13 下午7.25.29" /></a></p>

<p><a href="http://www.flickr.com/photos/elct9620/6504681743/"><img src="http://farm8.staticflickr.com/7166/6504681743_309eb6155e.jpg" alt="螢幕快照 2011-12-13 下午7.25.41" /></a></p>

<p>全選裡面的內容，然後複製（千萬別剪下，然後存檔，這樣就不能用了！）<br />
<a href="http://www.flickr.com/photos/elct9620/6504681825/"><img src="http://farm8.staticflickr.com/7013/6504681825_4b910e9fc0.jpg" alt="螢幕快照 2011-12-13 下午7.25.52" /></a></p>

<p>接著打開 PHPFog 的頁面，剛剛點擊了 Setup SSH Key 的連結，應該會出現如下的畫面。</p>

<pre>Nickname 可以隨便填寫，如 My Computer 之類的，而 Public Key 則貼上你剛剛複製的東西</pre>


<p><a href="http://www.flickr.com/photos/elct9620/6504681949/"><img src="http://farm8.staticflickr.com/7033/6504681949_75d383ebd2.jpg" alt="螢幕快照 2011-12-13 下午7.26.16" /></a></p>

<p>最後儲存即可！<br />
<a href="http://www.flickr.com/photos/elct9620/6504682031/"><img src="http://farm8.staticflickr.com/7004/6504682031_59527426b2.jpg" alt="螢幕快照 2011-12-13 下午7.26.36" /></a></p>

<h3>下載原始碼</h3>

<hr />

<p>這樣和PHPFog溝通的程序就完成了，接著我們要把PHPFog安裝好的WordPress下載下來修改（新增中文化）</p>

<p>先回到App的管理介面<br />
<a href="http://www.flickr.com/photos/elct9620/6504682111/"><img src="http://farm8.staticflickr.com/7005/6504682111_e5b31713c9.jpg" alt="螢幕快照 2011-12-13 下午7.26.56" /></a></p>

<p>選擇 Source Code 查看 git 要 clone 的位址<br />
<a href="http://www.flickr.com/photos/elct9620/6504682195/"><img src="http://farm8.staticflickr.com/7166/6504682195_b9c3ec48bb.jpg" alt="螢幕快照 2011-12-13 下午7.27.20" /></a></p>

<p>將 git clone … 這行記錄起來，待會會用來下載。<br />
<a href="http://www.flickr.com/photos/elct9620/6504682291/"><img src="http://farm8.staticflickr.com/7172/6504682291_e41b2beb96.jpg" alt="螢幕快照 2011-12-13 下午7.27.25" /></a></p>

<p>回到 Git Bash<br />
<a href="http://www.flickr.com/photos/elct9620/6504682375/"><img src="http://farm8.staticflickr.com/7035/6504682375_7dba14f155.jpg" alt="螢幕快照 2011-12-13 下午7.27.46" /></a></p>

<blockquote><p>弦也打算把資料放在桌面，所以 cd Desktop 切換到桌面。</p></blockquote>

<p>輸入剛剛的 git clone … 指令<br />
<a href="http://www.flickr.com/photos/elct9620/6504682475/"><img src="http://farm8.staticflickr.com/7170/6504682475_77af174f0e.jpg" alt="螢幕快照 2011-12-13 下午7.28.03" /></a></p>

<blockquote><p>第一次連線會運你說確定要繼續連接（未知的遠端伺服器）此時輸入 yes 就可以繼續</p></blockquote>

<p>連上之後就會開始下載 WordPress 原始碼<br />
<a href="http://www.flickr.com/photos/elct9620/6504682575/"><img src="http://farm8.staticflickr.com/7160/6504682575_82856fdcba.jpg" alt="螢幕快照 2011-12-13 下午7.28.10" /></a></p>

<h3>中文化</h3>

<hr />

<p>在等待下載的時間，我們可以先到 <a href="http://tw.wordpress.org">WordPress正體中文</a> 下載 WordPress 繁體中文版。<br />
<a href="http://www.flickr.com/photos/elct9620/6504682639/"><img src="http://farm8.staticflickr.com/7009/6504682639_1f6e064759.jpg" alt="螢幕快照 2011-12-13 下午7.28.40" /></a></p>

<p>此時，剛剛下載的 WordPress 原始碼應該完成了，打開資料夾看一下。<br />
<a href="http://www.flickr.com/photos/elct9620/6504682945/"><img src="http://farm8.staticflickr.com/7148/6504682945_1e61552374.jpg" alt="螢幕快照 2011-12-13 下午7.33.02" /></a></p>

<blockquote><p>正常情況會看到一個 .git 資料夾，那是 git 的資料，千萬不要誤刪</p></blockquote>

<p>解壓縮剛剛下載好的 WordPress 繁體中文版，然後都切換到 wp-content 資料夾準備複製語言包。<br />
<a href="http://www.flickr.com/photos/elct9620/6504683105/"><img src="http://farm8.staticflickr.com/7016/6504683105_c261ceb101.jpg" alt="螢幕快照 2011-12-13 下午7.33.28" /></a></p>

<p>將 WordPress 正體中文版的 wp-content/languages 資料夾複製到 App 的 wp-content 資料夾裡面。<br />
<a href="http://www.flickr.com/photos/elct9620/6504683333/"><img src="http://farm8.staticflickr.com/7157/6504683333_10358897bc.jpg" alt="螢幕快照 2011-12-13 下午7.33.46" /></a></p>

<p>接著打開 wp-config.php (根目錄下) 編輯(記事本或Notepad++等各種編輯器)。<br />
<a href="http://www.flickr.com/photos/elct9620/6504683421/"><img src="http://farm8.staticflickr.com/7020/6504683421_d44843f0a1.jpg" alt="螢幕快照 2011-12-13 下午7.34.30" /></a></p>

<p>找到以下程式碼：</p>

<pre><code> define('WPLANG', ''); </code></pre>


<p>然後改為：</p>

<pre><code> define('WPLANG', 'zh_TW'); </code></pre>


<p>結果如下圖，然後存檔。<br />
<a href="http://www.flickr.com/photos/elct9620/6504683533/"><img src="http://farm8.staticflickr.com/7172/6504683533_db92225df8.jpg" alt="螢幕快照 2011-12-13 下午7.34.42" /></a></p>

<h3>上傳</h3>

<hr />

<p>接著，我們先切換到 App 的目錄下，這樣才可以進行上傳（因為才有 .git 資料夾可以知道伺服器位置等等資訊）<br />
<a href="http://www.flickr.com/photos/elct9620/6504682767/"><img src="http://farm8.staticflickr.com/7164/6504682767_f5537b5d92.jpg" alt="螢幕快照 2011-12-13 下午7.30.27" /></a></p>

<blockquote><p>弦也的 App 網址為 elct9620.phpfogapp.com 但各位的不是，請不要打錯喔！</p></blockquote>

<p>輸入指令，新增要更新的檔案：</p>

<pre><code> $ git add . </code></pre>


<blockquote><p>. 就是全部的意思，這樣比較快可以完成選取檔案</p></blockquote>

<p><a href="http://www.flickr.com/photos/elct9620/6504683665/"><img src="http://farm8.staticflickr.com/7028/6504683665_de5d82236b.jpg" alt="螢幕快照 2011-12-13 下午7.35.03" /></a></p>

<p>接著輸入指令，註記這次更新是什麼情況：</p>

<pre><code> $ git commit -m "Add Chinese Language"</code></pre>


<blockquote><p>&#8221; 裡面的訊息可以自己輸入，因為這是中文化，所以輸入 Add Chinese Language</p></blockquote>

<p><a href="http://www.flickr.com/photos/elct9620/6504683841/"><img src="http://farm8.staticflickr.com/7157/6504683841_250fb37842.jpg" alt="螢幕快照 2011-12-13 下午7.35.22" /></a></p>

<p>之後會列出這次更新的檔案，檢查一下是否有檔案漏掉。<br />
<a href="http://www.flickr.com/photos/elct9620/6504683975/"><img src="http://farm8.staticflickr.com/7167/6504683975_f7a82881e6.jpg" alt="螢幕快照 2011-12-13 下午7.35.31" /></a></p>

<p>全部都OK之後，再次輸入指令將中文化好的 WordPress 上傳。</p>

<pre><code> $ git push </code></pre>


<p><a href="http://www.flickr.com/photos/elct9620/6504684109/"><img src="http://farm8.staticflickr.com/7167/6504684109_5ef1f6a1ea.jpg" alt="螢幕快照 2011-12-13 下午7.35.39" /></a></p>

<p>完成後，回到 <a href="https://phpfog.com">PHPFog</a> 管理頁面，再次打開 WordPress 就會發現被中文化了！<br />
<a href="http://www.flickr.com/photos/elct9620/6504684203/"><img src="http://farm8.staticflickr.com/7033/6504684203_90477fbf73.jpg" alt="螢幕快照 2011-12-13 下午7.36.00" /></a></p>

<p>呼呼！好久沒有寫這麼長的文章了，還挺累的，不過希望大家都可以輕鬆架設出自己的 WordPress on PHPFog 喔！</p>

<blockquote><p>其實用心經營一段時間後，網誌的廣告費大概也夠支付 $5/month 的 Custom Domain 和 Domain 的費用。不過想用 Sliver 這些付費方案，可能就要更加努力才行了！</p></blockquote>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Hello Octopress]]></title>
    <link href="http://revo-skill.frost.tw/blog/2011/11/27/hello-octopress/"/>
    <updated>2011-11-27T20:35:00+08:00</updated>
    <id>http://revo-skill.frost.tw/blog/2011/11/27/hello-octopress</id>
    <content type="html"><![CDATA[<p>第一次使用 Octopress 發佈再 Heroku 上。</p>

<p>這次的網誌也是以 Revolution 命名的，想必大家很清楚，這也是大學時期用的網誌。</p>

<p>往後會記錄以下的文章：</p>

<ul>
<li>程式語言</li>
<li>網頁設計</li>
<li>APP開發</li>
</ul>


<p>不然只有 Tumblr 記錄生活，還真的是太悶了～</p>
]]></content>
  </entry>
  
</feed>

