如何水水地写一个网站。(草稿)
这篇将介绍用比较简单的方式来写一个网站
一、语言问题
如果你是选择了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:内存型浏览器
。。。
标题干嘛还带句号?
另外Django、CodeIgniter应该写规范嘛。
网址干嘛用代码样式,而且没有链接?
Twitter那个框架拼写错了,是Bootstrap。