月度归档 2015年5月29日

通过清心醉

WEB开发超级IDE工具 Zend Studio

首先,要说最完整的开发IDE,那肯定是微软的Vistual Studio了。毕竟还有针对于C#、NET等开发。

不过,就以Vistual Studio 2015来说,跑起来会相当的辛苦。

PHP的项目开发,我一直都是在使用Zend Studio 12.0。整齐的视图布局,F3的代码跟踪也做的非常的好。

更主要的是,做WEB开发的,也会想把WEB封装到一个简单的APP里。别小看了ZEND,一样可以集成JAVA/C/C++/APP等开发。

首先说下ZEND 安装Android的步骤吧,其实很简单,但请确保你是可以翻墙到谷歌的

点击 Help菜单 -> Install New Software… ?
点击 ?Add… ?,输入地址:
https://dl-ssl.google.com/android/eclipse/

如果您的ZNED是汉化过的,我想你能知道放在哪里了。

然后就是独立下载个对应版本的JAVA,

新增2个::
变量名: JAVA_HOME
变量值: C:\Program Files\Java\jdk1.8.0_45

变量名: CLASSPATH
变量值: .;%JAVA_HOME%\lib\tools.jar

然后修改PATH变量,最前面加入以下变量值:
%JAVA_HOME%\bin;

/*
注释::
JAVA_HOME变量
JDK的安装路径,这个环境变量本身不存在,需要创建,创建完则可以利用%JAVA_HOME%作为统一引用路径,其值为:jdk在你电脑上的安装路径。

CLASSPATH变量
用于编译时JAVA类的路径,注意这里设置的是两个值,(.;)表示的是JVM先搜索当前目录。其值为:.;%JAVA_HOME%\lib\tools.jar。

PATH变量
系统默认已经存在PATH属性,可直接编辑。作用是用于配置路径,简化命令的输入
其值为:%JAVA_HOME%\bin
*/

这样,你就可以创建APP的项目了。

至于模拟器等等,也可以找到对应的URL来进行安装。

通过清心醉

Ecshop解决产品详细页图片模糊的问题

电脑端的打开了产品的页面,产品的图片默认是很模糊的,没有去认真的追踪源码里的获取参数.不过应该就是缩略图强制放大.

解决的方法很简单.修改goods.dwt产品模板

搜索 $goods.goods_img  这是默认显示的第一张图片

如果需要查看图片的位置可以追溯下源代码,看SQL进行处理的时候返回的路径

代码先不管了,修改$goods.goods_img为$goods.original_img,就可以解决问题.

因为每个人使用的主题不一样,代码位置都不一样,但$goods.good_img一般都会继续使用,除非部分主题开发者修改了别的命名.

通过清心醉

感谢-有你

数年前,你我相逢不相识;

几年后,你我争执两边倒;

谁对谁错已然没有意义。

承受过无数的压力;

受到过无数的鄙视。

因为我还有我自己的梦想,

也不忘对您的承诺。

梦想圆就已三载有余;

真挚的你现在在哪里?

人若有才,昔日之人或许借才补脸。厚脸之人,请饶道而行。

我的毕生辉煌,成功的背后,感谢一路有你 – 缘。

 

通过清心醉

表单提交的基础JS/PHP双重验证

首先得有个表单:

<form action=”” method=”post”>
<table align=”center” width=”80%” border=”1″ cellpadding=”2″ cellspacing=”0″>
<tr><td>商家用户名</td><td><font color=”red”><?php echo $this->user[‘user’]?>(不可修改)</font></td>
<td>商家店名</td><td><font color=”red”><?php echo $this->user[‘name’]?>(不可修改)</font></td></tr>

<tr>
<td>商家地址</td><td><input type=”text” name=”add” value=”<?php echo $this->user[‘add’]?>” style=”width:100%” id=”qxz2″ onchange=”qxzadd()” maxlength=”20″/></td>
<td>商家邮箱</td><td><input type=”text” name=”mail” value=”<?php echo $this->user[‘mail’]?>” id=”qxz1″ onchange=”qxzemail()”style=”width:100%” maxlength=”30″/></td>
</tr>

<tr>
<td>商家手机</td><td><input type=”text” name=”phone” value=”<?php echo $this->user[‘phone’]?>” id=”qxz0″ onchange=”qxzphone()” style=”width:100%” maxlength=”11″/></td>
</td><td>商家热线</td><td><input type=”text” name=”tel” value=”<?php echo $this->user[‘tel’]?>” id=”qxz3″ onchange=”qxztel()” style=”width:100%” maxlength=”18″/></td>
</tr>

<tr>
<td>商家密码</td><td><input type=”text” name=”password” value=”” id=”qxz4″ onchange=”qxzpass()” style=”width:100%” maxlength=”16″ placeholder=”默认不修改.只允许英文和数字”/></td>
<td>修改资料</td><td><center><input type=”submit” value=”修改” onclick=”post_sys()” style=”width:100%”/></center></td>
</tr>
</table>
</form>

里面的PHP值不管了 就是作者MVC设置的

然后对每个环节进行JS控制:

function qxzphone() //实时检测手机号码
{
var x=document.getElementById(“qxz0”).value; //获取表单ID=PHONE的VALUE数值
if(isNaN(x)) //判断是否为数字
{
alert(“请输入11位数字的手机号”);
document.getElementById(“qxz0″).value=””; //重写为空
return false;
}
else
{
if(x.length!=11) //判断数值长度
{
alert(“您输入的手机号不足11位数”);
document.getElementById(“qxz0″).value=””; //重写为空
return false;
}
else
{
var mreg = /^(((13[0-9]{1})|159|153|158)+\d{8})$/; //正则表达式判断手机号的合法性
if(!mreg.test(x)) //用正则判断phone的值 ,如果是11位数但号码是乱写的
{
alert(“您输入的手机号有误”);
document.getElementById(“qxz0″).value=””; //重写为空
return false;
}
else
{
//alert(‘正确’);
return true;
}
}
}
}
function qxzemail() //邮箱格式判断
{
var mail=document.getElementById(“qxz1”).value;
var mreg=/^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/;
if(!mreg.test(mail))
{
alert(“邮箱格式不正确!”);
document.getElementById(“qxz1″).value=””; //重写为空
return false;
}
else
{
//alert(“OKOK”);
return true;
}
}

function qxzadd()
{
var add=document.getElementById(“qxz2”).value;
if(add.length<1)
{
alert(“商家地址为空!”);
document.getElementById(“qxz2″).value=””; //重写为空
return false;
}
else if(add.length<4)
{
alert(“地址长度小于4”);
document.getElementById(“qxz2″).value=””; //重写为空
return false;
}
else
{
return true;
}
}

function qxztel()
{
var tel=document.getElementById(“qxz3”).value;
var mreg=/^((0\d{2,3})-)(\d{7,8})(-(\d{2,3,4}))?$/;
//正则表达式,区号0+(2-3位)-号码(7-8位)-分机(3-4位)
var mreg1=/^((0\d{2,3})-)(\d{7,8})?$/; //无分机号码判断
if(tel.length==null||tel.length==undefined||tel.length<1) //如果为空,表示没有固话,直接返回真结束
{
//alert(“商家固定电话为空”);
return true;
}
else if(!mreg1.test(tel)) //如果判断无分机号码不正确
{
if(!mreg.test(tel)) //如果有分机号码但格式不正确
{
alert(“号码不正确!”);
document.getElementById(“qxz3″).value=””; //重写为空return false;
}
else
{
//alert(“号码正确,并且是带有分机号码的!”);
return true;
}
}
else
{
return true;
}
}

