月度归档 2015年11月28日

通过清心醉

OPENCART无法发邮件-MAIL使用SMTP类文件

最近发现OPENCART发邮件系统有点问题,不知道是配置问题还是怎么的,老是出现错误.

由于邮件系统都是使用/system/library/mail.php里的mail函数

而默认使用方法是:

$mail = new Mail();
$mail->protocol = $this->config->get(‘config_mail_protocol’);
$mail->parameter = $this->config->get(‘config_mail_parameter’);
$mail->smtp_hostname = $this->config->get(‘config_mail_smtp_hostname’);
$mail->smtp_username = $this->config->get(‘config_mail_smtp_username’);
$mail->smtp_password = html_entity_decode($this->config->get(‘config_mail_smtp_password’), ENT_QUOTES, ‘UTF-8’);
$mail->smtp_port = $this->config->get(‘config_mail_smtp_port’);
$mail->smtp_timeout = $this->config->get(‘config_mail_smtp_timeout’);

$mail->setTo($this->request->post[’email’]);
$mail->setFrom($this->config->get(‘config_email’));
$mail->setSender(html_entity_decode($this->config->get(‘config_name’), ENT_QUOTES, ‘UTF-8′));
$mail->setSubject($subject);
$mail->setText($message);
$mail->send();

在类里对成员protocol 进行判断使用MSTP还是SENDMAIL方法

为了保证OPENCART的核心可以正常的使用,作者修改了SMTP的类方法,但只能使用SMTP的类操作,暂未对SENDMAIL进行操作.

使用方法和默认的操作相同

$mail=new mail();
$mail->parameter=’13823819185@139.com’; #抄送一份
$mail->smtp_hostname=’smtp.ym.163.com’;  #邮箱地址
$mail->smtp_username=’admin@qingxinzui.com’;  #用户名
$mail->smtp_password=’************’;  #密码
$mail->smtp_port=’25’; #端口
$mail->smtp_timeout=’30’; #超时施加 //默认5,进行重写
$mailto=”收件人@qingxinzui.com”;
$mailtitle=”测试邮件”; //邮件标题
$mailbody =”<center><div style=’font-size:24px;color:red;’>标题</div></center>”;
$mailbody.=”<table align=’center’ width=’50%’ border=’1′ cellpadding=’2′ cellspacing=’0′>”;
$mailbody.=”<tr><td><center>联系人</center></td><td>名字</td></tr>”;
$mailbody.=”<tr><td><center>联系电话</center></td><td>电话</td></tr>”;
$mailbody.=”<tr><td><center>联系地址</center></td><td>地址</td></tr>”;
$mailbody.=”<tr><td><center>店铺名称</center></td><td>店名</td></tr>”;
$mailbody.=”</table>”;
$mail->setTo($mailto); //收件人
$mail->setFrom($mail->smtp_username); //发件人
$mail->setSubject(html_entity_decode($mailtitle, ENT_QUOTES, ‘UTF-8′));
$mail->setText($mailbody);
$mail->send();

以下为class mail类的封装:

