如何水水地寫一個網站。(草稿)

huiter發表於2012-07-18

如何水水地寫一個網站。(草稿)

這篇將介紹用比較簡單的方式來寫一個網站

一、語言問題

如果你是選擇了Ruby的話,太牛了,我還沒接觸過。
如果你是選擇了Python的話,寫個網站,django一定是首選,很遺憾我也沒接觸過。
如果你是選擇了PHP的話,那就太好了,因為我也是一個PHP水貨。

所以語言問題解決了,就用PHP。

二、框架問題

首先是PHP的框架,當時作為小白的我面對這個問題果斷地去問了Luin神,Luin神推薦了Yii。
然後我就去看了看,果斷放棄了,的確不大易入門。探索過程之中發現了codeigniter,也就是CI框架。
這個框架的優點在於有異常清新的文件。

http://codeigniter.com.cn/user_guide/

這個典型的MVC框架+社群很活躍,無疑是一個比較好的選擇。


其次就是前端框架了,果斷用了twitter的bootstarp。
因為你沒有UI,沒有前端做出來的效果一定很挫,抱著把站搭出來的目的,這個是一個很好的選擇了。

http://twitter.github.com/bootstrap/

這個東西的確像它宣傳的那樣,適合各個水平的使用者,稍後細講吧。


三、開始學著使用框架

1.寫靜態頁

作為一個什麼也不會的孩子,先寫靜態頁是最明智的選擇了。

其實產品設計師也可以寫寫靜態頁,有些時候比用Axure做原型還快,保真度還高。

學習寫靜態頁的第一步就是找一個網站抄。
怎麼抄呢? 你要現有個Chrome瀏覽器吧。(我不大喜歡firefox。。。) 開啟bootstarp的介紹頁面,右鍵審查元素。 慢慢地看裡面的程式碼是怎麼寫的,頁面的樣子是什麼樣的。 然後自己新建個空白文件,把CSS,JS引用上,開始自己不斷地嘗試。

其實一段時間之後你就會發現,你用到的也就是那麼多。

首先是佈局。
(1)柵格化,頁面寬等分為12份,弄出1、2、9三個寬度的DIV。

<div class="row">
    <div class="span3">
        <div class="row">
            <div class="span1">
            </div>
            <div class="span2">
            </div>
        </div>
    </div>
    <div class="span9">
    </div>
</div>

響應式佈局神馬的我覺得就不要用了。個人不看好那個東西。 (2)icon,bootstrap自帶了很多比較好看的icon基本可以滿足需求。

<i class="icon-search icon-white"></i>

(3)button,label,badge

其實就是class="xxx xxx-yyy"來達到不同的顏色

(4)form,table,navbar 照著抄就行了。

不多講了

(5)各種效果、Modals與Dropdowns是比較常用的,其實不用懂那麼多。

<a href="#" class="btn btn-danger" rel="popover" data-content="And here's some amazing content. It's very engaging. right?" data-original-title="A Title">hover for popover</a>

這是Popovers的樣例程式碼,讀過application.js那個檔案的同志們就應該明白,其實各種效果的實現都是依靠'rel'、 ‘data-xxx’等實現的。各種效果無非就是裡面的引數不同而已。即使要自己的特殊定製,直接呼叫它們封裝好的函式即可。

(6)html頁面要css和js檔案。css檔案就不多說了,就那一個官方的檔案。js檔案通常要包含以下幾個:

<script src="/assets/js/jquery-1.7.2.min.js"></script>
<script src="/assets/js/bootstrap.min.js"></script>
<script src="/assets/js/application.js"></script>

.min 就是壓縮過的,載入速度變快的效果還是很明顯的。
application.js 就是實現了DEMO中各種效果的一些按鈕監聽什麼的,有興趣可以去看看。

(7)光用bootstarp自帶的肯定是不夠的,而且有時候需要對部分地方重新定義,你可以新建一個css檔案,用同名的類直接覆蓋掉之前的就可以了。js每個頁面也來個單獨的js檔案。


