仓酷云

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 1541|回复: 19
打印 上一主题 下一主题

[学习教程] PHP编程:用PHP4 和 PostgreSQL 构建一个电子商务...

[复制链接]
谁可相欹 该用户已被删除
跳转到指定楼层
楼主
发表于 2015-2-4 00:09:20 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
不断巩固,摸透大部分PHP常用函数,并可理解OOP,MYSQL优化,以及模板电子商务   本文经由过程一个复杂的web 使用,演示了 PHP 和 PostgresSQL 在电子商务中的使用。

不久之前,假如要架构一个严厉的Web使用的话,意味着购置价钱不菲的Cold Fusion 允许,和一个贸易的数据库办事法式像Sybase 加上Sun 办事器。侥幸的是,如许的日子一去不复返了。跟着日渐成熟的收费数据库市场和Apache 利用者的大批增加,一些替换产物已具有相当,乃至超越了这些专有软件的才能。

对照好的开放源码软件的一种是 PHP,一个很像Perl 的剧本言语,和PostgreSQL,一个很壮大的面向对象的数据库。假如把二者联合起来的话,你可以设计从复杂的留言簿到一个伟大的基于Web 的财政软件。PHP 供应大脑而Postgres 供应兴旺的肌肉。

上面引见一个很根基的 PHP 购物车和库存使用,充实使用 Postgres 的事务功效。源码推渌柿峡梢源?PHPBuilder.com 下载。

起首要提到的是使用法式的布局,在我的PHP Web 使用中,我老是起首设置一个综合库,网站的每个页面城市用到它,取名叫common.php 寄存在include 目次。

这个库会处置平常义务,例如数据库毗连,用户判别,站点的头部/尾部文件等。把这些函数放在一个中央,咱们的使用看上去很洁净,轻易保护。

表一:示范的库代码

common.php:
<?php

//毗连 postgres 数据库
$conn=pg_pconnect("user=tim dbname=db_example");

//看毗连是不是胜利
if (!$conn) {
//假如掉败则呈报失足
echo pg_errormessage($conn);
exit;
}

//站点的头文件

function site_header ($title) {
return '<HTML>
<HEAD>
<TITLE>'.$title.'</TITLE>
</HEAD>
<BODY>';
}

// 页面开头的 HTML 代码

function site_footer () {

return '</BODY></HTML>';

}

//一个复杂的查询履行函数,用来削减代码

function query($sql) {
global $conn;
return pg_exec($conn,$sql);
}

//让每个页面主动启动session或保留 session 形态

session_start();

?>


因而,咱们的第一个版本的库已可以用了,它毗连数据库,供应了复杂的 HTML
代码。

咱们站点上每个页面都包含:

<?php<n>

require ($DOCUMENT_ROOT.'/include/common.php');

echo site_header('示范页面');

/*
页面逻辑处置
*/

echo site_footer();

?>

普通说来,在构建使用法式时,把逻辑和实践的暗示(在咱们这里就是HTML)分隔是很明智的。因而,我把逻辑放到函数外面。然而PHP 利用函数挪用的办法,弱点是没有尺度的失足处置进程,假如函数外部有错的话,呼唤函数的法式不克不及把把毛病信息传递给用户。在其他的言语,例如Java 外面,你可使用try/catch语句来处置。