class mail
{
protected $to; //收件人
protected $from; //发件人
protected $subject;
protected $text;
public $protocol;
public $smtp_hostname; #主机地址 smtp.qq.com
public $smtp_username; #用户名
public $smtp_password; #密码
public $smtp_port;  #邮件端口
public $smtp_timeout; #超时时间
public $newline;
public $verp;
public $parameter; //#附加发送
private $ishostname; //主机值保留localhost
public $log_file;
public $debug;
public $auth; //验证
private $sock;

function __construct()
{
$this->smtp_port=25; //构造方法给予端口赋默认值
$this->smtp_timeout=30; //构造方法给予超时赋默认值
$this->ishostname  = “localhost”; //默认值,禁止外部修改
$this->debug=TRUE; //开启调试
$this->log_file=””; //日志文件
$this->sock=FALSE;
$this->protocol=’SMTP’; #邮件类型
$this->auth=TRUE;
$this->newline = “\n”;
$this->verp = false;
$this->parameter=”;
}

public function setTo($to) {
$this->to = $to;
}

public function setFrom($from) {
$this->from = $from;
}

public function setReplyTo($reply_to) {
$this->reply_to = $reply_to;
}

public function setSubject($subject) {
$this->subject = $subject;
}

public function setText($text) {
$this->text = $text;
}

function send()
{
$this->sendmail($this->to, $this->from, $this->subject,$this->text,’HTML’,$this->parameter);
}

private function sendmail($to, $from, $subject = “”, $body = “”, $mailtype, $cc = “”, $bcc = “”, $additional_headers = “”)
{
//收件人,发件人,邮件标题,邮件内容,邮件类型,抄送等参数
$header= “”;
$mail_from = $this->get_address($this->strip_comment($from));
$body= mb_ereg_replace(“(^|(\r\n))(\\.)”, “\\1.\\3”, $body);
$header .= “MIME-Version:1.0\r\n”;
if ($mailtype == “HTML”) {
$header .= ‘Content-type: text/html; charset=utf-8’ . “\r\n”;
}
$header .= “To: ” . $to . “\r\n”;
if ($cc != “”) {
$header .= “Cc: ” . $cc . “\r\n”;
}
$header .= “From: ” .$from . “\r\n”;
$header .= “Subject: ” . $subject . “\r\n”;
$header .= $additional_headers;
$header .= “Date: ” . date(“r”) . “\r\n”;
$header .= “X-Mailer:By (PHP/” . phpversion() . “)\r\n”;
list($msec, $sec) = explode(” “, microtime());
$header .= “Message-ID: <” . date(“YmdHis”, $sec) . “.” . ($msec * 1000000) . “.” . $mail_from . “>\r\n”;
$TO = explode(“,”, $this->strip_comment($to));

if ($cc != “”) {
$TO = array_merge($TO, explode(“,”, $this->strip_comment($cc))); //合并一个或多个数组
}

if ($bcc != “”) {
$TO = array_merge($TO, explode(“,”, $this->strip_comment($bcc)));
}
$sent = TRUE;
foreach ($TO as $rcpt_to) {
$rcpt_to = $this->get_address($rcpt_to);
if (!$this->smtp_sockopen($rcpt_to)) {
$this->log_write(“Error: Cannot send email to ” . $rcpt_to . “\n”);
$sent = FALSE;
continue;

}
if ($this->smtp_send($this->ishostname, $mail_from, $rcpt_to, $header, $body)) {
$this->log_write(“E-mail has been sent to <” . $rcpt_to . “>\n”);
} else {
$this->log_write(“Error: Cannot send email to <” . $rcpt_to . “>\n”);
$sent = FALSE;
}
fclose($this->sock);
$this->log_write(“Disconnected from remote host\n”);
}
echo “<br>”;
return $sent;
}

private function smtp_send($helo, $from, $to, $header, $body = “”)
{
if (!$this->smtp_putcmd(“HELO”, $helo)) {
return $this->smtp_error(“sending HELO command”);
}
#auth
if ($this->auth) {
if (!$this->smtp_putcmd(“AUTH LOGIN”, base64_encode($this->smtp_username))) {
return $this->smtp_error(“sending HELO command”);
}

if (!$this->smtp_putcmd(“”, base64_encode($this->smtp_password))) {
return $this->smtp_error(“sending HELO command”);
}
}
#
if (!$this->smtp_putcmd(“MAIL”, “FROM:<” . $from . “>”)) {
return $this->smtp_error(“sending MAIL FROM command”);
}

if (!$this->smtp_putcmd(“RCPT”, “TO:<” . $to . “>”)) {
return $this->smtp_error(“sending RCPT TO command”);
}

if (!$this->smtp_putcmd(“DATA”)) {
return $this->smtp_error(“sending DATA command”);
}

if (!$this->smtp_message($header, $body)) {
return $this->smtp_error(“sending message”);
}

if (!$this->smtp_eom()) {
return $this->smtp_error(“sending <CR><LF>.<CR><LF> [EOM]”);
}

if (!$this->smtp_putcmd(“QUIT”)) {
return $this->smtp_error(“sending QUIT command”);
}

return TRUE;
}

private function smtp_sockopen($address)
{
if ($this->smtp_hostname == “”) {
return $this->smtp_sockopen_mx($address);
} else {
return $this->smtp_sockopen_relay();
}
}

private function smtp_sockopen_relay()
{
$this->log_write(“Trying to ” . $this->smtp_hostname . “:” . $this->smtp_port . “\n”);
if (empty($this->smtp_timeout))
{
$this->smtp_timeout=5;
}
$this->sock = @fsockopen($this->smtp_hostname, $this->smtp_port, $errno, $errstr, $this->smtp_timeout);

//var_dump($this->sock);die();

if (!($this->sock && $this->smtp_ok())) {
$this->log_write(“Error: Cannot connenct to relay host ” . $this->smtp_hostname . “\n”);
$this->log_write(“Error: ” . $errstr . ” (” . $errno . “)\n”);
return FALSE;
}
$this->log_write(“Connected to relay host ” . $this->smtp_hostname . “\n”);
return TRUE;
}

private function smtp_sockopen_mx($address)
{
$domain = ereg_replace(“^.+@([^@]+)$”, “\\1”, $address);
if (!@getmxrr($domain, $MXHOSTS)) {
$this->log_write(“Error: Cannot resolve MX \”” . $domain . “\”\n”);
return FALSE;
}
foreach ($MXHOSTS as $host) {
$this->log_write(“Trying to ” . $host . “:” . $this->smtp_port . “\n”);
$this->sock = @fsockopen($host, $this->smtp_port, $errno, $errstr, $this->smtp_timeout);
if (!($this->sock && $this->smtp_ok())) {
$this->log_write(“Warning: Cannot connect to mx host ” . $host . “\n”);
$this->log_write(“Error: ” . $errstr . ” (” . $errno . “)\n”);
continue;
}
$this->log_write(“Connected to mx host ” . $host . “\n”);
return TRUE;
}
$this->log_write(“Error: Cannot connect to any mx hosts (” . implode(“, “, $MXHOSTS) . “)\n”);
return FALSE;
}

private function smtp_message($header, $body)
{
fputs($this->sock, $header . “\r\n” . $body);
$this->smtp_debug(“> ” . str_replace(“\r\n”, “\n” . “> “, $header . “\n> ” . $body . “\n> “));

return TRUE;
}

private function smtp_eom()
{
fputs($this->sock, “\r\n.\r\n”);
$this->smtp_debug(“. [EOM]\n”);

return $this->smtp_ok();
}

private function smtp_ok()
{
$response = str_replace(“\r\n”, “”, fgets($this->sock, 512));
$this->smtp_debug($response . “\n”);

if (!mb_ereg(“^[23]”, $response)) {
fputs($this->sock, “QUIT\r\n”);
fgets($this->sock, 512);
$this->log_write(“Error: Remote host returned \”” . $response . “\”\n”);
return FALSE;
}
return TRUE;
}

private function smtp_putcmd($cmd, $arg = “”)
{
if ($arg != “”) {
if ($cmd == “”)
$cmd = $arg;
else
$cmd = $cmd . ” ” . $arg;
}

fputs($this->sock, $cmd . “\r\n”);
$this->smtp_debug(“> ” . $cmd . “\n”);

return $this->smtp_ok();
}

private function smtp_error($string)
{
$this->log_write(“Error: Error occurred while ” . $string . “.\n”);
return FALSE;
}

private function log_write($message)
{
$this->smtp_debug($message);

if ($this->log_file == “”) {
return TRUE;
}

$message = date(“M d H:i:s “) . get_current_user() . “[” . getmypid() . “]: ” . $message;
if (!@file_exists($this->log_file) || !($fp = @fopen($this->log_file, “a”))) {
$this->smtp_debug(“Warning: Cannot open log file \”” . $this->log_file . “\”\n”);
return FALSE;
}
flock($fp, LOCK_EX);
fputs($fp, $message);
fclose($fp);

return TRUE;
}

private function strip_comment($address)
{
$comment = “\\([^()]*\\)”;
while (mb_ereg($comment, $address)) {
$address = mb_ereg_replace($comment, “”, $address);
}

return $address;
}

private function get_address($address)
{
$address = mb_ereg_replace(“([ \t\r\n])+”, “”, $address);
$address = mb_ereg_replace(“^.*<(.+)>.*$”, “\\1”, $address);

return $address;
}

private function smtp_debug($message)
{
if ($this->debug) {
echo $message . “<br>”;
}
}

private function get_attach_type($image_tag) //
{

$filedata = array();

$img_file_con = fopen($image_tag, “r”);
unset($image_data);
while ($tem_buffer = AddSlashes(fread($img_file_con, filesize($image_tag))))
$image_data .= $tem_buffer;
fclose($img_file_con);
$filedata[‘context’]  = $image_data;
$filedata[‘filename’] = basename($image_tag);
$extension            = substr($image_tag, strrpos($image_tag, “.”), strlen($image_tag) – strrpos($image_tag, “.”));
switch ($extension) {
case “.gif”:
$filedata[‘type’] = “image/gif”;
break;
case “.gz”:
$filedata[‘type’] = “application/x-gzip”;
break;
case “.htm”:
$filedata[‘type’] = “text/html”;
break;
case “.html”:
$filedata[‘type’] = “text/html”;
break;
case “.jpg”:
$filedata[‘type’] = “image/jpeg”;
break;
case “.tar”:
$filedata[‘type’] = “application/x-tar”;
break;
case “.txt”:
$filedata[‘type’] = “text/plain”;
break;
case “.zip”:
$filedata[‘type’] = “application/zip”;
break;
default:
$filedata[‘type’] = “application/octet-stream”;
break;
}
return $filedata;
}
}