2.開始學習ci框架了。

無疑就是開始上來看文件

http://codeigniter.org.cn/user_guide/index.html

遇到看不懂的就過,其實就是很普通的MVC。 不過後端框架問題就是多,你需要環境呀、什麼apache\php,資料庫什麼的先不說了。 mac下這些都比較好搞。

http://dancewithnet.com/2010/05/09/run-apache-php-mysql-in-mac-os-x/

隨網之舞的這篇文章的確很好用。
然後你就可以在~目錄下建若干個網站,然後配置幾個虛擬主機(上面的域名隨便寫),然後去改hosts檔案把虛擬主機用的域名都換成127.0.0.1就好了。

之後去github上clone下,就可以開始體驗了。

https://github.com/EllisLab/CodeIgniter/tree/2.1-stable

放到網站根目錄後訪問,會看到welcome頁面。

其實用CI開發只需關注幾點。

/application/controllers/ 存放C層檔案
/application/models/ 存放M層檔案
/application/views/ 存放V層檔案
/application/config/ 存放配置檔案
/application/libraries 存放一些你需要的檔案

自建目錄
/assets/{js/ico/css/img} 存放各種這些檔案

自建目錄
/scripts/sql/ 存放sql檔案

基本就這麼多。

CI的程式入口在根目錄下的index.php,所有的訪問必經過這裡。 所以你可以在這個檔案中加句

date_default_timezone_set("Asia/Shanghai");

當然也可以加別的東西啦~

接下來從C層開始說,
C層的檔案都放在/application/controllers/
這裡的檔名xyz就對應著url中的www.example.com/index.php/xyz

這裡插一段,index.php出現在URL中不好看,所以要使用.htaccess 這個東西。先在httpd.conf 中開啟.htaccess 然後去網站根目錄

touch .htaceess
vim .htaccess
#把下面這段粘進去
RewriteEngine on  
RewriteCond $1 !^(index\.php|favicon\.ico|robots\.txt)
RewriteRule ^(.*)$ index.php/$1 [L]

這樣我們就可以直接訪問www.example.com/xyz 當然你也可以利用config檔案中的routes.php來將URL與檔案對應。

CI 的MVC三層都支援一級資料夾,就是說我建一個test.php檔案,我可把它放到/application/controllers/c/test

先給一個DEMO吧,omarhub.huiter.me/c/test
---

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

/**
 * 測試環境 
 */


class Test extends CI_Controller
{        
    public function __construct()
    {
        parent::__construct();    
    }

    public function index()
    {
        $template['content'] = $this->load->view('test_view',$this->template,TRUE);
        $template['css'] = $this->load->view('test_css',$this->template,TRUE);
        $template['js'] = $this->load->view('test_js',$this->template,TRUE);
        $this->load->view('template_view',$template);
    }

}
/* End of file test.php */
/* Location: ./application/controllers/c/test.php */ 

上面給出了對應的test.php檔案。
類名要與檔名一致,且首字母大寫,下劃線什麼的不要亂用了。
繼承於CI_Controller,你也可以自己寫一個Controller 繼承於CI_Controller。

如在/application/core/下建一個Huiter_Controller 做一些自己的定義,然後在config資料夾下的config.php檔案中進行這個設定$config['subclass_prefix'] = 'Huiter_';

進入test.php檔案都會先執行index()
上面那幾行程式碼的意思就是將content\css\js內容都存在了template陣列中,然後傳給template_view,然後輸出。
這裡用到了一個函式$this->load-view('','','');
三個引數第一個是對應著/application/views中的檔案,第二個是傳遞的引數,第三個TRUE表述不直接輸出到頁面上。

如何給index()傳遞引數呢,這一點需要了解CI的URL。

如果我把這上的index()函式定義改為index($word='')
然後訪問.../c/test/hello
那麼在index函式體中就可以用$word接收到引數了。
當然你也可以用$this->input->get();或者$this->input->post();來接收引數。