我的处理举措是,每一个函数老是前往 true 或 false ,设置一个$feedback全局变量,如许的话,了局就能够测试。如今有一个叫做PEAR (http://pear.php.net/) 的项目在做尺度化毛病处置和数据库存取的勉力,
然而到今朝为止,还不克不及不乱运转。

上面是一个利用我的 true/false 办法挪用函数的例子:

<?php

$result=function_call_name();

if (!$result) {
//显示毛病
echo $feedback;
} else {
//没有毛病,持续
}

?>

好了,如今让咱们入手下手想一想购物车吧! 咱们需求一些根基的数据布局存储购物车的数据。例如,咱们需求一个库存数据库列出物品名字,部件号码,价钱和数目,同时,咱们
还需求纪录顾客购置的物品......太庞杂了,就写这些吧。

表2、购物车数据布局

Cart.sql:

# 创立一个按次表用来发生顾客号码。
# 每一个id 之间用随便的一个数字分隔,以防他人猜想购物车号码。
create sequence seq_customer_id increment 26 start 1;

create table customers (
customer_id int not null default 0 primary key,
name text,
address text,
credit_card text,
total_order MONEY DEFAULT '{CONTENT}.00'
);

create table cart_items (
cart_item serial,
customer_id int,
part_number int,
quantity int
);

create index idx_cart_customer on cart_items(customer_id);

create table item_inventory (
part_number serial,
name text,
price float,
inventory int
);


这个布局给咱们一个根基的购物车,为了标准数据库形式,我创立一个自力的表,用于列出顾客的购物车里的内容。如许,让顾客的购物车可以有多项物品,而且可以很轻易
地和库存数据库毗连。

如今咱们需求思索桓鲈谙呱痰甑母髦止δ芰恕R桓鲎罨镜墓δ芫褪侨〉靡徊抗何锍担道锾砑游锲罚缓蠼嵴恕5比灰桓鍪导什僮鞯脑谙呱痰辏剐枰芏喙δ埽皲?物品,调剂数目等。这些就等你本人来完成了。

我从一个复杂的生成一个顾客的功效入手下手,一切这些其实就是在列队的顾客中获得下一个顾客的材料,拔出顾客表,把顾客号码在PHP4 内置的session 办理中注册。

表3、创立一个新顾客
<?php

function cart_new() {

global $conn, $customer_id, $feedback;

// 启动一个事务
query("BEGIN WORK");

//查询下一个顾客号码
$res=query("SELECT nextval('seq_customer_id')");

//反省毛病
if (!$res || pg_numrows($res)<1) {
$feedback .= pg_errormessage($conn);
$feedback .= ' Error - Database didn't return next value ';
query("ROLLBACK");
return false;
} else {
$customer_id=pg_result($res,0,0);

// 挂号到 session
session_register('customer_id');

// 拔出新顾客
$res=query("INSERT INTO customers (customer_id)
VALUES ('$customer_id')");

//反省毛病
if (!$res || pg_cmdtuples($res)<1) {
$feedback .= pg_errormessage($conn);
$feedback .= ' Error - couldn't insert new customer row ';
query("ROLLBACK");
return false;
} else {
//commit this transaction
query("COMMIT");
return true;
}
}
}

?>

这段代码对照长,固然我不是很喜好,然而它演示了如何准确入手下手和停止Postgres 的事务和如何反省查询语句的毛病。我要在一切的代码用到一样的毛病监测法式,我想,你也应当如斯。

需求企图好假如查询失足的处置举措,你是直接终止法式呢?仍是从头运转查询语句,抑或持续履行,就当甚么也没有产生?细心思索每种选择的了局。例如,假如不克不及失掉下一个顾客的customer_id ,那末,创立新顾客的纪录也就泡汤,接上去就是不克不及更新她的地址,不克不及往购物车里添加物品,对吧?

如今,咱们看看添加物品的进程,这个步调绝对对照轻易,在添加物品之前,要先反省物品是不是在数据库中。如许对照平安,由于物品号码来自阅读器,能够被改动。一旦晓得物品存在,咱们就可以测试它是不是已在购物车里,假如已放入,那末数目加一,而不是别的拔出一行,不然,拔出一条数目为一的纪录到购物车。

表4、添加物品到购物车
<?php

function cart_add_item($item_id,$quantity=1) {
global $customer_id, $feedback, $conn;

$res=query("SELECT * FROM item_inventory WHERE part_number='$item_id'");

if (!$res || pg_numrows($res)<1) {
$feedback .= pg_errormessage($conn);
$feedback .= ' Error-item not found ';
return false;
} else {
// 反省物品是不是放入购物车,假如是,增添数目
// 入手下手事务
query("BEGIN WORK");

$res=query("SELECT * FROM cart_items ".
"WHERE part_number='$item_id' AND customer_id='$customer_id' FOR UPDATE");

if (!$res || pg_numrows($res)<1) {

//假如没有该物品,新拔出一条
$res=query("INSERT INTO cart_items ".
"(customer_id,part_number,quantity)".
"VALUES ($customer_id,$item_id,$quantity)");

if (!$res || pg_cmdtuples($res) < 1) {
$feedback .= pg_errormessage($conn);
$feedback .= ' Error-couldn't insert into cart ';
//虽然没有器材被改动,然而最好仍是回滚事务
query("ROLLBACK");
return false;
} else {
query("COMMIT");
return true;
}
} else {
//购物车中已存在该物品
$res=query("UPDATE cart_items SET quantity = quantity + $quantity ".
"WHERE part_number='$item_id' AND
customer_id='$customer_id'");
if (!$res || pg_cmdtuples($res) < 1) {
$feedback .= pg_errormessage($conn);
$feedback .= ' Error-couldn't increment quantity in cart ';
query("ROLLBACK");
return false;
} else {
// 提交改动,正式更新数据库。
query("COMMIT");
return true;
}
}
}
}

?>


如今咱们能创立新顾客,而且他们添加物品了。咱们如今需求结账,并减失落库存。这一局部是最庞杂的,充实使用了Postgres 的事务功效和先辈锁机制。

咱们用Postgres 的 SELECT...FOR UPDATE 语法作为入手下手,这个语句能无效地对以后选择的行加锁使你能在一个事务里更新并提交改动。

经由过程在一个事务里利用这个语句,你可以包管数据的分歧性。在其他的一些数据库,例如MySQL ,就不克不及锁定指定的数据行,而失掉不准确的数据和没用的库存统计。

这个语句也能使用子查询,别的一个数据库的尺度特征。子查询可让你很省事地把两个查询联合在一同,

锁定行今后,咱们需求依照购物车的物品削减对应的库存量。为简捷起见,咱们对库存不敷不呈报毛病,并把库存变成正数。你可以本人写一个办理页面,检查正数库存的物品,并去订购。

最初,咱们更新顾客表中的信誉卡,购置信息,算计购置金额,撤失落这个顾客的session。

表5、结账,减库存
<?php

function cart_checkout($credit_card,$address,$name) {
global $conn, $customer_id, $feedback;

// 事务入手下手
query("BEGIN WORK");

// 锁住库存表的对应行,用一个复杂的子查询来处置。

$sql="SELECT * FROM item_inventory ".
"WHERE part_number ".
"IN (SELECT part_number FROM cart_items ".
"WHERE customer_id='$customer_id') ".
"FOR UPDATE";
$res=query($sql);

if (!$res || pg_numrows($res)<1) {
$feedback .= pg_errormessage($conn);
$feedback .= ' Error - no items locked ';
query("END WORK");
return false;
} else {

// 库存的某几行已被锁定,从购物车获得物品和数目。
$sql="SELECT part_number,quantity ".
"FROM cart_items ".
"WHERE
customer_id='$customer_id' ".
"ORDER BY part_number DESC";
$res2=query($sql);

if (!$res2 || pg_numrows($res2)<1) {
$feedback .= pg_errormessage($conn);
$feedback .= ' Error - no items in cart ';
query("END WORK");
return false;
} else {
$rows=pg_numrows($res2);

// 更新库存余额

for ($i=0; $i < $rows; $i++) {
// 读取购物车数据
$quantity=pg_result($res2,$i,'quantity');
$item_id=pg_result($res2,$i,'part_number');

$res3=query("UPDATE item_inventory".
"SET inventory =inventory-$quantity ".
"WHERE part_number='$item_id'");

if (!$res3 || pg_cmdtuples($res3) < 1) {
$feedback .= pg_errormessage($conn);
$feedback .= ' Error - updating inventory failed ';
query("ROLLBACK");
return false;
}
}
// 库存更新停止,失掉这个定单的算计金额并更新顾客纪录
$res=query("SELECT sum(cart_items.quantity*item_inventory.price) ".
"FROM cart_items,item_inventory ".
"WHERE cart_items.customer_id='$customer_id' ".
"AND cart_items.part_number=item_inventory.part_number");

if (!$res || pg_numrows($res) < 1) {
//couldn't get order total
$feedback .= pg_errormessage($conn);
$feedback .= ' Error - couldn't get order total ';
query("ROLLBACK");
return false;
} else {
// 更新顾客表
$total=pg_result($res,0,0);
$res=query("UPDATE customers ".
"SET address='$address',name='$name',".
"total_order='$total',credit_card='$credit_card'".
"WHERE customer_id='$customer_id'");

if (!$res || pg_cmdtuples($res) < 1) {
$feedback .= pg_errormessage($conn);
$feedback .= ' Error - updating customer information ';
query("ROLLBACK");
return false;
} else {
// 改动正式失效
query("COMMIT");

// 删除 session
$customer_id=0;
session_destroy();
return true;
}
}
}
}
}

?>

  学习了六个多月PHP了,还是个新手,在这里受到了很多人的帮助,谢谢你们!
精灵巫婆 该用户已被删除
沙发
发表于 2015-2-4 09:29:40 | 只看该作者
这些中手常用的知识,当你把我说的这些关键字都可以熟练运用的时候,你可以选择自己
简单生活 该用户已被删除
板凳
发表于 2015-2-5 15:58:35 | 只看该作者
为了以后维护的方便最好是代码上都加上注释,“予人方便,自己方便”。此外开发文档什么的最好都弄齐全。我觉得这是程序员必备的素质。虽然会消耗点很多的时间。但是确实是非常有必要的。
因胸联盟 该用户已被删除
地板
发表于 2015-2-10 04:16:50 | 只看该作者
当留言板完成的时候,下步可以把做1个单人的blog程序,做为目标,
兰色精灵 该用户已被删除
5#
发表于 2015-2-12 00:18:01 | 只看该作者
你很难利用原理去编写自己的代码。对于php来说,系统的学习我认为还是很重要的,当你有一定理解后,你可你针对某种效果研究,我想那时你不会只是复制代码的水平了。
蒙在股里 该用户已被删除
6#
发表于 2015-3-2 20:30:57 | 只看该作者
学习php的目的往往是为了开发动态网站,phper就业的要求也涵盖了很多。我大致总结为:精通php和mysql
愤怒的大鸟 该用户已被删除
7#
发表于 2015-3-11 06:05:05 | 只看该作者
首先我是坚决反对新手上来就用框架的,因为对底层的东西一点都不了解,造成知识上的真空,会对以后的发展不利。我的观点上手了解下框架就好,代码还是手写。当然啦如果是位别的编程语言的高手的话,这个就另当别论啦。
变相怪杰 该用户已被删除
8#
发表于 2015-3-15 18:46:20 | 只看该作者
我还是推荐用firefox ,配上firebug 插件调试js能省下不受时间。谷歌的浏览器最好也不少用,因为谷歌的大侠们实在是太天才啦,把一些原来的js代码加了一些特效。
第二个灵魂 该用户已被删除
9#
发表于 2015-3-17 10:11:41 | 只看该作者
这些中手常用的知识,当你把我说的这些关键字都可以熟练运用的时候,你可以选择自己
admin 该用户已被删除
10#
发表于 2015-3-22 01:45:28 | 只看该作者
说php的话,首先得提一下数组,开始的时候我是最烦数组的,总是被弄的晕头转向,不过后来呢,我觉得数组里php里最强大的存储方法,所以建议新手们要学好数组。
11#
发表于 2015-3-25 12:05:35 | 只看该作者
对于懒惰的朋友,我推荐php的集成环境xampp或者是wamp。这两个软件安装方便,使用简单。但是我还是强烈建议自己动手搭建开发环境。
不帅 该用户已被删除
12#
发表于 2015-4-3 00:01:07 | 只看该作者
本文当是我的笔记啦,遇到的问题随时填充
冷月葬花魂 该用户已被删除
13#
发表于 2015-4-6 04:09:30 | 只看该作者
有时候汉字的空格也能导致页面出错,所以在写代码的时候,要输入空格最好用引文模式。
活着的死人 该用户已被删除
14#
发表于 2015-4-6 17:16:01 | 只看该作者
要进行开发,搭建环境是首先需要做的事,windows下面我习惯把环境那个安装在C盘下面,因为我配的环境经常出现诡异事件,什么事都没做环境有的时候就不能用啦。
飘飘悠悠 该用户已被删除
15#
发表于 2015-4-12 16:38:03 | 只看该作者
遇到出错的时候,我经常把错误信息直接复制到 google的搜索栏,一般情况都是能搜到结果的,不过有时候会搜出来一大片英文的出来,这时候就得过滤一下,吧中文的弄出来,挨着式方法。
分手快乐 该用户已被删除
16#
发表于 2015-4-15 08:42:55 | 只看该作者
不禁又想起那些说php是草根语言的人,为什么认得差距这么大呢。
老尸 该用户已被删除
17#
发表于 2015-4-21 12:27:13 | 只看该作者
我学习了一段时间后,我发现效果并不好(估计是我自身的问题)。因为一个人的精力总是有限的,同时学习这么多,会导致每个的学习时间都得不到保证。
小女巫 该用户已被删除
18#
发表于 2015-4-21 23:14:14 | 只看该作者
写的比较杂,因为我也是个新手,不当至于大家多多指正。
海妖 该用户已被删除
19#
发表于 2015-4-22 10:22:18 | 只看该作者
要进行开发,搭建环境是首先需要做的事,windows下面我习惯把环境那个安装在C盘下面,因为我配的环境经常出现诡异事件,什么事都没做环境有的时候就不能用啦。
若天明 该用户已被删除
20#
发表于 2015-4-26 12:49:27 | 只看该作者
写js我最烦的就是 ie 和 firefox下同样的代码 结果显示的结果千差万别,还是就是最好不要用遨游去调试,因为有时候遨游是禁用js的,有可能代码是争取结果被遨游折腾的认为是代码写错。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|仓酷云 鄂ICP备14007578号-2

GMT+8, 2024-12-24 01:26

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表