function qxzpass()
{
var pass=document.getElementById(“qxz4″).value;
var mage = RegExp(/[(\ )(\~)(\!)(\@)(\#)(\$)(\%)(\^)(\&)(\*)(\()(\))(\-)(\_)(\+)(\=)(\[)(\])(\{)(\})(\|)(\\)(\;)(\:)(\’)(\”)(\,)(\.)(\/)(\<)(\>)(\?)(\)]+/);
//密码禁止非法字符判断
var zhcn=/.*[\u4e00-\u9fa5]+.*$/;//判断是否包含有中文
if(pass.length==null||pass.length==undefined||pass.length<1)
{
return true; //密码为空
}
else if(pass.length<8||pass.length>16)
{
alert(“密码必须大于8小于16”);
document.getElementById(“qxz4″).value=””; //重写为空
return false;
}
else
{
if(mage.test(pass))
{
alert(“包含特殊字符,密码只能为数字/英文 \n 取消修改密码”);
document.getElementById(“qxz4″).value=””; //重写为空
return false;
}
else if(zhcn.test(pass))
{
alert(“包含中文字符,密码只能为数字/英文 \n 取消修改密码”);
document.getElementById(“qxz4″).value=””; //重写为空
return false;
}
else
{
return true;
}

}
}

function post_sys() //提交数据按钮
{
if(qxzphone()==true&&qxzadd()==true&&qxzemail()==true&&qxztel()==true&&qxzpass()==true) //如果5个参数的判断结果都为真
{
var qxz=new Array();//定义数组
for(i=0;i<5;i++)
{
qxz[i]=document.getElementById(“qxz”+i).value; //循环获取用户输入的数据到数组
}
//在这里循环获取的数据会用在变量str中
/*
for (i=0;i<qxz.length;i++) //测试循环输出数据
{
document.write(qxz[i] + “<br />”);
}
*/
//开始请求AJAX发送数据包!
var url=”/shangjia/index.php?controller=user&action=userform”; //请求的URL接收方法为user控制器的userform方法
var str=”phone=”+qxz[0]+”&email=”+qxz[1]+”&add=”+qxz[2]+”&tel=”+qxz[3]+”&pass=”+qxz[4]; //创建POST数据的字符串连接
var ajax=false;
//开始初始化XMLHttpRequest对象开始
if(window.XMLHttpRequest) { //Mozilla 浏览器
ajax = new XMLHttpRequest();
if (ajax.overrideMimeType) {//设置MiME类别
ajax.overrideMimeType(“text/xml”);
}
}
else if (window.ActiveXObject) { // IE浏览器
try {
ajax = new ActiveXObject(“Msxml2.XMLHTTP”);
} catch (e) {
try {
ajax = new ActiveXObject(“Microsoft.XMLHTTP”);
} catch (e) {}
}
}
if (!ajax) { // 异常,创建对象实例失败
window.alert(“不能创建XMLHttpRequest对象实例.”);
return false;
}
//对象创建结束
//正式开始数据请求!!
ajax.open(“POST”, url, true); //打开POST请求
ajax.setRequestHeader(“cache-control”,”no-cache”); //禁止缓存
ajax.setRequestHeader(“contentType”,”text/html;charset=uft-8″) //指定发送的编码
ajax.setRequestHeader(“Content-Type”,”application/x-www-form-urlencoded”); //POST请求头
ajax.send(str); //开始发送POST数据
ajax.onreadystatechange = function()
{
//如果执行状态成功,那么就把返回信息写到指定的层里
if (ajax.readyState == 4 && ajax.status == 200) {
//msg.innerHTML = ajax.responseText;
//alert(“数据POST成功!”);
alert(ajax.responseText);
}
}
//数据请求完毕,数据在方法里执行.
}
else
{
alert(“请确认是否有数值填写错误!”);
}
}

请求的URL是MVC的

在控制器的方法里,还有多个方法进行判断

/*
* 判断邮件类型,需要一个参数为判断的变量值
*/
protected function email_type($email) #判断邮件格式
{
if(preg_match(“/^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/”,$email))
{
return true; #返回真
}
else
{
return false; #返回假
}
}

/*
* 判断手机号码类型,参数为判断的手机号码
*/
protected function phone_type($phone)
{
if(preg_match(“/^(((13[0-9]{1})|159|153|158)+\d{8})$/”,$phone))
{
return true;
}
else
{
return false;
}
}

/*
* 判断电话号码格式
*/
protected function tel_type($tel)
{
if (!preg_match(“/^((0\d{2,3})-)(\d{7,8})?$/”,$tel)) //如果没有分机号码也不正确
{
if(!preg_match(“/^((0\d{2,3})-)(\d{7,8})(-(\d{2,3,4}))?$/”, $tel)) //如果有分机号码还是不正确
{
return false;
}
else
{ //有分机号码的.号码正确
return true;
}
return false;
}
else
{
return true;
}
}

/*
* 商家地址字符长度判断
* 第一个参数为商家地址,第二个为最少字数,默认为4个
*/
protected function add_type($add,$num=4)
{
$o=mb_strlen($add,’UTF8′); //获取商家长度
if ($o<$num)
{
return false;
}
else
{
return true;
}
}

protected function pass_type($pass,$num=8)
{
if(preg_match(“/[\’.,:;*?~`!@#$%^&+=)(<>{}]|\]|\[|\/|\\\|\”|\|/”,$pass)) //判断密码里是否有包含特殊字符
{
return false;
}
else if(preg_match(“/[\x7f-\xff]/”, $pass))
{
return false;
}
else
{
return true;
}
}

这样在接收的页面,就可以进行方法判断了,只要一个不符合要求,就不写入数据库

至于密码这一块,符号的定义可以自由截取部分,比如逗号是可以使用的等等.

使用JS/PHP双重判断的好处就是,别人恶意提交了AJAX请求,一样会面临被攻击的危险.

 

通过清心醉

wordpress全站使用新窗口打开链接

WordPress默认使用的是当前的窗口打开,说真的,有时候看久了真的感觉很想吐。

分类/文章页/页面/图片都是

如果一个个改的话,很麻烦

这有个超级变态的方法。

找到当前模板的header.php头文件。

<base target=”_blank”>

写上这个 全部都是新窗口打开。

通过清心醉

Ecshop控制搜索/分类里的产品显示数量

其实很简单,$size的值修改下

系统有判断是否为数字等等,如果不是强制转化为10

直接修改$size=12就可以了。

搜索显示数量修改文件/search.php 245行

分类显示数量修改文件/category.php  49行

通过清心醉

Ecshop二次开发-增加自定义属性的搜索

首先把作者修改好了的贡献出来,需要的朋友请自行下载(放心没写后门)

Ecshop搜索强化-增加自定义属性搜索

ECSHOP前台可按商品名称关键词、商品货号关键词等查找商品,但不能按特点货号查找。特点货号是ECSHOP特点库存的仅有识别号,树立特点库存后,特点货号保存在products表中,下面分析怎么开发按特点货号关键词查找。
search.php

$keywords .= “(goods_name LIKE ‘%$val%’ OR goods_sn LIKE ‘%$val%’ OR keywords LIKE ‘%$val%’ $sc_dsad)”;
修改为
$keywords .= “(goods_name LIKE ‘%$val%’ OR goods_sn LIKE ‘%$val%’ OR product_sn LIKE ‘%$val%’ OR keywords LIKE ‘%$val%’ $sc_dsad)”;

ECSHOP默认使用的是goods_name\goods_sn\keywords。其实要想搜索出来的产品条件更多,可以goods_brief产品描述等,不过这样会影响速度,不建议。上面修改的SQL语句中增加了product_sn特点货号关键字的搜索

 

$sql = “SELECT COUNT(*) FROM ” .$ecs->table(‘goods’). ” AS g “.
“WHERE g.is_delete = 0 AND g.is_on_sale = 1 AND g.is_alone_sale = 1 $attr_in “.
“AND (( 1 ” . $categories . $keywords . $brand . $min_price . $max_price . $intro . $outstock .” ) “.$tag_where.” )”;
修改为:
$sql = “SELECT COUNT(*) FROM ” .$ecs->table(‘goods’). ” AS g “.
“LEFT JOIN ” . $GLOBALS[‘ecs’]->table(‘products’) . ” AS p “.
“ON g.goods_id = p.goods_id “.
“WHERE g.is_delete = 0 AND g.is_on_sale = 1 AND g.is_alone_sale = 1 $attr_in “.
“AND (( 1 ” . $categories . $keywords . $brand . $min_price . $max_price . $intro . $outstock .” ) “.$tag_where.” )”;

// 取得契合条件的商品总数,SQL语句增加goods表与products表衔接查询。

接下来就是查询产品了,同样要增加goods表与products表链接查询。

$sql = “SELECT g.goods_id, g.goods_name, g.market_price, g.is_new, g.is_best, g.is_hot, g.shop_price AS org_price, “.
“NULL.user_price, g.shop_price * ‘$_SESSION[discount]’) AS shop_price, “.
“g.promote_price, g.promote_start_date, g.promote_end_date, g.goods_thumb, g.goods_img, g.goods_brief, g.goods_type “.
“FROM ” .$ecs->table(‘goods’). ” AS g “.
“LEFT JOIN ” . $GLOBALS[‘ecs’]->table(‘member_price’) . ” AS mp “.
“ON mp.goods_id = g.goods_id AND mp.user_rank = ‘$_SESSION[user_rank]’ “.
“WHERE g.is_delete = 0 AND g.is_on_sale = 1 AND g.is_alone_sale = 1 $attr_in “.
“AND (( 1 ” . $categories . $keywords . $brand . $min_price . $max_price . $intro . $outstock . ” ) “.$tag_where.” ) ” .
“ORDER BY $sort $order”;
修改为:
/* 查询商品 */
$sql = “SELECT g.goods_id, g.goods_name, g.market_price, g.is_new, g.is_best, g.is_hot, g.shop_price AS org_price, “.
“IFNULL(mp.user_price, g.shop_price * ‘$_SESSION[discount]’) AS shop_price, “.
“g.promote_price, g.promote_start_date, g.promote_end_date, g.goods_thumb, g.goods_img, g.goods_brief, g.goods_type “.
“FROM ” .$ecs->table(‘goods’). ” AS g “.
“LEFT JOIN ” . $GLOBALS[‘ecs’]->table(‘member_price’) . ” AS mp “.
“ON mp.goods_id = g.goods_id AND mp.user_rank = ‘$_SESSION[user_rank]’ “.
“LEFT JOIN ” . $GLOBALS[‘ecs’]->table(‘products’) . ” AS p “.
“ON g.goods_id = p.goods_id “.
“WHERE g.is_delete = 0 AND g.is_on_sale = 1 AND g.is_alone_sale = 1 $attr_in “.
“AND (( 1 ” . $categories . $keywords . $brand . $min_price . $max_price . $intro . $outstock . ” ) “.$tag_where.” ) ” .
“ORDER BY $sort $order”;

到此搜索自定义属性的产品开发完毕。

 

通过清心醉

Ecshop同步手机/邮箱/用户名登陆方法

首先作者提醒下,邮箱关系倒不到,不过考虑到后期肯定也要做个邮箱验证。

而手机是必须要有验证的,否则的话建议在模板里关闭手机注册/修改功能,否则上线之后手机号重复是个很严肃的问题。

言归正转:

修改user.php文件。

ECSHOP登陆的,请求的是该页面

elseif ($action == ‘act_login’) 在这里是请求登陆

当获取了参数之后是执行if ($user->login($username, $password,isset($_POST[‘remember’])))里的

所以我们需要写在这之前

首先我们在文件结尾处写个判断电话号码的正则表达式:

function is_telephone($phone)
{
$phones= “/^13[0-9]{1}[0-9]{8}$|15[0-9]{1}[0-9]{8}$|18[0-9]{1}[0-9]{8}$/”;
if (preg_match($phones, $phone))
{
return true;
}
else
{
return false;
}
}

接下来:

if(is_email($username)) //首先判断是否符合邮件
{
$sql =”select user_name from “.$ecs->table(‘users’).” where email='”.$username.”‘”; //SQL语句
$username_e = $db->getOne($sql); //如果有存在的数据赋值给变量
if($username_e) //判断前一句的返回值
{
$username=$username_e; //重新赋值
}
}
if(is_telephone($username))
{
$sql =”select user_name from “.$ecs->table(‘users’).” where mobile_phone='”.$username.”‘”;
$username_e = $db->getOne($sql);
if($username_e)
{
$username=$username_e;
}
}
 if ($user->login($username, $password,isset($_POST[‘remember’]))) 必须写在该语句前,才能很好的判断。因为会给$username重新赋值

这样就可以完整的多登陆方式了!

通过清心醉

Ecshop二次开发-增加立即结算

Ecshop默认的购物流程是先增加到购物车,然后再执行结算生成订单,如果客户看到了产品想直接购买,就会多个无趣的购物车过程。

修改方法网上也有,但可能说的不是很明细。而且该方法也会有争议的地方。

比如用户直接购买但未完成,然后返回主页什么的,购物车是否要清空重新计算,这个得看个人的需求。作者默认是不修改购物车的内容。

好了。直接说开发过程。

产品详细页在goods.dwt文件里

约337行(各人主题不一样。你可以搜索javascript:addToCart({$goods.goods_id}))

这是直接加入购物车的,我们在这下一行新增一个立即计算的URL

<a href=”javascript:Clearing({$goods.goods_id})”>立即结算</a>

点击时触发Clearing方法,参数为产品的ID,这时候我们的触发按钮就做好了。在写JS以前我们先来看JS的文件体:

 

 

/js/common.js文件

function addToCart(goodsId, parentId)  有这么一个方法是AJAX的POST请求,里面有个Ajax.call()方法在transport.js文件里有写请求方法等。

在该方法里有个Ajax.call(….. addToCartResponse, ‘POST’, ‘JSON’)  //这里的addToCartResponse就是回调方法了

我们复制addToCart和addToCartResponse这两个方法

重新命名为Cliaring和Cliaringreturn  //第一个为AJAX请求,第二个为回调

修改Cliaring里的Ajax.call请求的回调URL::

Ajax.call(….. addToCartResponse, ‘POST’, ‘JSON’)为Ajax.call(….. Cliaringreturn, ‘POST’, ‘JSON’)

接下来,我们修改Cliaringreturn的回调里的一个变量URL

var cart_url = ‘flow.php?step=checkout‘;  修改为var cart_url = ‘flow.php?step=cart‘;

到此修改就完毕了。

针对mobile手机端的话,其实是大同小异,只是mobile开发者使用了MVC的结构,这时候我们一样可以借鉴。

 

通过清心醉

PHP过时了吗

作为一名PHP后端程序员,掌握了PHP及MYSQL等数据库的操作语法之后。

很多人都说,前端学学,DIV+CSS/JAVASCRIPT,不然哪算是一个完整的WEB开发人员。

就我来说,我根本所谓的DIV+CSS,更不懂JAVASCRIPT。

可有点编程经验的人来说,掌握其语法,结构及使用规范,没什么大同小异的。再说了,后端不只是PHP一个,还有MYSQL,LINUX服务器的搭配等等。

现在WEB后端来说,莫过于JSP和PHP了。PHP难道真就过时了?

都说JSP安全,难道PHP不安全吗?

都说JSP都是企业级应用的,速度快。难道PHP跑的慢吗?对于WINDWOS/LINUX平台的安全先不说。虽然JSP是编译型的语言。JSP基本跑与WINDOWS平台,当然现在也可以在LINUX平台跑了,可PHP默认就在LINUX上得到了支持。数据库方面,JSP通常使用ORACLE,都说企业级嘛。那我真的很想打死那些制造谣言的人,你们知道PHP的PDO吗?要想跑的快,PHP一样可以得到速度上的支持。

作者认为,那些脑残的在讨论熟好熟坏之前,是否应该考虑下开发所面对的使用对象?

你会为了做个简单的博客,用JSP+ORACLE吗?就为所谓的速度快?支付数据库的使用费用?或者说,你使用破解等方法?

PHP过时,那就奇怪,FACEBOOK怎么还是用PHP,一家那么有钱的大公司了,怎么不用JSP?PHP的ZEND公司难道是摆设?

还有一堆堆国内的个人小网站,怎么都还在用PHP?因为PHP开源、免费。配合免费的MYSQL。再配合免费开源的Linux CentOS平台,哪个敢说不是投资最小化的一种方法?(你有钱你可以全部使用企业级应用,作者和土豪永远不可能成为朋友)

说PHP过时了的,好好翻墙去看看FACEBOOK,看那人气流量,PHP+MYSQL是否可以支撑。关键还是技术的问题。

PHP、JAVA、C等都是一种语言而已,面向的使用人群不同,各有优势。

作者最近都在对ECSHOP进行二次开发,感觉,PHP的确很弱。

但弱的不是PHP本身,而是开发的人想的没那么周到,不然他们怎么商业化?

不能因为一个PHP写的程序感觉弱就说该语言弱。C呢?很多都转C++、NET了。现在学C,谁敢说没出路?

PHP虽然是弱语言,那是因为你没见过什么叫PHP开发出来的强大程序。

作者接触过MAGENCO和PRESTASHOP这两款国外的开源电子商城。还接触过国内的ECSHOP商城。特别是MAGENTO,PHP的基础不说,看看MAGNETO(正确来说是ZEND的)EAV模型,做的如何?数据结构又如何?安全性能又如何? 作者说的还是社区版的,有钱的下个企业级的,看看人家企业级的又是如何?放网站上谁会信你这是PHP写的?

作者没有排挤JSP的意思,只是想说,不同的用户型,用不同的开发体,没有谁好谁不好。 只能说你懂不懂。

 

通过清心醉

Ecshop-mobile-网银支付开发

如果是针对电脑端的,系统默认已经封装了很多的方法可以使用。

针对mobile端:ECTouch

首先我们在创建订单的时候,系统会循环输出数据库里存在的支付方式,因为手机端不同于电脑端,ECTouch自己有创建一个表:

先说说流程,如果订单被创建,选择的是网银支付,那么就会有个表单POST到网银支付网关

请求的URL地址为:pay3.chinabank.com.cn/PayGate

由于公司的网关支付接口刚申请,只能使用测试阶段,测试后发现跳转过后的其实是电脑端的页面,说明应该还有其他的手机端请求,等公司的申请下来了再来公布应该请求的URL地址

首先我们应该有个语言包wangyin.php文件:

<?php
if (! defined(‘IN_ECTOUCH’)) {
die(‘非法访问’);
}
global $_LANG;
$_LANG[‘wangyin’] = ‘网银支付’;
$_LANG[‘wangyin_desc’] = ‘网银在线支付’;
$_LANG[‘wangyin_account’] = ‘网银商家帐号’;
$_LANG[‘wangyin_key’] = ‘网银KEY’;
$_LANG[‘pay_button’] = ‘立即使用网银在线支付’;
?>

在language/zh_cn/目录(注是插件里)

然后我们来看核心的文件wangyin.php:panment目录里

<?php
/*
* 网银支付插件手机端
* 作者:清心醉
* 更多开发请参考 http://www.qingxinzui.com/
*
* 参数说明:
* 由于使用的是手机端的开发
* 目录应该为:
* mobile/pulgins/payment/
*
* 更多需要在后台显示出来的参数,可以在语言包里增加
*/
if (!defined(‘IN_ECTOUCH’))
{
die(‘非法访问!’);
}
$payment_lang = ROOT_PATH . ‘plugins/payment/language/’ . C(‘lang’) . ‘/’ . basename(__FILE__);

if (file_exists($payment_lang))
{
include_once ($payment_lang);
L($_LANG);
}

if (isset($set_modules) && $set_modules == TRUE)
{
$i = isset($modules) ? count($modules) : 0;
$modules[$i][‘code’] = basename(__FILE__, ‘.php’);
$modules[$i][‘desc’] = ‘wangyin_desc’;
$modules[$i][‘is_cod’] = ‘0’;
$modules[$i][‘is_online’] = ‘1’;
$modules[$i][‘pay_fee’] = ‘0’;
$modules[$i][‘author’] = ‘<a href=”http://www.qingxinzui.com”  target=”_black”>清心醉</a>’;
$modules[$i][‘website’] = ‘http://www.qingxinzui.com/’;
$modules[$i][‘version’] = ‘1.0.0’;
$modules[$i][‘config’] = array(
array(‘name’ => ‘wangyin_account’, ‘type’ => ‘text’, ‘value’ => ‘1001’),
array(‘name’ => ‘wangyin_key’, ‘type’ => ‘text’, ‘value’ => ‘test’),
);
return;
}

class wangyin
{
function wangyin()
{
}

function __construct()
{
$this->wangyin();
}
function get_code($order, $payment)
{
$data_vid = trim($payment[‘wangyin_account’]);
$data_vpaykey = trim($payment[‘wangyin_key’]);
$data_orderid = $order[‘order_sn’];
$data_vamount = $order[‘order_amount’];
$data_vmoneytype = ‘CNY’;
$data_vreturnurl = return_url(basename(__FILE__, ‘.php’));
if (empty($order[‘order_id’]))
{
$remark1 = “qingxinzui”;
}
else
{
$remark1 = ”;
}

$MD5KEY =$data_vamount.$data_vmoneytype.$data_orderid.$data_vid.$data_vreturnurl.$data_vpaykey;
/*
* 在这里特别要注意拼接的顺序
*/
$MD5KEY = strtoupper(md5($MD5KEY));
//MD5转大写

$def_url = ‘<br /><form style=”text-align:center;” method=”post” name=”E_FORM” action=”https://pay3.chinabank.com.cn/PayGate” target=”_blank”>’;
//请求URL,根据多种不同的版本action的参数不同
$def_url .= “<input type=HIDDEN name=’v_mid’ value='”.$data_vid.”‘>”;
$def_url .= “<input type=HIDDEN name=’v_oid’ value='”.$data_orderid.”‘>”;
$def_url .= “<input type=HIDDEN name=’v_amount’ value='”.$data_vamount.”‘>”;
$def_url .= “<input type=HIDDEN name=’v_moneytype’ value='”.$data_vmoneytype.”‘>”;
$def_url .= “<input type=HIDDEN name=’v_url’ value='”.$data_vreturnurl.”‘>”;
$def_url .= “<input type=HIDDEN name=’v_md5info’ value='”.$MD5KEY.”‘>”;
$def_url .= “<input type=HIDDEN name=’remark1’ value='”.$remark1.”‘>”;
$def_url .= “<input type=submit value=’转到网银支付’>”;
$def_url .= “</form>”;
return $def_url;
}

function callback($data)
{
if (!empty($_GET))
{
$payment = model(‘Payment’)->get_payment($data[‘code’]);

$v_oid = trim($_POST[‘v_oid’]);
$v_pmode = trim($_POST[‘v_pmode’]);
$v_pstatus = trim($_POST[‘v_pstatus’]);
$v_pstring = trim($_POST[‘v_pstring’]);
$v_amount = trim($_POST[‘v_amount’]);
$v_moneytype = trim($_POST[‘v_moneytype’]);
$remark1 = trim($_POST[‘remark1’ ]);
$v_md5str = trim($_POST[‘v_md5str’ ]);

$key= $payment[‘wangyin_key’];
$md5string=strtoupper(md5($v_oid.$v_pstatus.$v_amount.$v_moneytype.$key));

if ($v_md5str==$md5string)
{
if ($v_pstatus == ’20’)
{
if ($remark1 == ‘qingxinzui’)
{
$v_oid = model(‘Payment’)->get_order_id_by_sn($v_oid, “true”);
}
else
{
$v_oid = model(‘Payment’)->get_order_id_by_sn($v_oid);
}
model(‘Payment’)->order_paid($v_oid, 2);
return true;
}
}
else
{
return false;
}
}
else
{
return false;
}

}
public function notify()
{
$this->callback();
}

}

?>

在这里特别鄙视下某些群组,一个简单的方法,硬是没人和你说

事实也证明,自学是最好的能力的象征。

如有不懂的或者支付的开发,请留言

或者邮件至:admin@qingxinzui.com

通过清心醉

Ecshop邮件设置

25端的话没去试,作者使用的是465的SSL

由于ECSHOP对PHP的要求版本在5.3以内,该版本内的PHP里默认是不打开openssl扩展的

需要修改两个文件:

httpd.conf文件打开

mod_ssl.so

php.ini文件打开

extension=php_openssl.dll

 

然后重启apache即可.

 

通过清心醉

ecshop二次开发之模版调用PHP文件的变量

不管你对MVC认识有多少,如果只是修改核心的话,不涉及使用MVC,但如果有别人的插件,是基于MVC模式进行开发的,你要修改就难了。

好了上正题:

在这里我严重鄙视下中国人的开源精神,对这些很基础很简单的问题,没几个人说

给实例::

$id=123456;

$this->assign(‘fenleiid’,$id);

$this->display(‘fenleiid.dwt’);

首先由于有模板库的机制

我们在fenleiid.dwt模版文件里引用模版库

<!– #BeginLibraryItem “/library/catgoodsall.lbi” –><!– #EndLibraryItem –>

这时候,我们之需要在catgoodsall.lbi文件里这么写:

{$fenleiid} 就可以提取变量了 如果是数组,就用for循环吧, 注意模板库里的变量名字$fenleiid

是在$this->assign(‘fenleiid‘,$id);  定义的,就是说,模版生成个变量(可以是数组)名叫fenleiid 他的值是$id(也可以是返回的数组)。

搞定,有不懂的,直接留言。

通过清心醉

Ecshop 手机端ECTouch二次开发实例

最近上班了。没去写Magento二次开发的实例了。

接收了Ecshop的开发,首先就是mobile端的开发。

默认的ECTouch使用的是首页显示所有的产品,没有分类处理、没有产品数量处理,一页循环加载所有产品。

如果有看作者开始写的首次接触Ecshop,我想你能猜到个大概的流程了。

不过这个就有点不一样哦,ECTouch运用了自己的MVC模式,如果没有任何的MVC基础,是难以理解的哦!

正文开始:

由于需要的是修改正文,我们看看URL:

127.0.0.1/mobile/index.php?m=default&c=index&a=index

有3个参数admin/default/install

在mobile/include/apps里可以看到,里面就有了MVC的目录架构,至于admin的话就有V层,因为要编辑嘛

第一个应该是主题的名称/themes/default/

c=index&a=index 控制器和方法了

控制器文件:mobile/include/apps/controller/IndexController.class.php
class IndexController extends CommonController {

public function index()

比如作者要修改index首页的信息,显示一级分类3的最新8个产品:

$this->assign(‘fenlei3’,model(‘Index’)->get_fenlei_id_num(3,8)); #加入这句在
$this->display(‘index.dwt’);  #之前

看,这有个model,系统会自动实例化,model(‘index’),这里面的index参数,就是我们要实例化调用的model模型数据

模型文件:mobile/include/apps/model/IndexModel.class.php

我们在来看我们这的第二个参数,第二个参数是一个方法的返回值:

get_fenlei_id_num(3,8) ,所以IndexModel.class.php文件里加入该方法:

*
* 调用指定分类产品的方法 http://www.qingxinzui.com/
*
*/
function get_fenlei_id_num($cat_id = ”, $num = ”) #提取指定分类的产品 ,需要分类id和提取的数量(默认提取最前面的)
{
/*SQL语句开始*/
$sql =
‘Select g.goods_id, g.cat_id,c.parent_id, g.goods_name, g.goods_name_style,
g.market_price, g.shop_price AS org_price, g.promote_price, ‘ .
“IFNULL(mp.user_price, g.shop_price * ‘$_SESSION[discount]’) AS shop_price, ” .
“promote_start_date, promote_end_date, g.goods_brief, g.goods_thumb, goods_img, ” .
“g.is_best, g.is_new, g.is_hot, g.is_promote ” .
‘FROM ‘ . ‘ecs_goods’ . ‘ AS g ‘ .
‘LEFT JOIN ‘ . ‘ecs_category’  . ‘ AS c ON c.cat_id = g.cat_id ‘ .
“LEFT JOIN ” . ‘ecs_member_price’. ” AS mp ” .
“ON mp.goods_id = g.goods_id AND mp.user_rank = ‘$_SESSION[user_rank]’ ” .
“Where g.is_on_sale = 1 AND g.is_alone_sale = 1 AND g.is_delete = 0 ” .
$sql .= ” AND (c.parent_id =” . $cat_id . ” OR g.cat_id = ” . $cat_id . ” OR g.cat_id ” . db_create_in ( array_unique ( array_merge ( array (
$cat_id
), array_keys ( cat_list ( $cat_id, 0, false ) ) ) ) ) . “)”;
$sql .= ” LIMIT $num”;
/*SQL语句结尾*/
/*
* 由于该手机模板没有使用电脑端的部分函数,所以上面的表名是自己添加的如果表前缀有问题则要修改下
*
* */
$res = $this->query($sql); #提取指定分类的所有数据所有SQL产品数据
$goods = array (); #定义数组接收提取所有的到数组
$o=1; #用于模板后面的判断
foreach ( $res as $idx => $row )
{
$goods [$idx] [‘id’] = $row [‘article_id’];
$goods [$idx] [‘id’] = $row [‘goods_id’];
$goods [$idx] [‘name’] = $row [‘goods_name’];
$goods [$idx] [‘brief’] = $row [‘goods_brief’];
$goods [$idx] [‘brand_name’] = $row [‘brand_name’];
$goods [$idx] [‘goods_style_name’] = add_style ( $row [‘goods_name’], $row [‘goods_name_style’] );
$goods [$idx][‘short_name’] = C(‘goods_name_length’) > 0 ? sub_str($row[‘goods_name’], C(‘goods_name_length’)) : $row[‘goods_name’];
$goods [$idx] [‘short_style_name’] = add_style ( $goods [$idx] [‘short_name’] );
$goods [$idx] [‘market_price’] = price_format ( $row [‘market_price’] );
$goods [$idx] [‘shop_price’] = price_format ( $row [‘shop_price’] );
$goods [$idx][‘thumb’] = get_image_path($row[‘goods_id’], $row[‘goods_thumb’], true);
$goods [$idx][‘goods_img’] = get_image_path($row[‘goods_id’], $row[‘goods_img’]);
$goods [$idx] [‘url’] = build_uri(‘goods/index’, array(‘id’ => $row[‘goods_id’]));
if(!($o&1)) #判断是否为偶数
{
$goods[$idx][‘_number’]=2;  #如果是偶数 每一行的都为2
}
else
{
$goods[$idx][‘_number’]=1; #否则为1
}
$o++;
}
return $goods; #返回数组
}

作者在这里加了_number,后面有用,继续吧

这里会以数组的方式把提取的8个最新的产品数据返回给控制器。

$this->assign(‘fenlei3’,…) 这里因为有了命名了。

好了,我们修改index.dwt 把系统默认显示所有产品的

<!– #BeginLibraryItem “/library/recommend_hot.lbi” –><!– #EndLibraryItem –>

这文件做修改吧

<table width=’100%’ align=’center’ border=”0″ cellspacing=”0″ cellpadding=”0″>
<!–{foreach from=$fenlei3 item=goods}–>
<!–{if $goods._number eq 1}–>
<tr>
<td width=’50%’ align=’center’>
<p><b><a href=”{$goods.url}” title=”{$goods.name|escape:html}” target=”_blank”>{$goods.name}</a></b></p>
<p><a href=”{$goods.url}” target=”_blank”>
<p><img src=”{$goods.goods_img}” alt=”{$goods.name|escape:html}” width=”150px” height=”150px”/></a></p>
<p><div style=”text-indent: 5px;”>市场价<span>{$goods.market_price}</span></p>
<p><div style=”text-indent: 7px;”><span>售  价{$goods.shop_price}</span></div></p>

</td>
<!–{else $goods._number eq 2}–>
<td width=’50%’ align=’center’>
<p><b><a href=”{$goods.url}” title=”{$goods.name|escape:html}” target=”_blank”>{$goods.name}</a></b></p>
<p><a href=”{$goods.url}” target=”_blank”>
<p><img src=”{$goods.goods_img}” alt=”{$goods.name|escape:html}” width=”150px” height=”150px”/></a></p>
<p><div style=”text-indent: 5px;”>市场价<span>{$goods.market_price}</span></p>
<p><div style=”text-indent: 7px;”><span>售  价{$goods.shop_price}</span></div></p>
</td>
</tr>
<tr><td colspan=”2″ height=”10px”></td></tr>
<!–{/if}–>
<!–{/foreach}–>
</table>

前面提到了_number,这是一个判断奇偶的,因为模板里不能很好的用PHP,除非修改核心的过滤代码,可是修改过后就不安全了。

这里作者是要输出table,两列,因为_number是1和2 所以只做两个判断,如果1输出第一个并且带<tr>开始,如果2输出第二个并且带<tr>结束

这里不用怕会出错,因为模型model的方法里,$o是自增长的,然后整除2来判断。

视图效果可能不太友好,毕竟作者主要还是针对PHP后端及服务器。

 

 

 

 

通过清心醉

首次接触Ecshop

上班的公司使用的是Ecshop开发的电子商城,虽然作者一直都是针对Magento的安装维护及开发的学习、工作,也曾想过把公司的Ecshop换成Magento,但由于当前的Ecshop前端效果基本已经做完,只需要实现PHP的功能就好了,前端需要的也就是小改。

一开始开网上说,有PHP基础,很容易操作,我们都知道,PHP二次开发来说,最基本的就是对数据库的增删改查了。

我们来看看Ecshop的代码流程,也算是让刚接触Ecshop的其他新手知道Ecshop的过程是如何实现的。

Ecshop 感觉最麻烦的,就是需要修改什么就得代码里增加,这和Magneto的插件扩展性来说,根本就不是一个级别的。

Ecshop主页通过$smarty->assign()来调用需要的数据,在$smarty->display(‘index.dwt’);前

比如说$smarty->assign()获取最新产品,这里面一般有两个参数

$smarty->assign(‘chanpin’, cat_chanpin(3,4));

这里的意思是调用分类3的产品4个。第二个参数是进行SQL操作的一个方法,你可以改成你需要返回的数组值

第一个参数算是命名方法吧,作者命名为chanpin

这样,视图模板就可以使用了。不过视图模板之前,还有一个叫lib的模板库文件

index.dwt这种dwt后缀的虽然说是显示操作,但其实核心数据还是在当前主题的library文件夹里。

好了,来个代码走势图:

index.php入口

$smarty->assign(‘chanpin’, cat_chanpin(3,4)); #假设cat_chanpin($a,$b)方法已经存在并且返回数据库的数组

$smarty->display(‘index.dwt’); #访问的首页视图

index.dwt开始提取同级目录中的library目录里的需要文件

<!– #BeginLibraryItem “/library/page_header.lbi” –><!– #EndLibraryItem –>

这就是提取/library/page_header.lbi模板库文件里的数据

page_header.bli文件里如果我们需要foreach循环数据,命名方式为:

<!–{foreach from=$fenlei item=goods}–>

这里注意,item是必须的参数,更多的可以参考模板的说明。

 

 

通过清心醉

PHP判断是否移动设备访问-框架提取版

<?php
function is_mobile_request()
{
$_SERVER[‘ALL_HTTP’] = isset($_SERVER[‘ALL_HTTP’]) ? $_SERVER[‘ALL_HTTP’] : ”;
$mobile_browser = 0;
if(preg_match(‘/(up.browser|up.link|mmp|symbian|smartphone|midp|wap|phone|iphone|ipad|ipod|android|xoom)/i’, strtolower($_SERVER[‘HTTP_USER_AGENT’])))
$mobile_browser++;
if((isset($_SERVER[‘HTTP_ACCEPT’])) and (strpos(strtolower($_SERVER[‘HTTP_ACCEPT’]),’application/vnd.wap.xhtml+xml’) !== false))
$mobile_browser++;
if(isset($_SERVER[‘HTTP_X_WAP_PROFILE’]))
$mobile_browser++;
if(isset($_SERVER[‘HTTP_PROFILE’]))
$mobile_browser++;
$mobile_ua = strtolower(substr($_SERVER[‘HTTP_USER_AGENT’],0,4));
$mobile_agents = array(
‘w3c ‘,’acs-‘,’alav’,’alca’,’amoi’,’audi’,’avan’,’benq’,’bird’,’blac’,
‘blaz’,’brew’,’cell’,’cldc’,’cmd-‘,’dang’,’doco’,’eric’,’hipt’,’inno’,
‘ipaq’,’java’,’jigs’,’kddi’,’keji’,’leno’,’lg-c’,’lg-d’,’lg-g’,’lge-‘,
‘maui’,’maxo’,’midp’,’mits’,’mmef’,’mobi’,’mot-‘,’moto’,’mwbp’,’nec-‘,
‘newt’,’noki’,’oper’,’palm’,’pana’,’pant’,’phil’,’play’,’port’,’prox’,
‘qwap’,’sage’,’sams’,’sany’,’sch-‘,’sec-‘,’send’,’seri’,’sgh-‘,’shar’,
‘sie-‘,’siem’,’smal’,’smar’,’sony’,’sph-‘,’symb’,’t-mo’,’teli’,’tim-‘,
‘tosh’,’tsm-‘,’upg1′,’upsi’,’vk-v’,’voda’,’wap-‘,’wapa’,’wapi’,’wapp’,
‘wapr’,’webc’,’winw’,’winw’,’xda’,’xda-‘
);
if(in_array($mobile_ua, $mobile_agents))
$mobile_browser++;
if(strpos(strtolower($_SERVER[‘ALL_HTTP’]), ‘operamini’) !== false)
$mobile_browser++;
// Pre-final check to reset everything if the user is on Windows
if(strpos(strtolower($_SERVER[‘HTTP_USER_AGENT’]), ‘windows’) !== false)
$mobile_browser=0;
// But WP7 is also Windows, with a slightly different characteristic
if(strpos(strtolower($_SERVER[‘HTTP_USER_AGENT’]), ‘windows phone’) !== false)
$mobile_browser++;
if($mobile_browser>0)
return true;
else
return false;
}
if(is_mobile_request()==true)
{
echo “手机的操作系统是:”.$_SERVER[‘HTTP_USER_AGENT’];

}
else
{
#echo “电脑的操作系统是:”.$_SERVER[‘HTTP_USER_AGENT’];
}
?>

通过清心醉

PHP判断是否是否为手机端登陆

<?php
if(stripos($_SERVER[‘HTTP_USER_AGENT’],”android”)==true||
stripos($_SERVER[‘HTTP_USER_AGENT’],”ios”)==true||
stripos($_SERVER[‘HTTP_USER_AGENT’],”wp”)==true)

#通过判断操作系统的名称,当然以前那些老塞班系统你也可以加!
{
echo ‘手机访问’;
}
else
{
echo ‘电脑访问’;
}
?>

 

当然更多的判断条件,我们可以写个数组进行循环判断,如果是手机访问返回true,否则返回false;

通过清心醉

通过Magento模块开发浅谈框架MVC

作者是自学人员,什么apache、php 、mysql 、Linux配置什么的,都是一点点写出来了。

上星期无聊着,就想试试框架,略接触过Zend和ThinkPHP,一开始我就在想,怎么那么难啊?如果反正都使难,我不如直接去上手学电子商城的二次开发了。所以选择了国外开源最好的Magento。

作者以前页曾经小了解过MVC的分层,控制器调用模型,模型进行数据操作后把视图文件包含进来,直接视图里输出模型数据。

上手Magento之后,一堆堆的命名规范,都大同小异,类都是驼峰方式,控制器方法后面必须加Action。这和Zend基本没差别嘛,话说,Magento就是用Zend开发出来的。

什么类啊/数据模型啊/视图啊,其实MVC里,更多的是继承。

由系统提供一整套的API来给我们调用,比如$this->getRequest(),有点ZEND基础的人都知道接收$_POST等数据。

什么是框架,他不过就是一款有规范的MVC分层,但里面封装了有很多很完善的方法(函数)给我们使用。

如果要接触框架,思维很重要,更重要的是PHP的基础。

作者文章写过的Magento开发实例,也算是一种框架了吧?但有很多的方法(函数)作者没用过,或者说不知道哪才需要用?

多写代码,学会追踪继承的父类,或者查看其他代码的规范,也是提升对框架认识的一种哦。

 

 

通过清心醉

Magento 开发实例七(模型Model)资源安装配置

本来先要写数据库的增删改查的,但如果懂PHP的朋友们看了前面的文章,相信都能想到办法了。所以先说说资源的配置问题,下文再写详细的增删改查。

作者提醒:永远不要相信国内搜索的数据,如果真的想认真学开发,好好GOOGLE看看国外正宗的开源教程,或者多看Magento的核心代码的编写规范以及插件的规范。作者就因为误信国内的数据,所以资源配置都得最后来弄。

正文开始:app.tar

Magento都是由配置文件做系统的支撑的。

读取modules所有的模块配置->

读取所有模块里的etc目录里的配置文件(比如config.xml)->

根据etc目录里的配置文件分配路由、资源等(需要的时候调用出来)->

然后就是MVC的访问操作了。就是作者前面几篇文章所说

 

其实,Magento当读取到etc/config.xml文件的时候,会查看有没有setup节点,如果有,执行安装,一般来说都是只执行一次,所以一会我们写的代码里要有中指。

 

首先增加安装配置:

<mymodule_setup>

<setup>

<module>Mage_Mymodule</module>

</setup>

<connection>

<use>core_setup</use>

</connection>

</mymodule_setup>

 

定义个module_setupsetup里直接使用module,表示直接使用模块里的mysql4-install.0.1.0.php文件

 

在这里作者要特别说明下,<setup><module>Mage_Mymodule</module></setup>

看这名字就知道,是项目名/模块(插件名)

至于<connection><use>core_setup</use></connection>

 

我们可以追踪到app/code/core/Mage/Core/Model/Resource/Setup文件

class Mage_Core_Model_Resource_Setup

{

const DEFAULT_SETUP_CONNECTION = ‘core_setup’;

const VERSION_COMPARE_EQUAL = 0;

const VERSION_COMPARE_LOWER = -1;

const VERSION_COMPARE_GREATER = 1;

 

const TYPE_DB_INSTALL = ‘install’;

const TYPE_DB_UPGRADE = ‘upgrade’;

const TYPE_DB_ROLLBACK = ‘rollback’;

const TYPE_DB_UNINSTALL = ‘uninstall’;

const TYPE_DATA_INSTALL = ‘data-install’;

const TYPE_DATA_UPGRADE = ‘data-upgrade’;

………

………

}

一般来说我们是需要配置个类继承该类来进行安装的,但由于作者在<setup>节点里直接使用的是模块的名称而不是<class>(比如配置的Blog就是class),这时候Magento会自动找到sql目录里的mysql4-install.0.1.0.php文件。

 

这要特别说明下的就是

Config.xml里有个配置文件的版本:

<modules>

<Mage_Mymodule>

<version>1.1.1</version>

</Mage_Mymodule>

</modules>

 

但我们mysql4-install.0.1.0文件,是不受那个版本的影响,如果需要默认安装,必须要有mysql4-install.0.1.0.php

 

Mage/Mymodule/sql/mymodule_setup/Mysql4-install.0.1.0.php

#目录里的mymodule_setup是我们前面定义的,可以看config.xml文件

#写入下面的

<?php

echo “类名是:”.get_class($this).”</br>”;

die(“exit”);

 

在这里我们一定要加个die();否则流程走了一次,就不走了哦!

而且后面我们执行有SQL的操作的时候,也加个DIE好点,看数据库里存在数据了再把DIE关闭.

这时候只要一刷新缓存:

2015-05-03

看到了吧,作者没定义任何类,系统自动使用核心的Setup类,就是作者前面说的app/code/core/Mage/Core/Model/Resource/Setup文件。

 

动起来吧:让我们用资源配置来安装数据表/字段并且写入数据:

首先我们要确保数据库里没有blog表哦

2015-05-03-01

修改mysql4-install-0.1.0.php

#注:请保留die(“exit”);

 

<?php

echo “类名是:”.get_class($this).”</br>”;

$installer=$this; #把类重新赋值,也可以直接使用$this,这不是强制的,但只是命名规范而已

$installer->startSetup(); #启动安装方法,可以在app/code/core/Mage/Core/Model/Resource/Setup里查看到

$table=$installer->getTable(‘mymodule/blog’);#添加表名称,如果有前缀,会自动增加哦.

$sql=”CREATE TABLE $table(id int primary key auto_increment,name varchar(128),phone varchar(128))”;

$intosql=”INSERT INTO $table(name,phone)VALUES(‘qingxinzui’,’13823819185′)”;

$installer->run($sql);

$installer->run(intosql);

$installer->endSetup();

die(“安装成功!”);

 

然后我们刷新下页面

 

类名是:Mage_Core_Model_Resource_Setup
安装成功!

 

看看MYSQL里吧

是不是已经有了你想要的表和字段内容了?

 

这时候我们就可以把die(“安装成功!”);取消掉了

同时删除magento数据库里的blog表和字段

重新走一遍。

 

如果你是和作者一样的走法你会发现,刷新后,直接返回主页了,其实是因为数据已经写入成功,已经没有DIE中止了。

这时候再看数据库里,blog表和字段内容都存在的。

资源配置安装完成。

 

如果我们需要升级

修改config.xml文件里的版本号

比如作者修改为1.1.2

然后创建个mysql4-upgrade-1.1.1-1.1.2.php

 

这有些会迷惑的,我们一开始安装的时候文件名是mysql4-install-0.1.0.php

怎么这是1.1.1

0.1.0是默认安装,当写入到数据库之后(可以在core_resource看)版本实际是以config.xml里的<version>写入的

所以我们要针对当前的<version>来进行命名升级

 

mysql4-upgrade-1.1.1-1.1.2.php文件写入:

 

<?php

echo “类名是:”.get_class($this).”</br>”;

$installer=$this; #把类重新赋值,也可以直接使用$this,这不是强制的,但只是命名规范而已

$installer->startSetup();

$table=$installer->getTable(‘mymodule/blog’);

$intosql=”INSERT INTO $table(name,phone)VALUES(‘qingxinzui1′,’13823819185’)”;

$installer->run($intosql);

$installer->endSetup();

die(“安装成功!”);

 

我们一样加个die看是否有写入

如果blog表里多一行数据,说明成功。

这时候我们在关闭DIE,让系统再执行一次,如此一来我们应该有3行数据了。

 

以后我们需要再进行升级模块(插件)

只需要看config.xml里的配置文件的<version>是多少

然后在模块(插件)的sql目录里创建对应的文件

mysql4-upgrade-<version>-新的<version>.php

如:mysql4-upgrade-1.1.1-1.1.2.php

这时候别忘记了把config.xml里的也修改成1.1.2

现在的版本你要不确定可以core_resource表里看。

 

通过清心醉

Magento 开发实例六(模型Model)通过Block(块)功能提取所有数据

需要学习的下载看:app.tar

回顾上文的具体流程:

URL触发控制器-> 控制器如果有执行布局-> 触发布局type里的Block(块功能)-> 系统实例化Block块类-> 调用Block块里面的类方法(需要在视图里调用方法,所以作者直接用构造方法)-> 类方法里进行SQL写入-> 视图输出

 

如果要进行所有数据返回到数据集,Magento提供了getCollection()的方法,因此我们需要配置getCollection()的配置项来配置模型集合。

 

作者的是以blog做为表,在每个模型配置/实例化类中都有指定mymodule/blog

 

每个模型都有一个“protected属性“_resourceCollectionName,该值是从父类“Mage_Core_Model_Abstract继承来的。这个属性的值是这个模型对应的模型集合的URI

protected ‘_resourceCollectionName’ => string ‘mymodule/blog_collection’

 

更多具体的我们可以:

$data1=Mage::getModel(‘mymodule/blog’);

var_dump($data); #打印数组就可以看到protected ‘_resourceCollectionName’ =>

 

在默认情况下,这个值是模型的URI加上“_collectionMagento把模型集合也看做是一种资源(Resrouce),所以运用资源模型的命名规则,模型集合的全名是

我们追踪config.xml,看看我们的配置

<global><models><mymodule_resource> 在资源配置里,我们可以看到我们定于的资源类<class>Mage_Mymodule_Model_Resource

 

Mage_Mymodule_Model_Resource_Blog_Collection

#因为我们是在Blog模型资源下

然后我们要创建如下文件

class Mage_Mymodule_Model_Resource_Blog_Collection extends Mage_Core_Model_Resource_Db_Collection_Abstract{

protected function _construct()

{

$this->_init(‘mymodule/blog’);

}

}

 

在这说下,如果是继承,可以查看核心代码的目录

 

好了,同样,我们在mymodule/index/index视图里增加个调用表单,用于输出blog表里的全部数据,增加个触发URL

<a href=<?php echo $this->getUrl(‘mymodule/blog/blogsql’); ?>查看全部的blog数据</a>

 

这时候,Blog执行控制器我们需要写多个blogsql的代码:

function blogsqlAction()

{

$this->loadLayout();

$this->renderLayout();

}

直接引用布局,我们来增加布局配置:local.xml

<mymodule_blog_blogsql>

<reference name=”root”>

<block type=”mymodule/blogsql” name=”root” output=”toHtml” template=”mymodule/blogsql.phtml”/>

</reference>

</mymodule_blog_blogsql>

 

Block()里增加个Blogsql的方法:

 

class Mage_Mymodule_Block_Blogsql extends Mage_Core_Block_Template

{

protected $data;

function __construct()

{

$this->data=Mage::getModel(‘mymodule/blog’)->getCollection(); #实例模型全部资源

return $this->data; #返回的模型的值,给视图直接调用

}

}

 

 

 

已经实现了我们需要的,然后我们在视图里操作输出吧:

 

 

 

Blogsql.phtml文件里:

 

 

 

blogsql的视图:</br>

 

<?php

 

$o=0;

 

foreach($this->data as $blog)

 

{

 

echo “编号:”.$o++.”名字:”.$blog->getName().”-电话“.$blog->getPhone().”</br>”;

 

}

?>

 如果我们需要之需要获取全部数据集中的name

可以用:$this->data=Mage::getModel(‘mymodule/blog’)->getCollection()->addAttributeToSelect(‘name’);