通过清心醉

浅谈大数据在互联网+中的重要性

在这之前,我们需要了解什么是互联网+?

看完了作者这一篇,让你知道什么才叫大数据的互联网+时代.

“互联网+”就是“互联网+各个传统行业”,但这并不是简单的两者相加,而是利用信息通信技术以及互联网平台,让互联网与传统行业进行深度融合,创造新的发展生态。

以上的数据,出自BAIDU.文中有提到:利用信息通信技术以及互联网平台.

信息通信技术::->就是通过网络互动交换信息.

比如利用FACEBOOK网站进行社区交流,利用MSN进行在线信息交流.这些工作,只要会精通了任意一门编程语言,什么C++,JAVA,PHP都可以写出来.只是面对的群体不同,比如IOS苹果系统,Windows系统,及网站系统.

#######################

接下来就是互联网平台了::->前面作者两个平台都红字标注,是因为平台才是最主要的结果. 而且,平台才是大数据的终结者,没有平台,你拿什么谈数据?大数据,就好比SEO,如果不懂,慢慢往下看(接下来的文章,纯属作者个人见解,您不喜欢可以直接无视.).

 

在这作者要模拟两个不同网络公司的数据资源::

1->先说说现在主流趋势微信公众平台:

简单化的操作,可以让用户很好的使用,更重要的也许就是因为微信的用户是唯一性的,保证都是真实的用户.更方便的管理,同时国内使用量非常大,很好的数据性.

2->再说说作者现在的网站:

虽然百度没排名,但GOOGLE效果流量一直都很不错,很单调的技术文章等.

接下来,就以大数据为中心,用模拟的方式区分下微信公众平台和作者网站是否有大数据的前提:

题目1->访问用户的需求:

公众平台:只知道有用户;

我的网站:能知道为什么来访问我的网站,是哪点吸引了用户;

题目2->用户的访问设备:

公众平台:只知道用户通过电脑/IPAD/MOBILE手机访问了;

我的网站:能知道每一个用户的访问设备,我可以更准确的知道电脑/IPAD/MOBILE手机访问的百分比

题目3->用户到底有多感兴趣:

公众平台:用户挥一挥衣绣就走了.没留下任何东西;

我的网站:用户在我每一个页面停了多久,然后又偷看我的哪些页面资料一目了然;

 

根据上面三个简单的划分,作者来说说什么是大数据:

大数据一:要知道用户的群体,大概年纪\访问设备

大数据二:要知道用户群体感兴趣的内容是什么,如果用SEO来理解就是能准确到用户对那些数据感兴趣(在这比喻如果来作者网站都是学网站建设资料的,那么我就可以根据网站建设写更多的资料吸引更多想学习的人,更可以根据不同网站建设的页面停留时间来对网站进行更精确的网站建设资料划分)

除了上问的数据分析,大数据更重要的是什么?

更重要的是要有数据,要有资料数据,用户数据.(不管你是用公众平台还是百度平台,数据永远是在他们那,你只是使用他们的功能做跳板,最简单的微信公众平台里发的内容,最下面,永远都会有微信的广告内容,因为你只是他们平台中的一个独立资料数据.)

做过程序开发或者有接触过程序的人都该知道,有个东西叫数据库,为什么叫数据库? 因为数据库是保存了全部资料数据和用户数据的一种资源,如果连数据库都没有,谈什么大数据时代,顶多算个互联网,更别提互联网+了;

作者虽然只是一名程序员,但程序员感兴趣的永远是一堆堆的数据,包括”大数据”;

 

文中一开始就提起的”平台”,什么是平台?

58同城是平台,阿里巴巴是平台(B2B),赶集网是平台.

平台得有自己独立的运营商管理,有独立的服务商管理,有独立的用户管理.

把服务商的资料展现给用户,把用户的需求展现给商家,运营商进行系统的运维.

这样,不管是商家还是个体户还是用户,都可以更容易的展现自己的资源(比如产品)和需求信息.

运营商只需要对不同的版块做好数据的分析,把数据资源中最靠及完整性最高的展现出来.

未来人与人,人与商家,人与生产厂家就不在需要面对面的交谈,只要运营商给予权重性的保证可靠性,网络化的未来科技,不遥远了.

这,就是互联网+;

 

 

 

 

 

 

 

通过清心醉

网站建设二之服务器快速安装及开发工具使用

由于服务器的配置涉及Unix的配制,包括Windows也比较麻烦,所以后期会针对不同的系统平台编写系统配置:

需要安装两个东西
XAMPP–>WEB网站系统快速安装平泰
ZEND STUIDO –>PHP网站开发系统IDE环境

针对不同的系统,下载对应的XAMPP,分Win7/WinXp两个版本(学习阶段以WINDOWS为核心)

打开XAMPP

1

选择NEXT
然后
2
继续点NEXT

接着是配置目录:建议默认使用C:\xampp目录
3
NEXT安装:

4

点这两个启用

5

变成:

6

然后游览器访问
http://127.0.0.1/

确定可以看到以下页面,说明安装成功!

7

到现在为止,WEB系统服务环境就算安装完成了。

接着安装ZEND STUDIO
图不发了,直接全部点next(下一步)

安装好之后运行,会弹出这个,设置目录为C:\xampp
01
这时候,项目的目录位置就是C:\xampp了

这时候,我们进入xampp目录,修改htdocs文件夹为htdocs1

在ZEND里
点左上角的
file->new->local php project (没办法截图,看着来做)

直接点Finish 安装完成之后是::

10

双击PHP文件
11
写上echo phpinfo();
点左上的保存

然后打开游览器访问:http://127.0.0.1/

12

如果可以显示类似内容说明环境配置成功,可以准备入手PHP开发了。

网站建设二之服务器安装

通过清心醉

网站建设之看懂WEB流程

首先要先了解两个::静态页面和动态页面。

(WEB静态基本以htlm为主,动态为PHP,JSP,ASP等)

静态页面,一般由就是一个文件一个页面,比如我在这写的文章

第一篇可以是1.html,第二篇可能是2.html,第三篇可能是3.html

那么我写一篇文章,就要写一个文件,包括页面的设计。

静态页面执行过程:

打开游览器–》访问指定的文件–》游览器显示指定文件的内容;

我们可以自己创建1.html,2.html等等文件,直接打开,就是这页面里的内容了。

如果以目录方式的话。就是:

目录/1.html;

目录/2.html;

目录/3.html;

 

 

动态页面,就需要涉及数据结构了:

动态页面需要配置服务器。

网页程序解释器(PHP),数据库存储器(MYSQL),WEB站点服务器(APACHE)。

服务器的流程过程:

打开动态网页(这以PHP为主)–》

WEB站点服务器(APACHE)得知用户访问的是PHP文件–》

利用网页程序解释器(PHP)打开对应的PHP代码文件–》

因为PHP文件只有过程和操作方法,文章数据是保存在数据库的,这时候PHP程序代码中连接数据库存储器(MYSQL)–》

当成功连接数据库存储器(MYSQL)的时候,提取文章的标题、文章内容等信息–》

把提取的文章信息以代码的方式显示出来(在这要注意,所有的网页文件都是源代码,只是游览器可以读的出类型,所以才会有我们看到漂亮的网页页面)。

动态网站好在哪? 就是他可以带参数

上面的方法中,连接数据库拿文章信息的时候,如果有个id=1表示第一篇,id=2表示拿第二篇,就可以拿出指定需要的了。

