Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save wastemobile/7947928 to your computer and use it in GitHub Desktop.
Save wastemobile/7947928 to your computer and use it in GitHub Desktop.

1 介紹

Symphony 很棒,讓我們來讓它更好。

這文章與建立網站的前端相關,維持模板(templates)能夠重複利用,關聯資料來源(Datasources)、事件(Events)以及其他資源到你的頁面(Pages),程式碼的架構,還有更多。這文件的起心動念,是因為發現自己不停的重複再重複相同流程,才有了改良的意圖。

假設你已經知道 Symphony CMS 的 master.xsl 是什麼,同時也已經用過它。如果你還不明瞭,請先參考 Symphony 的預設 workspace.

2 一切從需求開始

客戶(或是你自己)說:「我有一些活動即將開始,我想讓這些資訊出現在首頁與聯繫頁面。」

2.1 取得資源

我們已經有一個「活動」的資料表(section)記錄了三個欄位:

  • Title (Textbox field) - 活動的標題
  • Body (Textbox field) - 內文
  • Date (Date field) - 開始的日期時間

兩個頁面:

  • Home
  • Contact

還有一個資料來源,擷取了下一個活動

  • Next event

3 傳統的工作流程

將資料呈現於前端的傳統工作流程

  1. 加附需要的 DatasourcesEventsPage
  2. page.xsl 模板中寫 XSL 代碼
  3. 將 CSS 與 JS 寫進一些檔案中

現在我們要在首頁呈現接下來的活動資訊:

  1. 加附 Next event Datasource 到 Home 頁面
  2. 寫 XSL code 到 home.xsl
  3. 將 CSS 與 JS 寫進一些檔案中

Contact 頁面要重複相同的事:

  1. 加附 Next event Datasource 到 Contact 頁面
  2. home.xsl 拷貝、貼上一些 XSL 代碼到 contact.xsl
  3. 同樣拷貝 CSS 與 JS(這些檔案不是應該可以沿用?)

客戶高興了,但是...