下面我看講下view層的東西吧。
這裡我依然使用了php與html混寫。 在這裡,你大概只需要知道三件事,

如何拿到C層的變數並輸出
如何寫迴圈
如何寫判斷

首先來看下C層的程式碼:

$template['content'] = $this->load->view('test_view',$this->template,TRUE);
$template['css'] = $this->load->view('test_css',$this->template,TRUE);
$template['js'] = $this->load->view('test_js',$this->template,TRUE);
$this->load->view('template_view',$template);

這裡我將$template傳給了template_view,然後來看一下template_view的程式碼吧。

<!DOCTYPE html>
<html lang="zh-CN">
    <head>
        <meta charset="utf-8">
            <title>By huiter</title>
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <meta name="description" content="">
            <meta name="author" content="huiter">
            <!-- Le styles -->
                <link href="/assets/css/bootstrap.css" rel="stylesheet">
                <?php if ( isset ($css) && ! empty($css)): ?>
                    <?php print $css; ?>
                <?php endif ?>

            <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
            <!--[if lt IE 9]>
            <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
            <![endif]-->
            <!-- Le fav and touch icons -->         
            <link rel="shortcut icon" href="/assets/ico/favicon.ico">
    </head>

    <body>
    <div class="container">

        <?php if ( isset ($content) && ! empty($content)): ?>
            <?php print $content; ?>
        <?php endif ?>

    </div> 
    <!-- /container -->
    <!--[if IE 6]>
    <script src="http://letskillie6.googlecode.com/svn/trunk/letskillie6.zh_CN.pack.js"></script>
    <![endif]-->
        <script src="/assets/js/jquery-1.7.2.min.js"></script>
        <script src="/assets/js/bootstrap.min.js"></script> 
        <script src="/assets/js/application.js"></script>
         <?php if ( isset ($js) && ! empty($js)): ?>
            <?php print $js;?>
        <?php endif ?>  
    </body>
</html>

這裡我們可以看到

<?php if ( isset ($css) && ! empty($css)): ?>
    <?php print $css; ?>
<?php endif ?>

通過這種方式,我們就可以就可以將template陣列中的$css讀出來了。
這裡我們可以看到if語句的基本寫法,下面再給一個for的寫法。
假設我們在C層令

$template['info'] = array("a"=>"Dog","b"=>"Cat","c"=>"Horse");

那麼我們可利用這樣的方式,來獲取值

<?php foreach ($info as $key => $value) :?>
    <span><?php echo $key;?></span> 
    <span><?php echo $value;?></span>       
<?php endforeach;?>

這樣我們就可以得到

<span>a</span>
<span>Dog</span>
<span>b</span>
<span>Cat</span>
<span>c</span>
<span>Horse</span>

知道這些基本就可以通過判斷和迴圈來向html中加入對應的資料,或者輸出哪些html不輸出哪些html 例如

<ul class="nav">
    <li <?php if($page=='home'):?>class="active"<?php endif;?>><a href="/home">寫心情</a></li>  
    <li <?php if($page=='about'):?>class="active"<?php endif;?>><a href="/about">關於</a></li>
    <li class="divider-vertical"></li>
</ul>

這樣就可以我們傳遞進來一個值page來表述當前頁,令navbar中的當前頁的選項為選中狀態,
這一點是通過加一個class="active"實現的。

view層基本介紹到這了。

這時,你就可以把自己寫好的靜態頁拆分下,把公共部件提取成小view,然後用CI框架實現它。

現在,我假設你已經能運用C、V兩層了。 之後,我們就可以來看M層了。

首先跳轉至CI文件

http://codeigniter.org.cn/user_guide/database/index.html

這裡你需要配置個mysql。如果你要玩mongodb的話也是可以的。 其實這個文件你只需關注兩點

如何設定資料庫的相關配置使你能連線上資料庫
怎麼執行各種資料庫操作