通过清心醉

PHP开发之OPENCART多用户权限控制

由于使用OPENCART管理员的核心代码进行二次开发,很多时候用户的操作权限是很重要的,否则就会出现越权修改其他商家的产品等信息.

由于现在作者编写的是B2O2O的类型,暂时还在O2O的开发阶段(B2因为是多域名区分而已,一样需要多用户实现,所以先把重心放在O2O上用户数据的区分上)

作者昨天写了一个图片库区分的方法,该方法类似,主要针对于常用的产品及用户信息(后期B2整合O2O的时候还需要对分类进行划分,思路相同)权限区分功能.

1:用户的登陆数据表是唯一的,有独立的唯一性;

2:用户上传的产品末尾添加字段:product_laction_id; //

 

OPENCART判断用户是否登陆,其实是判断是否存在$this->session->data[‘user_id’]的参数值

session是一个对象,data是session对象内的一个数组.

在登陆之后,可自行创建新的参数值,比如作者创建的是:

$this->session->data[‘location_user_id’]

虽然值是相同的,但访问权限用任意一个就可以了

 

为什么呢? 因为OPENCART触发的页面都是以GET的方式获取,如果说你有很强大的前端工程师支撑你完全可以纯AJAX化.

具体是唯一,GET的时候,我们就必须要判断下用户的合法性了

假设有两个用户ID

ID1=100;

ID2=200;

/index.php?route=localisation/location&token=TQEAMbDBFvt6CmRbYszezUn9GmozQQjr&location_user_id=100

我们看上面的链接中,请求localisation里的location控制器,调用默认的index方法

token为OPENCART的加密权限方式,但只是用于区分用户是否已登陆

最后一个参数location_user_id=100;

就是打开控制器之后,根据GET的location_user_id的值,显示用户ID=100的商家信息

直接改200就变ID=200的商家信息了,就会受到恶意的修改.

方法:针对GET的location_user_id与$this->session->data[‘location_user_id’]判断,不存在即die();

不过建议,最好在执行模型SQL语句的时候强制执行.

不管UPDATE还是DELETE.统一WHERE user_id= ‘$location_user_id’;

 

通过清心醉

opencart-B2B-O2O-C2C开发之区分用户的图片操作方法

不管B2B,O2O,C2C,都是要完整的区分用户的目录结构.因为后台都是多用户操作.

在这作者假设你已经可以使用OPENCART二次开发来划分用户的登陆及显示数据.

假设创建一个用户之后,创建一个图片目录,目录名为用户的编号(假设编号$userid为1001);

mkdir(DIR_IMAGE . ‘catalog/’.$this->session->data[‘user_id’] , 0777);

chmod(DIR_IMAGE . ‘catalog/’.$this->session->data[‘user_id’] , 0777);

然后是用户独立后台上传图片,创建目录,进入目录时的方法:

在FileManager控制器中替换掉:

if (isset($this->request->get[‘directory’]))
{
$directory = DIR_IMAGE . ‘catalog/’. $this->request->get[‘directory’];
} else
{
$directory = DIR_IMAGE . ‘catalog/’.$this->session->data[‘user_id’];
}

 

 

 

通过清心醉

opencart开发前台显示指定分类的产品模组(块)

和开发支付方式一样,开发模块需要有对应的MVC+L参数,并且Language里必须有$_[‘header_title’]模块名.同时该模型名必须是唯一的.

opencart后台会循环读取/controller/module里的模块PHP文件代码,然后根据每个文件的$_[‘header_title’]获取模块的标题名称.

同时该文件的类名(比如作者现在开发显示分类的产品,类是:class ControllerModuleCategoryproduct extends Controller) .

类名是Categoryproduct,然后根据命名规则,查询extension表内的code有无对应的参数值,如果没有,用户可以安装,否则是添加更多.

我们来看看extension表内是如何区分的:

extension_id=>’27’,type=>’module’,code=’categoryproduct’;

//类型为module里的文件,参数是类名为categoryproduct的模块,安装后就可以看到

extension_id=>’28’,type=>’payment’,code=’paypal’;

//类型为payment支付扩展里的文件,参数是类名为paypal的模块.

好了,说了数据库表内的关系,来看看完整控制器吧(视图请自行编写)