我們做了很多重複的工:

  1. 加附 Next event Datasource 到 yyy 頁面 (重複工作問題 #1)
  2. xxx.xsl 重複拷貝、貼上到 yyy.xsl (重複工作問題 #2)
  3. 拷貝與貼上 CSS 和 JS (重複工作問題 #3)

4 改善工作流程 (重複工作問題 #2)

重複的 XSL 代碼不是件好事。為了避免重工,重新架構是必要的。一般來說,可以在 /workspace/utilities 目錄下建立一個新的 XSL 檔案擺放這些代碼;但為了達成這目的,我會建立 Widget,讓 Utilities 真的只控管「工具碼」,像是 form-controls.xsldate-format.xsl 這類代碼。

一個 Widget 不只是一個單純的 XSL 工具碼,稍後會解釋這點。現在,我會建立一個 XSL 檔案,擺在 /workspace/widgets/next-event/xsl/next-event.xsl,然後只放必要的 XSL 代碼進去。

<xsl:template name="w_next-event">
    <!-- Code to display the widget -->
</xsl:template>

注意: 根據我的理論,masterl.xsl 也應該是個 Widget,而不是一個 Utility

工作流程改善 #1 在前端呈現內容:

  1. 加附需要的 DatasourcesEventsPage
  2. 如果還沒有需要的 Widgets,就新建它;若是已經存在,匯入到 Page 然後呼叫那些由 Widgets 提供的 templates(指 XSL template)
  3. 將 CSS 與 JS 寫進一些檔案中

現在就來在 Home 頁面呈現我們的活動:

  1. 加附 Next event 資料來源到 Home 頁面
  2. 建立 next-event.xsl,匯入到 home.xsl 接著呼叫 w_next-event.xsl template
  3. 將 CSS 與 JS 寫進一些檔案中

Now, the same thing for Contact Page:

  1. 加附 Next event 資料來源到 Contact 頁面
  2. next-event.xsl 匯入到 contact.xsl 並呼叫 w_next-event.xsl template
  3. 拷貝與貼上 CSS 和 JS

簡單明瞭。我想你正在這樣做,對吧?:)

這改善了 XSL 代碼重複的問題,但是...

還有兩個問題需要修正:

  1. 加附需要的 DatasourcesEventsPage (重工問題 #1)
  2. 若沒有需要的 Widgets,建立它;匯入到 Page 並從 Widgets 呼叫 templates
  3. 將 CSS 與 JS 寫進一些檔案中 (重工問題 #3)

5 改進工作流程 (重工問題 #1)

當需要把這個 widget 加入到網站內20個頁面時,就會發現這步驟很惱人:

  1. 加附 Next event 資料來源到 XXX 頁面

萬一我們的 Next event Widget 需要四個資料來源?然後還有一個表單、兩個事件也要處理?

在每一頁你都需要手動加入四個資料來源和兩個事件,一直重複這些工作?能不能讓 Next event Widget 也有類似頁面的能力,就是可以加附資料來源和事件上去...

Widget 關聯到四個資料來源和兩個事件:

Next event -> Datasource #1
           -> Datasource #2
           -> Datasource #3
           -> Datasource #4
           -> Event #1
           -> Event #2

頁面包含 Widget:

Home -> Next event
Contact -> Next event

如此一來,開發者只需要串聯一個頁面到一個 Widget,收工。想要嗎?繼續讀下去就有了。

工作流程改善 #2 在前端顯示資料:

  1. 建立需要的 Widgets:
  • 加附 DatasourcesEventsWidget
  • 寫 XSL 代碼到 Widget 檔案
  1. 匯入 WidgetsPage 並從裡面呼叫需要的 templates
  2. 將 CSS 與 JS 寫進一些檔案中

Now let's display our event on Home Page:

  1. Create Next event widget:
    • Attach Next event Datasource to Widget
    • Write XSL code in next-event.xsl
  2. Import next-event.xsl in home.xsl & call w_next-event.xsl template
  3. Write CSS & JS in some files

Now let's display our event on Contact Page:

  1. Next event widget already exists (it includes the Datasources & Events as well)
  2. Import next-event.xsl in contact.xsl & call w_next-event.xsl template
  3. Copy + paste the CSS and JS

Neat, right? If the project has more than 10 pages, this workflow is a time-saver. But ...

There is still one duplication problem:

  1. Create required Widgets:
  • Attach Datasources & Events to Widget
  • Write XSL code in Widget file
  1. Import Widgets in Page & call templates from Widgets
  2. Write CSS & JS in some files (DRY problem #3)

6 Improving workflow (DRY problem #3)

This code duplication affects assets like CSS & JS. In my projects I found it very useful to have a CSS file and a JS file for each Page.

Looking above, it is logical to have a CSS file and a JS file for each Widget. This way, a Widget will include the Datasources & Events and some XSL, CSS and JS files.

I find it VERY handy to group all these files together. In Symphony's default workspace the CSS and JS for all pages and resources are kept together (CSS in /workspace/css, JS in/workspace/js). I decided to group them related to functionality and came up with this structure:

/workspace
    /css
        library files like bootstrap.css
        ...
    
    /datasources
        next_event.php
        ...

    /events
        ...
    
    /js
        library files like bootstrap.js
        ...

    /pages
        /home
            /config
                home.xml
            /css
                home.css
            /js
                home.js
            /xsl
                home.xsl
        ...

    /utilities
        date-format.xsl
        form-controls.xsl
        ...

    /widgets
         /master
            /config
                master.xml
            /css
                master.css
            /js
                master.js
            /xsl
                master.xsl
        /next-event
            /config
                next-event.xml
            /css
                next-event.css
            /js
                next-event.js
            /xsl
                next-event.xsl
        ...

Workflow final for meeting the requirement from our client requires this:

  1. Create a Widget
    • Link the Widget to Datasources & Events
    • Write XSL, CSS & JS in their dedicated files. Include the CSS & JS within XSL
  2. Link the Page to the Widget (similar to linking Datasources & Events)
  3. Include widget.xsl in page.xsl
  4. Call widget template in page.xsl

Have I told you that a Widget can be linked to another Widget? Yes, they can be linked. So, the final solution to our problem would be:

  1. Create Master widget
  2. Create Next event widget
  3. Home & Contact pages already include Master
  4. Link Master to Next event

Ta-da !

P: Home    -----v 
             W: Master -> W: Next Event -> DS: Next event
P: Contact -----^

7 Final words

I'm successfully using this workflow so far and developing time for a given feature reduced drastically. My Widgets library keeps growing from project to project. I hope yours will as well.

Food for thought: How hard would it be to port functionality from one site to another using this structure?

If you're interested, make sure you follow the Resources repository on GitHub. If you can't find it, it means I didn't create it, yet, but will do it soon enough. This repository is the base implementation to make the above idea possible.

#8 Full ensemble available

There's an ensemble available containing some examples of the workflow. See the Readme for details.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment