一:采用Thinkphp5.0框架
Thinkphp5.0简介:
官网下载 和 composer(php依赖管理工具)安装。
目录结构:
application是应用目录,
index目录是模块目录:
模块目录下可以有控制器controller目录控制器直接命名Index.php这里和thinkphp3(IndexController.class.php)不一样了。
也可以在模块下创建model,view目录。
command.php是命令行工具配置。
common.php是公共函数。
config.php是应用公共函数前台可以直接调用。
database.php是数据库的配置文件。
route.php url路由配置文件。
tags.php 应用行为扩展配置文件。
extend目录:
扩展的类库
public目录:
对外部访问的目录
static目录下放的是静态资源(js,css,image)。
index.php文件是项目的入口文件。
router.php文件是快速测试文件。
runtime目录:
运行时候生成的文件。
vendor目录:
第三方类库
thinkphp目录:
thinkphp5核心类库目录。
build.php文件:
定义的自动生成定位文件。
think文件:
命令入口设置文件。
TP5神器-webserver
config.php里面设置
'default_return_type' => 'html',这样就能控制前台输出模式类型。
虚拟域名配置:
也可以使用集成工具配置phpstudy等方面的。
TP5自动化模块搭建
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <[email protected]>
// +----------------------------------------------------------------------
return [
// 生成应用公共文件
'__file__' => ['common.php', 'config.php', 'database.php'],
// 定义demo模块的自动生成 (按照实际定义的文件名生成)
/* 'demo' => [
'__file__' => ['common.php'],
'__dir__' => ['behavior', 'controller', 'model', 'view'],
'controller' => ['Index', 'Test', 'UserType'],
'model' => ['User', 'UserType'],
'view' => ['index/index'],
], */
// 其他更多的模块定义
'common' =>[
'__dir__' => ['model'],
'model' => ['Category', 'Admin'],
],
];
1.在app目录下创建了build.php文件
2.命令行切换到站点根目录下
3.使用命令 php think build
编写config.php配置文件修改静态文件路径。
view里面的页面如果存在公共部分的页面,应该放在一个目录里面作为公共使用。需要的页面只需要导入就可以了。
{include file="public/head,public/nav"} 这里和thinkphp3不太一样。<>变 { }。
url访问模式http://localhost/thinkphp5.0/index.php?s=index/user/register
http://localhost/thinkphp5.0/index.php/index/user/register 一样效果
s是模块,后面是控制器,然后方法如果页面的链接可以写成{:url('user/register')};tp5新特性
需求分析:
三大模块 商家模块:
主平台模块:
前台模块:
数据库设计:
数据表:
#生活分类表
CREATE TABLE o2o_category(
id int(11) unsigned NOT NULL auto_increment,
name VARCHAR(50) NOT NULL DEFAULT '',
parent_id int(10) unsigned NOT NULL DEFAULT 0,
listorder int(8) unsigned NOT NULL DEFAULT 0,
status tinyint(1) NOT NULL DEFAULT 0,
create_time int(11) unsigned NOT NULL DEFAULT 0,
update_time int(11) unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (id),
KEY parent_id(parent_id)
)ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
#城市表
CREATE TABLE o2o_city(
id int(11) unsigned NOT NULL auto_increment,
name VARCHAR(50) NOT NULL DEFAULT '',
uname VARCHAR(50) NOT NULL DEFAULT '',
parent_id int(10) unsigned NOT NULL DEFAULT 0,
listorder int(8) unsigned NOT NULL DEFAULT 0,
status tinyint(1) NOT NULL DEFAULT 0,
create_time int(11) unsigned NOT NULL DEFAULT 0,
update_time int(11) unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (id),
KEY parent_id(parent_id),
UNIQUE KEY uname(uname)
)ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
#商圈表
CREATE TABLE o2o_area(
id int(11) unsigned NOT NULL auto_increment,
name VARCHAR(50) NOT NULL DEFAULT '',
city_id int(11) unsigned NOT NULL DEFAULT 0,
parent_id int(10) unsigned NOT NULL DEFAULT 0,
listorder int(8) unsigned NOT NULL DEFAULT 0,
status tinyint(1) NOT NULL DEFAULT 0,
create_time int(11) unsigned NOT NULL DEFAULT 0,
update_time int(11) unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (id),
KEY parent_id(parent_id),
KEY city_id(city_id)
)ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
#商户表
CREATE TABLE o2o_bis(
id int(11) unsigned NOT NULL auto_increment,
name VARCHAR(50) NOT NULL DEFAULT '',
email VARCHAR(50) NOT NULL DEFAULT '',
logo VARCHAR(255) NOT NULL DEFAULT '',
licence_logo VARCHAR(255) NOT NULL DEFAULT '',
description text NOT NULL,
city_id int(11) unsigned NOT NULL DEFAULT 0,
city_path varchar(50) NOT NULL DEFAULT '',
bank_info varchar(50) NOT NULL DEFAULT '',
money decimal(20,2) NOT NULL DEFAULT '0.00',
bank_name varchar(50) NOT NULL DEFAULT '',
bank_user varchar(50) NOT NULL DEFAULT '',
faren varchar(20) NOT NULL DEFAULT '',
faren_tel varchar(20) NOT NULL DEFAULT '',
listorder int(8) unsigned NOT NULL DEFAULT 0,
status tinyint(1) NOT NULL DEFAULT 0,
create_time int(11) unsigned NOT NULL DEFAULT 0,
update_time int(11) unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (id),
KEY name(name),
KEY city_id(city_id)
)ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
#商户账户表
CREATE TABLE o2o_bis_account(
id int(11) unsigned NOT NULL auto_increment,
username VARCHAR(50) NOT NULL DEFAULT '',
password char(32) NOT NULL DEFAULT '',
code VARCHAR(10) NOT NULL DEFAULT '',
bis_id int(11) unsigned NOT NULL DEFAULT 0,
last_login_ip VARCHAR(30) NOT NULL DEFAULT '',
last_login_time int(11) unsigned NOT NULL DEFAULT 0,
is_main tinyint(1) unsigned NOT NULL DEFAULT 0,
listorder int(8) unsigned NOT NULL DEFAULT 0,
status tinyint(1) NOT NULL DEFAULT 0,
create_time int(11) unsigned NOT NULL DEFAULT 0,
update_time int(11) unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (id),
KEY username(username),
KEY bis_id(bis_id)
)ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
#商户门店表
CREATE TABLE o2o_bis_location(
id int(11) unsigned NOT NULL auto_increment,
name VARCHAR(50) NOT NULL DEFAULT '',
logo VARCHAR(255) NOT NULL DEFAULT '',
address VARCHAR(255) NOT NULL DEFAULT '',
tel VARCHAR(20) NOT NULL DEFAULT '',
contact VARCHAR(20) NOT NULL DEFAULT '',
xpoint VARCHAR(20) NOT NULL DEFAULT '',
ypoint VARCHAR(20) NOT NULL DEFAULT '',
bis_id int(11) unsigned NOT NULL DEFAULT 0,
open_time int(11) unsigned NOT NULL DEFAULT 0,
content text NOT NULL,
is_main tinyint(1) unsigned NOT NULL DEFAULT 0,
api_address VARCHAR(255) NOT NULL DEFAULT '',
city_id int(11) unsigned NOT NULL DEFAULT 0,
city_path varchar(50) NOT NULL DEFAULT '',
category_id int(11) unsigned NOT NULL DEFAULT 0,
category_path VARCHAR(50) NOT NULL DEFAULT '',
bank_info varchar(50) NOT NULL DEFAULT '',
listorder int(8) unsigned NOT NULL DEFAULT 0,
status tinyint(1) NOT NULL DEFAULT 0,
create_time int(11) unsigned NOT NULL DEFAULT 0,
update_time int(11) unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (id),
KEY name(name),
KEY city_id(city_id),
KEY bis_id(bis_id),
KEY category_id(category_id)
)ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
#团购商品表
CREATE TABLE o2o_deal(
id int(11) unsigned NOT NULL auto_increment,
name VARCHAR(100) NOT NULL DEFAULT '',
category_id int(11) NOT NULL DEFAULT 0,
se_category_id int(11) NOT NULL DEFAULT 0,
bis_id int(11) NOT NULL DEFAULT 0,
location_ids VARCHAR(100) NOT NULL DEFAULT '',
image VARCHAR(200) NOT NULL DEFAULT '',
description text NOT NULL,
start_time int(11) NOT NULL DEFAULT 0,
end_time int(11) NOT NULL DEFAULT 0,
origin_price decimal(20,2) NOT NULL DEFAULT '0.00',
current_price decimal(20,2) NOT NULL DEFAULT '0.00',
city_id int(11) NOT NULL DEFAULT 0,
buy_count int(11) NOT NULL DEFAULT 0,
total_count int(11) NOT NULL DEFAULT 0,
coupons_begin_time int(11) NOT NULL DEFAULT 0,
coupons_end_time int(11) NOT NULL DEFAULT 0,
xpoint VARCHAR(20) NOT NULL DEFAULT '',
ypoint VARCHAR(20) NOT NULL DEFAULT '',
bis_account_id int(10) NOT NULL DEFAULT 0,
balance_price decimal(20,2) NOT NULL DEFAULT '0.00',
notes text NOT NULL,
listorder int(8) unsigned NOT NULL DEFAULT 0,
status tinyint(1) NOT NULL DEFAULT 0,
create_time int(11) unsigned NOT NULL DEFAULT 0,
update_time int(11) unsigned NOT NULL DEFAULT 0,
PRIMARY KEY(id),
KEY category_id(category_id),
KEY se_category_id(se_category_id),
KEY city_id(city_id),
KEY start_time(start_time),
KEY end_time(end_time)
)ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
#用户账户表
CREATE TABLE o2o_user(
id int(11) unsigned NOT NULL auto_increment,
username VARCHAR(50) NOT NULL DEFAULT '',
password char(32) NOT NULL DEFAULT '',
code VARCHAR(10) NOT NULL DEFAULT '',
last_login_ip VARCHAR(30) NOT NULL DEFAULT '',
last_login_time int(11) unsigned NOT NULL DEFAULT 0,
email VARCHAR(30) NOT NULL DEFAULT '',
mobile VARCHAR(20) NOT NULL DEFAULT '',
listorder int(8) unsigned NOT NULL DEFAULT 0,
status tinyint(1) NOT NULL DEFAULT 0,
create_time int(11) unsigned NOT NULL DEFAULT 0,
update_time int(11) unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (id),
UNIQUE KEY username(username),
UNIQUE KEY email(email)
)ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
#推荐位表
CREATE TABLE o2o_featured(
id int(11) unsigned NOT NULL auto_increment,
type tinyint(1) NOT NULL DEFAULT 0,
title VARCHAR(30) NOT NULL DEFAULT '',
image VARCHAR(255) NOT NULL DEFAULT '',
url VARCHAR(255) NOT NULL DEFAULT '',
description VARCHAR(255) NOT NULL DEFAULT '',
listorder int(8) unsigned NOT NULL DEFAULT 0,
status tinyint(1) NOT NULL DEFAULT 0,
create_time int(11) unsigned NOT NULL DEFAULT 0,
update_time int(11) unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (id)
)ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
#订单表
CREATE TABLE o2o_order(
id int(11) unsigned NOT NULL auto_increment,
out_trade_no VARCHAR(100) NOT NULL DEFAULT '',
transaction_id VARCHAR(100) NOT NULL DEFAULT '',
user_id int(11) NOT NULL DEFAULT 0,
username VARCHAR(50) NOT NULL DEFAULT '',
pay_time VARCHAR(20) NOT NULL DEFAULT '',
payment_id tinyint(1) NOT NULL DEFAULT 1,
deal_id int(11) NOT NULL default 0,
deal_count int(11) NOT NULL default 0,
pay_status tinyint(1) NOT NULL DEFAULT 0,
total_price decimal(20,2) NOT NULL DEFAULT '0.00',
pay_amount decimal(20,2) NOT NULL DEFAULT '0.00',
status tinyint(1) NOT NULL DEFAULT 1,
referer VARCHAR(255) NOT NULL DEFAULT '',
create_time int(11) unsigned NOT NULL default 0,
update_time int(11) unsigned NOT NULL default 0,
PRIMARY KEY (id),
UNIQUE out_trade_no(out_trade_no),
key user_id(user_id),
key create_time(create_time )
)ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
后台模块页面搭建:
可以去官网下载开源代码。减少开发量,修改一下源代码就行了。
首先编写生活服务分类的管理模块。
创建好后台每一个功能,这里可能有公用的js代码,放在资源目录下里面包含弹出窗口填写表单提交。
提交的数据有一个表单add.html
<form class="form form-horizontal form-o2o-add" id="form-o2o-add" method="post" action="{:url('category/save')}">
<div class="row cl">
<label class="form-label col-xs-4 col-sm-2"><span class="c-red">*</span>生活服务分类名称:</label>
<div class="formControls col-xs-8 col-sm-9">
<input type="text" class="input-text" value="" placeholder="" id="name" name="name">
</div>
</div>
<div class="row cl">
<label class="form-label col-xs-4 col-sm-2"><span class="c-red">*</span>分类栏目:</label>
<div class="formControls col-xs-8 col-sm-9">
<span class="select-box">
<select name="parent_id" class="select">
<option value="0">一级分类</option>
{volist name="categorys" id="vo"}
<option value="{$vo.id}">--{$vo.name}</option>
{/volist}
</select>
</span>
</div>
</div>
<div class="row cl">
<div class="col-xs-8 col-sm-9 col-xs-offset-4 col-sm-offset-2">
<button type="submit" class="btn btn-primary radius" ><i class="Hui-iconfont"></i> 保存</button>
<button onClick="layer_close();" class="btn btn-default radius" type="button"> 取消 </button>
</div>
</div>
</form>
提交到Category控制器,接受数据的3种方法:
//print_r($_POST);
//print_r(input('post.'));
//print_r(request()->post());
public function save() {
//print_r($_POST);
//print_r(input('post.'));
//print_r(request()->post());
/**
* 做下严格判定
*/
if(!request()->isPost()) {
$this->error('请求失败');
}
$data = input('post.');
//dump($data);exit;
//halt($data);
//echo 12;exit;
///$data['status'] = 10;
//debug('begin');
$validate = validate('Category');
$data['name'] = htmlentities($data['name']);
if(!$validate->scene('add')->check($data)) {
$this->error($validate->getError());
}
if(!empty($data['id'])) {
return $this->update($data);
}
//debug('end');
//echo debug('begin', 'end','m');exit;
// 把$data 提交model层
$res = $this->obj->add($data);
if($res) {
$this->success('新增成功');
}else {
$this->error('新增失败');
}
}
thinkphp5.0验证机制 Validate。
<?php
namespace app\admin\validate;
use think\Validate;
class Category extends Validate {
protected $rule = [
['name', 'require|max:1000', '分类名必须传递|分类名不能超过10个字符'],
['parent_id','number'],
['id', 'number'],
['status', 'number|in:-1,0,1','状态必须是数字|状态范围不合法'],
['listorder', 'number'],
];
/**场景设置**/
protected $scene = [
'add' => ['name', 'parent_id', 'id'],// 添加
'listorder' => ['id', 'listorder'], //排序
'status' => ['id', 'status'],
];
}
conf.php配置文件默认设置分页每一页15条。
model查询数据库方法。
public function getFirstCategorys($parentId = 0) {
$data = [
'parent_id' => $parentId,
'status' => ['neq',-1],
];
$order =[
'listorder' => 'desc',
'id' => 'desc',
];
$result = $this->where($data)
->order($order)
->paginate();
//echo $this->getLastSql();
return $result;
}
返回分页结果数据。
public function index()
{
$parentId = input('get.parent_id', 0, 'intval');
$categorys = $this->obj->getFirstCategorys($parentId);
return $this->fetch('',[
'categorys'=>$categorys,
]);
}
控制器方法把数据传到页面上。
页面显示:
<div class="page-container">
<div class="cl pd-5 bg-1 bk-gray mt-20"> <span class="l"> <a class="btn btn-primary radius" onclick="o2o_s_edit('添加生活服务分类','{:url('category/add')}','','300')" ><i class="Hui-iconfont"></i> 添加分类</a></span> <span class="r"></span> </div>
<div class="mt-20">
<table class="table table-border table-bordered table-bg table-hover table-sort">
<thead>
<tr class="text-c">
<th width="40"><input name="" type="checkbox" value=""></th>
<th width="80">ID</th>
<th width="100">分类</th>
<th width="30">排序序号</th>
<th width="150">新增时间</th>
<th width="60">发布状态</th>
<th width="100">操作</th>
</tr>
</thead>
<tbody>
{volist name="categorys" id="vo"}
<tr class="text-c">
<td><input name="" type="checkbox" value=""></td>
<td>{$vo.id}</td>
<td>{$vo.name}</td>
<td class="text-c listorder"><input size="3" attr-id="{$vo.id}" name="listorder" value="{$vo.listorder}"/></td>
<td>{$vo.create_time|date="y-m-d h:i", ###}</td>
<td class="td-status"><a href="{:url('category/status',['id'=>$vo.id, 'status'=>$vo.status==1?0:1])}" title="点击修改状态">{$vo.status|status}</a></td>
<td class="td-manage"><a href="{:url('category/index',['parent_id'=>$vo.id])}">获取子栏目</a><a style="text-decoration:none" class="ml-5" onClick="o2o_s_edit('编辑','{:url('category/edit', ['id'=>$vo.id])}','',300)"title="编辑"><i class="Hui-iconfont"></i></a> <a style="text-decoration:none" class="ml-5" onClick="o2o_del('{:url('category/status', ['id'=>$vo.id, 'status'=>-1])}')" title="删除"><i class="Hui-iconfont"></i></a></td>
</tr>
{/volist}
</tbody>
</table>
</div>
</div>
{:pagination($categorys)}
其中使用的方法是后台的公共函数的方法。
{:pagination($categorys)}使用函数,或者{$categorys|pagination}这两种方法执行函数。
这样就实现了展示数据的页面。
在编辑按钮上编辑连接和数据:
这样点击按钮的时候,传递数据到控制器,控制器通过数据的id查找到分类,显示到编辑页面上。
<!--包含头部文件-->
{include file="public/header" /}
<body>
<div class="page-container">
<form class="form form-horizontal form-o2o-add" id="form-o2o-add" method="post" action="{:url('category/save')}">
<div class="row cl">
<label class="form-label col-xs-4 col-sm-2"><span class="c-red">*</span>生活服务分类名称:</label>
<div class="formControls col-xs-8 col-sm-9">
<input type="text" class="input-text" value="{$category->name}" placeholder="" id="name" name="name">
</div>
</div>
<div class="row cl">
<label class="form-label col-xs-4 col-sm-2"><span class="c-red">*</span>分类栏目:</label>
<div class="formControls col-xs-8 col-sm-9">
<span class="select-box">
<select name="parent_id" class="select">
<option value="0">一级分类</option>
{volist name="categorys" id="vo"}
<option value="{$vo.id}" {if condition="$category.parent_id eq $vo.id"} selected="selected"{/if}>--{$vo.name}</option>
{/volist}
</select>
</span>
</div>
</div>
<div class="row cl">
<input type="hidden" name="id" value="{$category->id}">
<div class="col-xs-8 col-sm-9 col-xs-offset-4 col-sm-offset-2">
<button type="submit" class="btn btn-primary radius" ><i class="Hui-iconfont"></i> 保存</button>
<button onClick="layer_close();" class="btn btn-default radius" type="button"> 取消 </button>
</div>
</div>
</form>
</div>
</div>
<!--包含头部文件-->
{include file="public/footer" /}
保存按钮是和添加按钮一样的。
这样就完成了分类的编辑。
接下来是分类的删除按钮。
public function status() {
$data = input('get.');
$validate = validate('Category');
if(!$validate->scene('status')->check($data)) {
$this->error($validate->getError());
}
$res = $this->obj->save(['status'=>$data['status']], ['id'=>$data['id']]);
if($res) {
$this->success('状态更新成功');
}else {
$this->error('状态更新失败');
}
}
$('.listorder input').blur(function() {
// 编写我们的抛送的逻辑
//获取主键id
var id = $(this).attr('attr-id');
// 获取排序的值
var listorder = $(this).val();
var postData = {
'id' : id,
'listorder':listorder,
};
var url = SCOPE.listorder_url;
// 抛送http
$.post(url, postData, function(result){
// 逻辑
if(result.code == 1) {
location.href=result.data;
}else {
alert(result.msg);
}
},"json");
});
protected $autoWriteTimestamp = true;
配置文件写也可以。
会自动把create_time创建为当前时间。
异步加载排序。
完成删除,这样分类管理就完成了。
第三方包封装:
通过地址获取经纬度;
首先自己生成第三方类,完成url链接:
<?php
/** 百度地图业务封装**/
class Map{
/**
* http://api.map.baidu.com/geocoder/v2/?address=北京市海淀区上地十街10号&output=json&ak=您的ak&callback=showLocation
* @param unknown $address **/
public static function getLngLat($address){
//拼装url
$date=[
'address'=>$address,
'ak'=>config('map.ak'),
'output'=>'json',
];
$url=config('map.baidu_map_url').config('map.geocoder').'?'.http_build_query($date);
$result =doCurl($url);
return $result;
}
public static function staticimage($center) {
if(!$center) {
return '';
}
$data = [
'ak' => config('map.ak'),
'width' => config('map.width'),
'height' => config('map.height'),
'center' => $center,
'markers' => $center,
];
$url = config('map.baidu_map_url').config('map.staticimage').'?'.http_build_query($data);
// 1 file_get_contents($url);
// 2 curl
$result = doCurl($url);
return $result;
}
}
返回的结果是一个url,这时候再写一个发送请求的类:
写在公共函数:
function doCurl($url,$type=0,$data=[]){
$ch = curl_init();//初始化
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
if($type==1){
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch,CURLOPT_POSTFIELDS,$data);
}
//执行并获取内容
$output=curl_exec($ch);
//释放
curl_close($ch);
return $output;
}
public static function getLngLat($address) {
if(!$address) {
return '';
}
//http://api.map.baidu.com/geocoder/v2/?callback=renderOption&output=json&address=百度大厦&city=北京市&ak=您的ak
$data = [
'address' => $address,
'ak' => config('map.ak'),
'output' => 'json',
];
$url = config('map.baidu_map_url').config('map.geocoder').'?'.http_build_query($data);
// 1 file_get_contents($url);
// 2 curl
$result = doCurl($url);
if($result) {
return json_decode($result, true);
}else {
return [];
}
//return $result;
}
同理这个是根据地址生成图片地址。
api参数配置文件的存放。config(mao.变量名)便可使用。
这就完成了百度地图api的封装。
打造属于TP5自己的发送邮件服务:
发送邮件开源包,其它的在126.com上注册账号开启服务便可以了。
修改testemail.php发送:
<?php
/**
* This example shows making an SMTP connection with authentication.
*/
//SMTP needs accurate times, and the PHP time zone MUST be set
//This should be done in your php.ini, but this is how to do it if you don't have access to that
header("content-type:text/html;charset=utf-8");
require 'class.phpmailer.php';
require 'class.smtp.php';
date_default_timezone_set('PRC');//set time
//Create a new PHPMailer instance
$mail = new PHPMailer;
//Tell PHPMailer to use SMTP
$mail->isSMTP();
//Enable SMTP debugging
// 0 = off (for production use)
// 1 = client messages
// 2 = client and server messages
$mail->SMTPDebug = 2; //用的时候这个应该注释 不然会输出代码
//Ask for HTML-friendly debug output
$mail->Debugoutput = 'html';
//Set the hostname of the mail server
$mail->Host = "smtp.126.com"; //发送者使用的邮件服务器
//Set the SMTP port number - likely to be 25, 465 or 587
$mail->Port = 25;
//Whether to use SMTP authentication
$mail->SMTPAuth = true;
//Username to use for SMTP authentication
$mail->Username = "[email protected]"; //发送者邮箱
//Password to use for SMTP authentication
$mail->Password = "AAAAAA123"; //客户端授权密码
//Set who the message is to be sent from
$mail->setFrom('[email protected]', 'zhw'); //发送者邮箱
//Set an alternative reply-to address
//$mail->addReplyTo('[email protected]', 'First Last');
//Set who the message is to be sent to
$mail->addAddress('[email protected]', 'zhw'); //邮件接收者邮箱
//Set the subject line
$mail->Subject = '邮件标题'; //发送邮件标题
//Read an HTML message body from an external file, convert referenced images to embedded,
//convert HTML into a basic plain-text alternative body
$mail->msgHTML('邮件正文'); //发送邮件正文
//Replace the plain text body with one created manually
//$mail->AltBody = 'This is a plain-text message body';
//Attach an image file
//$mail->addAttachment('images/phpmailer_mini.png');
//send the message, check for errors
if (!$mail->send()) {
echo "Mailer Error: " . $mail->ErrorInfo;
} else {
echo "Message sent success!";
}
<?php
/**
* 发送邮件类库
*/
namespace phpmailer;
use think\Exception;
class Email {
/**
* @param $to
* @param $title
* @param $content
* @return bool
*/
public static function send($to, $title, $content) {
date_default_timezone_set('PRC');//set time
if(empty($to)) {
return false;
}
try {
//Create a new PHPMailer instance
$mail = new PHPMailer;
//Tell PHPMailer to use SMTP
$mail->isSMTP();
$mail->Debugoutput = 'html';
//Set the hostname of the mail server
$mail->Host = config('email.host');
//Set the SMTP port number - likely to be 25, 465 or 587
$mail->Port = config('email.port');
//Whether to use SMTP authentication
$mail->SMTPAuth = true;
//Username to use for SMTP authentication
$mail->Username = config('email.username');
//Password to use for SMTP authentication
$mail->Password = config('email.password');
//Set who the message is to be sent from
$mail->setFrom(config('email.username'), 'ZHW');
//Set an alternative reply-to address
//$mail->addReplyTo('[email protected]', 'First Last');
//Set who the message is to be sent to
$mail->addAddress($to);
//Set the subject line
$mail->Subject = $title;
//Read an HTML message body from an external file, convert referenced images to embedded,
//convert HTML into a basic plain-text alternative body
$mail->msgHTML($content);
//Replace the plain text body with one created manually
//$mail->AltBody = 'This is a plain-text message body';
//Attach an image file
//$mail->addAttachment('images/phpmailer_mini.png');
//send the message, check for errors
if (!$mail->send()) {
return false;
//echo "Mailer Error: " . $mail->ErrorInfo;
} else {
return true;
}
}catch(phpmailerException $e) {
return false;
}
}
}
封装结果
商户模块:
包括用户,商户,主平台用户。
首先到登录页面,这边创建一个注册链接跳转到http://localhost/thinkphp5.0/index.php/bis/register/index.html页面
然后填充数据,提交,这里存在提交
等等信息,首先跳转到这个页面的控制器之前先获取一级城市和一集目录显示到页面上。
public function index()
{
//获取一级城市的数据
$citys = model('City')->getNormalCitysByParentId();
//获取一级栏目的数据
$categorys = model('Category')->getNormalCategoryByParentId();
return $this->fetch('',[
'citys' => $citys,
'categorys' => $categorys,
]);
}
然后将数据显示到页面上,选择一级城市后,写一个js函数在common.js里面只要一级城市变化,就发送异步请求到后台
api/city/getCitysByParentId()方法返回的结果是result 包括状态,信息,还有数据。
js:
/**城市相关二级内容**/
$(".cityId").change(function(){
city_id = $(this).val();
// 抛送请求
url = SCOPE.city_url;
postData = {'id':city_id};
$.post(url,postData,function(result){
//相关的业务处理
if(result.status == 1) {
// 将信息填充到html中
data = result.data;
city_html = "";
$(data).each(function(i){
city_html += "<option value='"+this.id+"'>"+this.name+"</option>";
});
$('.se_city_id').html(city_html);
}else if(result.status == 0) {
$('.se_city_id').html('');
}
}, 'json');
});
接下来的是图片上传的功能:
$(function() {
$("#file_upload").uploadify({
'swf' : SCOPE.uploadify_swf,
'uploader' : SCOPE.image_upload,
'buttonText' : '图片上传',
'fileTypeDesc' : 'Image files',
'fileObjName' : 'file',
'fileTypeExts' : '*.gif; *.jpg; *.png',
'onUploadSuccess' : function(file, data, response) {
console.log(file);
console.log(data);
console.log(response);
if(response) {
var obj = JSON.parse(data);
$("#upload_org_code_img").attr("src", obj.data);
$("#file_upload_image").attr("value", obj.data);
$("#upload_org_code_img").show();
}
}
});
$("#file_upload_other").uploadify({
'swf' : SCOPE.uploadify_swf,
'uploader' : SCOPE.image_upload,
'buttonText' : '图片上传',
'fileTypeDesc' : 'Image files',
'fileObjName' : 'file',
'fileTypeExts' : '*.gif; *.jpg; *.png',
'onUploadSuccess' : function(file, data, response) {
console.log(file);
console.log(data);
console.log(response);
if(response) {
var obj = JSON.parse(data);
$("#upload_org_code_img_other").attr("src", obj.data);
$("#file_upload_image_other").attr("value", obj.data);
$("#upload_org_code_img_other").show();
}
}
});
});
图片上传到的控制器:
<?php
namespace app\api\controller;
use think\Controller;
use think\Request;
use think\File;
class Image extends Controller
{
public function upload() {
$file = Request::instance()->file('file');
// 给定一个目录
$info = $file->move('upload');
if($info && $info->getPathname()) {
return show(1, 'success','/'.$info->getPathname());
}
return show(0,'upload error');
}
}
如果成功返回图片路径。
然后在js逻辑里面添加到页面上就可以了。
这里thinkphp5自带的上传图片或者文件方式和3不同是:
$file = Request::instance()->file('file');
// 给定一个目录
$info = $file->move('upload');
if($info && $info->getPathname()) {
return show(1, 'success','/'.$info->getPathname());
}
return show(0,'upload error');
以上之前也使用过了就不多说了。
public function index()
{
//获取一级城市的数据
$citys = model('City')->getNormalCitysByParentId();
//获取一级栏目的数据
$categorys = model('Category')->getNormalCategoryByParentId();
return $this->fetch('',[
'citys' => $citys,
'categorys' => $categorys,
]);
}
public function add() {
if(!request()->isPost()) {
$this->error('请求错误');
}
// 获取表单的值
$data = input('post.');
//检验数据
$validate = validate('Bis');
if(!$validate->scene('add')->check($data)) {
$this->error($validate->getError());
}
// 获取经纬度
// $lnglat = \Map::getLngLat($data['address']);
// if(empty($lnglat) || $lnglat['status'] !=0 || $lnglat['result']['precise'] !=1) {
// $this->error('无法获取数据,或者匹配的地址不精确');
// }
// 判定提交的用户是否存在
$accountResult = Model('BisAccount')->get(['username'=>$data['username']]);
if($accountResult) {
$this->error('该用户存在,请重新分配');
}
// 商户基本信息入库
$bisData = [
'name' => $data['name'],
'city_id' => $data['city_id'],
'city_path' => empty($data['se_city_id']) ? $data['city_id'] : $data['city_id'].','.$data['se_city_id'],
'logo' => $data['logo'],
'licence_logo' => $data['licence_logo'],
'description' => empty($data['description']) ? '' : $data['description'],
'bank_info' => $data['bank_info'],
'bank_user' => $data['bank_user'],
'bank_name' => $data['bank_name'],
'faren' => $data['faren'],
'faren_tel' => $data['faren_tel'],
'email' => $data['email'],
];
$bisId = model('Bis')->add($bisData);
// 总店相关信息检验
$data['cat'] = '';
if(!empty($data['se_category_id'])) {
$data['cat'] = implode('|', $data['se_category_id']);
}
// 总店相关信息入库
$locationData = [
'bis_id' => $bisId,
'name' => $data['name'],
'logo' => $data['logo'],
'tel' => $data['tel'],
'contact' => $data['contact'],
'category_id' => $data['category_id'],
'category_path' => $data['category_id'] . ',' . $data['cat'],
'city_id' => $data['city_id'],
'city_path' => empty($data['se_city_id']) ? $data['city_id'] : $data['city_id'].','.$data['se_city_id'],
'api_address' => $data['address'],
'open_time' => $data['open_time'],
'content' => empty($data['content']) ? '' : $data['content'],
'is_main' => 1,// 代表的是总店信息
'xpoint' => '125',
'ypoint' => '100',
];
$locationId = model('BisLocation')->add($locationData);
// 账户相关的信息检验
// 自动生成 密码的加盐字符串
$data['code'] = mt_rand(100, 10000);
$accounData = [
'bis_id' => $bisId,
'username' => $data['username'],
'code' => $data['code'],
'password' => md5($data['password'].$data['code']),
'is_main' => 1, // 代表的是总管理员
];
$accountId = model('BisAccount')->add($accounData);
if(!$accountId) {
$this->error('申请失败');
}
// 发送邮件
$url = request()->domain().url('bis/register/waiting', ['id'=>$bisId]);
$title = "o2o入驻申请通知";
$content = "您提交的入驻申请需等待平台方审核,您可以通过点击链接<a href='".$url."' target='_blank'>查看链接</a> 查看审核状态";
\phpmailer\Email::send($data['email'],$title, $content); // 线上关闭 发送邮件服务
$this->success('申请成功', url('register/waiting',['id'=>$bisId]));
}
完成注册发送邮件功能。
public function index() {
$bis = $this->obj->getBisByStatus(1);
return $this->fetch('', [
'bis' => $bis,
]);
}
将数据展现到页面上便可。
其它功能都差不多了。
public function index()
{
if(request()->isPost()) {
// 登录的逻辑
//获取相关的数据
$data = input('post.');
// 通过用户名 获取 用户相关信息
// 严格的判定
$ret = model('BisAccount')->get(['username'=>$data['username']]);
if(!$ret || $ret->status !=1 ) {
$this->error('改用户不存在,获取用户未被审核通过');
}
if($ret->password != md5($data['password'].$ret->code)) {
$this->error('密码不正确');
}
model('BisAccount')->updateById(['last_login_time'=>time()], $ret->id);
// 保存用户信息 bis是作用域
session('bisAccount', $ret, 'bis');
return $this->success('登录成功', url('index/index'));
}else {
// 获取session
$account = session('bisAccount', '', 'bis');
if($account && $account->id) {
return $this->redirect(url('index/index'));
}
return $this->fetch();
}
}
登录逻辑登录成功后将用户信息放入session中。并且跳转到后台管理页面
情况session
public function logout() {
// 清除session
session(null, 'bis');
// 跳出
$this->redirect('login/index');
}
模仿上方开发完成后台功能:
前台模块:
导入类库后直接使用 <div>{:captcha_img()}</div>就可以生成验证码了。
public function register()
{
if(request()->isPost()){
$data = input('post.');
if(!captcha_check($data['verifycode'])) {
// 校验失败
$this->error('验证码不正确');
}
//严格校验 tp5 validate
if($data['password'] != $data['repassword']) {
$this->error('两次输入的密码不一样');
}
// 自动生成 密码的加盐字符串
$data['code'] = mt_rand(100, 10000);
$data['password'] = md5($data['password'].$data['code']);
//$data = 12;// test
try {
$res = model('User')->add($data);
}catch (\Exception $e) {
$this->error($e->getMessage());
}
if($res) {
$this->success('注册成功',url('user/login'));
}else{
$this->error('注册失败');
}
}else {
return $this->fetch();
}
//QLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'singwa' for key 'username'
}
控制器方法如上
注册登录这里就不多说了。