class ControllerModuleCategoryproduct extends Controller {
private $error = array();

public function index() {
$this->load->language(‘module/categoryproduct’);

$this->document->setTitle($this->language->get(‘heading_title’));

$this->load->model(‘extension/module’);

if (($this->request->server[‘REQUEST_METHOD’] == ‘POST’) && $this->validate()) {
if (!isset($this->request->get[‘module_id’])) {
$this->model_extension_module->addModule(‘categoryproduct’, $this->request->post);
} else {
$this->model_extension_module->editModule($this->request->get[‘module_id’], $this->request->post);
}

$this->session->data[‘success’] = $this->language->get(‘text_success’);

$this->response->redirect($this->url->link(‘extension/module’, ‘token=’ . $this->session->data[‘token’], ‘SSL’));
}

$data[‘heading_title’] = $this->language->get(‘heading_title’);

$data[‘text_edit’] = $this->language->get(‘text_edit’);
$data[‘text_enabled’] = $this->language->get(‘text_enabled’);
$data[‘text_disabled’] = $this->language->get(‘text_disabled’);

$data[‘entry_name’] = $this->language->get(‘entry_name’);
$data[‘entry_product’] = $this->language->get(‘entry_product’);
$data[‘entry_limit’] = $this->language->get(‘entry_limit’);
$data[‘entry_width’] = $this->language->get(‘entry_width’);
$data[‘entry_height’] = $this->language->get(‘entry_height’);
$data[‘entry_status’] = $this->language->get(‘entry_status’);

$data[‘help_product’] = $this->language->get(‘help_product’);

$data[‘button_save’] = $this->language->get(‘button_save’);
$data[‘button_cancel’] = $this->language->get(‘button_cancel’);

if (isset($this->error[‘warning’])) {
$data[‘error_warning’] = $this->error[‘warning’];
} else {
$data[‘error_warning’] = ”;
}

if (isset($this->error[‘name’])) {
$data[‘error_name’] = $this->error[‘name’];
} else {
$data[‘error_name’] = ”;
}

if (isset($this->error[‘width’])) {
$data[‘error_width’] = $this->error[‘width’];
} else {
$data[‘error_width’] = ”;
}

if (isset($this->error[‘height’])) {
$data[‘error_height’] = $this->error[‘height’];
} else {
$data[‘error_height’] = ”;
}

$data[‘breadcrumbs’] = array();

$data[‘breadcrumbs’][] = array(
‘text’ => $this->language->get(‘text_home’),
‘href’ => $this->url->link(‘common/dashboard’, ‘token=’ . $this->session->data[‘token’], ‘SSL’)
);

$data[‘breadcrumbs’][] = array(
‘text’ => $this->language->get(‘text_module’),
‘href’ => $this->url->link(‘extension/module’, ‘token=’ . $this->session->data[‘token’], ‘SSL’)
);

if (!isset($this->request->get[‘module_id’])) {
$data[‘breadcrumbs’][] = array(
‘text’ => $this->language->get(‘heading_title’),
‘href’ => $this->url->link(‘module/categoryproduct’, ‘token=’ . $this->session->data[‘token’], ‘SSL’)
);
} else {
$data[‘breadcrumbs’][] = array(
‘text’ => $this->language->get(‘heading_title’),
‘href’ => $this->url->link(‘module/categoryproduct’, ‘token=’ . $this->session->data[‘token’] . ‘&module_id=’ . $this->request->get[‘module_id’], ‘SSL’)
);
}

if (!isset($this->request->get[‘module_id’])) {
$data[‘action’] = $this->url->link(‘module/categoryproduct’, ‘token=’ . $this->session->data[‘token’], ‘SSL’);
} else {
$data[‘action’] = $this->url->link(‘module/categoryproduct’, ‘token=’ . $this->session->data[‘token’] . ‘&module_id=’ . $this->request->get[‘module_id’], ‘SSL’);
}

$data[‘cancel’] = $this->url->link(‘extension/module’, ‘token=’ . $this->session->data[‘token’], ‘SSL’);

if (isset($this->request->get[‘module_id’]) && ($this->request->server[‘REQUEST_METHOD’] != ‘POST’)) {
$module_info = $this->model_extension_module->getModule($this->request->get[‘module_id’]);
}

$data[‘token’] = $this->session->data[‘token’];

if (isset($this->request->post[‘name’])) {
$data[‘name’] = $this->request->post[‘name’];
} elseif (!empty($module_info)) {
$data[‘name’] = $module_info[‘name’];
} else {
$data[‘name’] = ”;
}

$this->load->model(‘catalog/category’);  //使用分类

$data[‘categorys’] = array();
//定义分类数组

if (isset($this->request->post[‘category’]))
{
$data[‘categorys’] = $this->request->post[‘category’];
//如果有存在POST过来的category,直接视图上使用
}
else
{   //否则
$categorys = $this->model_catalog_category->getCategoryAll();
foreach ($categorys as $category)
{
$data[‘categorys’][] = array(
‘category_id’ => $category[‘category_id’],
‘name’       => $category[‘name’]
);
}
}
if (isset($this->request->post[‘limit’])) {
$data[‘limit’] = $this->request->post[‘limit’];
} elseif (!empty($module_info)) {
$data[‘limit’] = $module_info[‘limit’];
} else {
$data[‘limit’] = 8;
}

if (isset($this->request->post[‘width’])) {
$data[‘width’] = $this->request->post[‘width’];
} elseif (!empty($module_info)) {
$data[‘width’] = $module_info[‘width’];
} else {
$data[‘width’] = 200;
}

if (isset($this->request->post[‘height’])) {
$data[‘height’] = $this->request->post[‘height’];
} elseif (!empty($module_info)) {
$data[‘height’] = $module_info[‘height’];
} else {
$data[‘height’] = 300;
}

if (isset($this->request->post[‘status’])) {
$data[‘status’] = $this->request->post[‘status’];
} elseif (!empty($module_info)) {
$data[‘status’] = $module_info[‘status’];
} else {
$data[‘status’] = ”;
}

$data[‘header’] = $this->load->controller(‘common/header’);
$data[‘column_left’] = $this->load->controller(‘common/column_left’);
$data[‘footer’] = $this->load->controller(‘common/footer’);

$this->response->setOutput($this->load->view(‘module/categoryproduct.tpl’, $data));
}

protected function validate() {
if (!$this->user->hasPermission(‘modify’, ‘module/categoryproduct’)) {
$this->error[‘warning’] = $this->language->get(‘error_permission’);
}

if ((utf8_strlen($this->request->post[‘name’]) < 3) || (utf8_strlen($this->request->post[‘name’]) > 64)) {
$this->error[‘name’] = $this->language->get(‘error_name’);
}

if (!$this->request->post[‘width’]) {
$this->error[‘width’] = $this->language->get(‘error_width’);
}

if (!$this->request->post[‘height’]) {
$this->error[‘height’] = $this->language->get(‘error_height’);
}

return !$this->error;
}
}