關於資料庫配置,文件講的很詳細了。 怎麼執行各種操作呢,建議可以直接去

http://codeigniter.org.cn/user_guide/database/active_record.html

用Active Record 類可以很好地完成各種操作,主要是省去了很多防注入的工作。

給個M層的demo

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Offer_model extends CI_Model {

    function __construct()
    {
        parent::__construct();
    }


    function get_entry_byoffer_url_token($offer_url_token)
    {
        $this->db->select('offer.*,fellow.fellow_url_token,fellow.first_name,fellow.last_name');
        $this->db->from('offer');
        $this->db->join('fellow','offer.fellow_id = fellow.id');
        $this->db->where('offer_url_token',$offer_url_token);

        $query = $this->db->get();
        return $query->row_array();
    }

    function get_entrys_bynothing($number,$time_stamp,$orderby)
    {
        $this->db->select('offer.*,fellow.fellow_url_token,fellow.first_name,fellow.last_name');
        $this->db->from('offer');
        $this->db->join('fellow','offer.fellow_id = fellow.id');
        $this->db->where('offer.created <=',$time_stamp); 
        $this->db->order_by($orderby,'desc');
        $this->db->limit($number);

        $query = $this->db->get();

        return $query->result_array();
    }


    function insert_entry($data)
    { 
        $this->db->insert('offer', $data);
        return mysql_insert_id();
    }


    function delete_entry_byoffer_url_token($offer_url_token)
    {
        $this->db->delete('offer', array('offer_url_token' => $offer_url_token)); 
        return 1;
    }
}

看一看文件就很容易理解這一切。

在C層

    $this->load->model('offer_model','',TRUE);
    $offer = $this->offer_model->get_entry_byoffer_url_token($offer_url_token);

載入剛剛可寫的offer_model,然後呼叫裡面的函式,用$offer獲取。

現在我們知道資料怎麼從C層傳遞給V層,知道怎麼從M層拿資料到C層。 我們基本上完成了對C框架的初步認識。

而對框架的使用,或者說是網站開發的難點就是在於設計。
如何管理好你的這些程式碼,MVC三層就夠了麼?
資料層是不是要分的更細?
asp.net中三層結構BLL\DAL\ENRTY很具有參考意義。
加上每個.aspx檔案都有對應的.cs檔案
相當於一個v 一個c。
BLL層對資料處理成直接可用的資料。
DAL層負責從連線資料庫從資料庫中拿出需要的資料。
ENTRY層負責定義物件。(程式導向,這個無所謂啦。)
其實就相當於在我們CI的MVC三層中加一個層來將從資料庫中拿到的資料進行下處理輸出給C。
所以4層-5層結構還是比較有必要的。

當然也不是分的越細越好,什麼事情都要有度,太多層管理起來就複雜了。
畢竟一切都是為了交付麼。


四、一些探索

1、X層結構

資料庫:mysql,表與物件對應。
M層:從資料庫中拿資料,主要就是寫各種SQL語句,對於需要多表的查詢一律使用join。
API層:仿restful風格。接受資料$in,輸出資料$out,與M層通訊。
C層:頁面跳轉邏輯,從API獲取資料,傳至V層,輸出頁面。
V層:通過資料夾的方式按頁面分隔view檔案,並抽取公共組建放入template資料夾。

封裝API的好處就是測試可以前後端分離。
而且在網站實現方式上有更多的選擇。
你可以用PHP去實現。你也可以Node.js去實現。你也可以去做IOS\Android客戶端。

2、相關配套設定

CI REST:http://github.com/philsturgeon/codeigniter-restserver
Jquery寫的測試工具或使用Chrome外掛POSTMAN
新浪SAE(免費。。。)

有了這些就可以搞一個在Internet上的網站了。

3、其他的東西

(1)好看的網站模版獲取:365psd.com, onepagelove.com, themeforest.net
(2)node.js less jade coffeescript backbone (3)zombie.js:記憶體型瀏覽器 。。。

相關文章