OPENCART的模块如果有执行安装,数据不单只是追加到extension表.为什么呢?

因为opencart一个模块可以在多个地方使用.比如作者现在开发的主页显示指定分类的产品

可以选择分类ID为1,也可以添加为2,也可以添加为3等等.如果是同一个页面,一个位置,只是上下位不同,可以使用同一个视图类型.

来看看OPENCART是如何实现多元化的:

在module表内:

module_id=>模块ID

name=>模块名字(多元化的关键,一个模块派生出来的多个名字命名)

code=>模块参数(categoryproduct)

setting=>数值(JSON类型);

接着是前台获取模块参数的控制器,文中使用的视图请自行编写

class ControllerModuleCategoryproduct extends Controller
{
public function index($setting)
{
$this->load->language(‘module/categoryproduct’);
$data[‘heading_title’] = $this->language->get(‘categoryproduct’);
$this->load->model(‘catalog/category’);
$data[‘categoryname’]=$this->model_catalog_category->getCategoryname($setting[‘category’]);

$data[‘text_tax’] = $this->language->get(‘text_tax’);

$data[‘button_cart’] = $this->language->get(‘button_cart’);
$data[‘button_wishlist’] = $this->language->get(‘button_wishlist’);
$data[‘button_compare’] = $this->language->get(‘button_compare’);

if (!$setting[‘limit’]) {
$setting[‘limit’] = 4;
}  //如果没设置数量,那么数量为4

$this->load->model(‘catalog/product’);
$this->load->model(‘tool/image’);
//获取分类产品及图行工具模型
$category_id=$setting[‘category’]; //获取分类ID
$products_id=$this->model_catalog_product->getCategoryProducts($category_id);
$data[‘products’]=array();
for ($o=0;$o<count($products_id);$o++)
{
if ($o==$setting[‘limit’]) //判断循环提取的数量是否达到了要求
{
break;
}
$product_info = $this->model_catalog_product->getProduct($products_id[$o][‘product_id’]);
if ($product_info)
{
if ($product_info[‘image’])
{
$image = $this->model_tool_image->resize($product_info[‘image’], $setting[‘width’], $setting[‘height’]);
} else
{
$image = $this->model_tool_image->resize(‘placeholder.png’, $setting[‘width’], $setting[‘height’]);
}

if (($this->config->get(‘config_customer_price’) && $this->customer->isLogged()) || !$this->config->get(‘config_customer_price’)) {
$price = $this->currency->format($this->tax->calculate($product_info[‘price’], $product_info[‘tax_class_id’], $this->config->get(‘config_tax’)));
} else {
$price = false;
}

if ((float)$product_info[‘special’]) {
$special = $this->currency->format($this->tax->calculate($product_info[‘special’], $product_info[‘tax_class_id’], $this->config->get(‘config_tax’)));
} else {
$special = false;
}

if ($this->config->get(‘config_tax’)) {
$tax = $this->currency->format((float)$product_info[‘special’] ? $product_info[‘special’] : $product_info[‘price’]);
} else {
$tax = false;
}

if ($this->config->get(‘config_review_status’)) {
$rating = $product_info[‘rating’];
} else {
$rating = false;
}

$data[‘products’][$o] = array(
‘product_id’  => $product_info[‘product_id’],
‘thumb’       => $image,
‘name’        => $product_info[‘name’],
‘description’ => utf8_substr(strip_tags(html_entity_decode($product_info[‘description’], ENT_QUOTES, ‘UTF-8’)), 0, $this->config->get(‘config_product_description_length’)) . ‘..’,
‘price’       => $price,
‘special’     => $special,
‘tax’         => $tax,
‘rating’      => $rating,
‘href’        => $this->url->link(‘product/product’, ‘product_id=’ . $product_info[‘product_id’])
);
}
}
if ($data[‘products’])
{
if (file_exists(DIR_TEMPLATE . $this->config->get(‘config_template’) . ‘/template/module/categoryproduct.tpl’)) {
return $this->load->view($this->config->get(‘config_template’) . ‘/template/module/categoryproduct.tpl’, $data);
} else {
return $this->load->view(‘default/template/module/categoryproduct.tpl’, $data);
}
}
}
}

 

 

通过清心醉

opencart是如何实现管理员登陆的?

首先我们要知道一个:MVC设计模式的规则.

一般都是使用一个文件来做分发控制(如果是MAGNETO还有路由控制,当然OPENCART也可以使用VQMOD实现).

index.php就是OPENCART的分发控制:

看看这一句:$controller->addPreAction(new Action(‘common/login/check’));

实例化后的$controller调用方法:

注:OPENCART的一切数据基本使用$this->session对象,而用户基本使用$this->user对象.在这些对象里封装了获取购物车数据,用户数据等方法.

控制流程:

执行check()方法,如果不存在user_id($this->user->isLogged()的返回值),跳转到common/login的index方法(index为默认方法,具体可以查看controller的封装)

index()中,默认再一次判断是否存在有user对象的user_id值

如果存在跳转仪表盘.

接着,判断是否存在有POST的参数和是否合法:

if (($this->request->server[‘REQUEST_METHOD’] == ‘POST’) && $this->validate())

validate的方法原型::

/**
* 判断用户的登陆参数
* 错误的话返回flase;
*
* @return boolean
*/
protected function validate() {

if (!isset($this->request->post[‘username’])
|| !isset($this->request->post[‘password’])
|| !$this->user->shangjialogin($this->request->post[‘username’], $this->request->post[‘password’]))
{
$this->error[‘warning’] = $this->language->get(‘error_login’);
}
return !$this->error;
}

上文的红色字体中,就是作者新增加的模型方法,如果用户密码正确,返回true,否则false;

这样,就需要在模型里对$this->user类的私有成员user_id进行赋值.

成功达到管理员登陆的效果!

 

通过清心醉

opencart获取title的标准方法

PHP内置就有_get和_set的方式,虽然作者也没用过。但其实这两个魔术方法,_get就是获取数据,_set就是写入数据,这一点大家都应该有听过。

再来是OPENCART的获取页面标题的TITLE的方法。

由于OPENCART是使用MVC+L的设计模式,在C控制器层中,部分会有返回视图,比如头部(headert.tpl)和尾部(footer.tpl),这样设计的好处就是,头尾基本不会变,变的只是内容体,而头部有个需要变更的就是TITLE了。(至于描述及关键字一般不考虑,如果是产品一般直接UPDATE成产品的参数)

直接来上代码解释

假设我做了一个后台的支付管理插件,那么后台的支付管理插件的TITLE的获取是:

$this->load->language(‘paymunt/paypal’); //获取贝宝语言包
$this->document->setTitle($this->language->get(‘heading_title’));

第二句就是重中之重了。

如果你有用心观察OPENCART的每一个language都会发现第一个基本就是$_[‘heading_title’]。

没错,这就是给页面的标题用set的模式写进setTitle()方法处理

而且document是一个对象类型。

系统又是如何知道写入的标题是什么呢?

假设在一个控制器中(如PAYPAL)用了以上的方法。

先给TITLE赋值。

这就要特别注意作者前面说的,OPENCART使用的是MVC+L,头尾是以return 返回视图的方式。

所以说,在paypal控制器中写入了TITLE的值之后。

在使用:$data[‘header’]=$this->load->controller(‘common/header’);

 

以下是完整的:paypal控制器标题参数

$this->load->language(‘paymunt/paypal’); //获取贝宝语言包
$this->document->setTitle($this->language->get(‘heading_title’)); //写入参数到document对象中
$data[‘header’]=$this->load->controller(‘shangjia/header’); //头部直接调用

我们来看看header.php控制器中:

$data[‘title’] = $this->document->getTitle(); //直接调用每一个模型/插件的heading_title;

通过清心醉

OPENCART微信NATIVE-JSAPI支付插件

opencart微信NATIVE-JSAPI支付插件,完美支持最新2.0.3版本:

非DEMO类型的插件.
部分人使用DEMO来使用,用户就需要修改PHP的配置文件.

插件特点:
后台完全自定义:无需懂任何PHP代码.上传安装即可.

需要的后台参数:
1:绑定支付的APPID
2:公众帐号APPSECRET
3:商户支付密钥KEY
4:商户号MCHID
5:状态
6:启用微信二维码支付
7:启用微信客户端支付
8:订单已支付后的状态

注:
第6条和第7条为选择状态
即用户可以启用二维码扫描支付和微心客户端内的JSAPI来支付
由于JSAPI支付复杂,而且手机差的会卡,所以允许只打开一个来使用

其他说明:
二维码支付直接设置好了参数就可以使用.
至于JSAPI的支付,需要进入公众平台设置:
设置1:
进入公众平台-微信支付-开发配置-公众号支付-支付授权目录:
填写完整的域名(如):http://www.qingxinzui.com/catalog/controller/payment

设置2:
进入公众平台-开发者中心-配置项-网页服务-网页帐号-OAuth2.0网页授权:
填写完整的域名(如):qingxinzui.com
第一是JSAPI允许的请求路径和回调路径,第二是因为JSAPI需要获取用户的OPPENID信息.

需要的请到作者的网站购买.

通过清心醉

OPENCART 支付宝(ALIPAY)支付插件

opencart支付宝(alipay)支付插件包含企业版及个人版.
企业版默认打开电脑端及移动端支付.
个人版为担保交易,为了保证个人商家交易上的纠纷,由商家自行到alipay官网进行货运的跟踪.
后台需要设置以下几个参数:
1:合作者身份ID
2:交易安全校验码
3:支付宝帐户
4:选择项-状态
5:选择项-支付模式
6:选择项-订单已支付后的状态
注:
第5条为:
企业版模式为即时到帐收款,直接填写对应的参数值即可.
担保交易由于考虑到个人商家的利益,未添加自动执行发货.
原因是如果用户申请退款没有详细的发货记录会被取消订单. 请自行到官网进行发货
第6条为订单交易成功之后,订单的状态(提取后台所有订单状态模式,用户自行定义)

需要的请到作者的网站购买