如果您对PHP-电商项目-8感兴趣,那么本文将是一篇不错的选择,我们将为您详在本文中,您将会了解到关于PHP-电商项目-8的详细内容,我们还将为您解答php电商的相关问题,并且为您提供关于48套Jav
如果您对PHP-电商项目-8感兴趣,那么本文将是一篇不错的选择,我们将为您详在本文中,您将会了解到关于PHP-电商项目-8的详细内容,我们还将为您解答php 电商的相关问题,并且为您提供关于48 套 Java 大型分布式电商项目实战 \ 高并发 \ 集群 \ 分布式 \ 系统架构视频教程电商项目、Java电商项目-1.构建数据库,搭建项目环境、PHP 用redis做电商项目中的秒杀商品功能、PHP-电商项目-4的有价值信息。
本文目录一览:- PHP-电商项目-8(php 电商)
- 48 套 Java 大型分布式电商项目实战 \ 高并发 \ 集群 \ 分布式 \ 系统架构视频教程电商项目
- Java电商项目-1.构建数据库,搭建项目环境
- PHP 用redis做电商项目中的秒杀商品功能
- PHP-电商项目-4
PHP-电商项目-8(php 电商)
分布式全文搜索解决方案
1.解决方案介绍
ElasticSearch是一个基于RESTful web接口的分布式全文搜索引擎。
本解决方案是基于MysqL数据库 、 Hadoop生态(可选)、 ElasticSearch搜索引擎三大数据系统实现一个分布式全文搜索系统。
主要包括数据接入、数据索引和全文搜索3个模块。适用于各种项目的各种搜索场景。
1.1 三大数据系统
1.1.1 关系型数据库
用于对商品,用户等各种数据进行结构化存储。 关系型数据库对于事务性非常高的OLTP[^1]操作(比如订单,结算等)支持良好。
On-Line Transaction Processing联机事务处理,也称为面向交易的处理
主选:MysqL数据库
1.1.2 hadoop生态
Hadoop是一个由Apache基金会所开发的分布式系统基础架构。
Hadoop实现了一个分布式文件系统(Hadoop distributed File System),简称HDFS。
Hadoop的框架最核心的设计就是:HDFS和MapReduce。HDFS为海量的数据提供存储,而MapReduce则为海量的数据提供计算。
hadoop是数据仓库主要的载体,除了备份关系型数据库的所有版本,还存储用户行为,点击,曝光,互动等海量日志数据,hadoop对于数据分析,数据挖掘等OLAP[^2]操作支持比关系型数据库更加具有扩展性和稳定性。
On-Line Analytical Processing联机分析处理
Hive,基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供简单的SQL查询功能。
HBase,Hadoop的一个子项目,是一个分布式的、面向列的开源数据库。
Spark,专为大规模数据处理而设计的快速通用的计算引擎,可以在 Hadoop 文件系统中并行运行,作为对 Hadoop 的补充。
1.1.3 搜索引擎
以elasticsearch和solr为代表。搜索引擎是获取信息最高效的途径,几乎成为各类网站,应用的基础标配设施(地位仅次于数据库)。
ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。
1.2 基于ES的分布式搜索技术架构
2.软件安装
2.1 安装JDK
ElasticSearch是用JAVA语言开发的,其运行需要安装JDK。
JDK (Java Development Kit) ,是整个Java的核心,包括了Java运行环境(Java Runtime Envirnment),一堆Java工具和Java基础的类库(rt.jar)。
2.1.1 下载安装JDK
下载地址https://www.oracle.com/technetwork/java/javase/downloads/index.html
等待,出现以下界面,则安装完成,点击关闭即可
2.1.2 配置环境变量
配置 JAVA_HOME环境变量
配置Path环境变量
2.1.3 测试-查看JDK版本
打开命令行窗口,输入java -version
查看JDK版本
出现以上界面,说明安装成功。
2.2 安装Elasticsearch
权威指南https://www.elastic.co/guide/cn/elasticsearch/guide/current/index.html
2.2.1 下载安装
下载地址https://www.elastic.co/downloads
解压
2.2.2 配置Path环境变量
(bin目录)
2.2.3 启动elasticsearch
打开命令行窗口 执行命令 elasticsearch -d 启动elasticsearch
注:该命令行窗口 不要关闭。
浏览器打开 http://localhost:9200
出现以上界面,则启动成功。
2.2.4 目录解读
-
bin:启动文件
-
config:配置文件
- log4j2.properties:日志配置文件
- jvm.options:java虚拟机的配置
- elasticsearch.yml:es的配置文件
-
data:索引数据目录
-
lib:相关类库jar包
-
logs:日志目录
-
modules:功能模块
-
plugins:插件
.2.5(选装)安装Elasticsearch-Head
elasticsearch-head是一个用于浏览ElasticSearch集群并与其进行交互的Web项目
GitHub托管地址:https://github.com/mobz/elasticsearch-head
下载并解压:
安装:打开命令行,切换到Elasticsearch-Head目录,执行以下命令
npm install
启动:打开命令行,切换到Elasticsearch-Head目录,执行以下命令
npm run start
启动成功后,可通过http://localhost:9100进行访问
由于跨域(Elasticsearch位于9200端口),需要添加配置: E:\elasticsearch-7.1.0\config\elasticsearch.yml中
#新添加的配置行
http.cors.enabled: true
http.cors.allow-origin: "*"
重新启动
访问效果:
2.3 安装Elasticsearch-PHP
https://github.com/elastic/elasticsearch-php
使用composer安装:
在项目目录下,执行以下命令
composer require elasticsearch/elasticsearch
2.4 配置PHP.ini
配置PHP.ini的sys_temp_dir
否则,使用过程中可能会出现以下报错
3.ElasticSearch基本使用
3.1 基本概念
3.1.1 节点与集群
Elastic 本质上是一个分布式数据库,允许多台服务器协同工作,每台服务器可以运行多个 Elastic 实例。
单个 Elastic 实例称为一个节点(node)。一组节点构成一个集群(cluster)。
3.1.2 索引
在Elasticsearch中存储数据的行为就叫做索引(indexing)
在Elasticsearch中,文档归属于一种类型(type),而这些类型存在于**索引(index)**中
类比传统关系型数据库:
Relational DB -> Databases -> Tables -> Rows -> Columns
Elasticsearch -> Indices -> Types -> Documents -> Fields
Elasticsearch集群可以包含多个索引(indices)(数据库)
每一个索引可以包含多个类型(types)(表)
每一个类型包含多个文档(documents)(行)
然后每个文档包含多个字段(Fields)(列)。
3.2 基本使用
3.2.1 创建索引
$es = \Elasticsearch\ClientBuilder::create()->setHosts(['127.0.0.1:9200'])->build();
$params = [
'index' => 'test_index'
];
$r = $es->indices()->create($params);
dump($r);die;
预期结果:
array(3) {
["ackNowledged"] => bool(true)
["shards_ackNowledged"] => bool(true)
["index"] => string(10) "test_index"
}
3.2.2 添加文档(索引文档)
$es = \Elasticsearch\ClientBuilder::create()->setHosts(['127.0.0.1:9200'])->build();
$params = [
'index' => 'test_index',
'type' => 'test_type',
'id' => 100,
'body' => ['id'=>100, 'title'=>'PHP从入门到精通', 'author' => '张三']
];
$r = $es->index($params);
dump($r);die;
预期结果:
array(8) {
["_index"] => string(10) "test_index"
["_type"] => string(9) "test_type"
["_id"] => string(3) "100"
["_version"] => int(1)
["result"] => string(7) "created"
["_shards"] => array(3) {
["total"] => int(2)
["successful"] => int(1)
["Failed"] => int(0)
}
["_seq_no"] => int(0)
["_primary_term"] => int(1)
}
3.2.3 修改文档
$es = \Elasticsearch\ClientBuilder::create()->setHosts(['127.0.0.1:9200'])->build();
$params = [
'index' => 'test_index',
'type' => 'test_type',
'id' => 100,
'body' => [
'doc' => ['id'=>100, 'title'=>'ES从入门到精通', 'author' => '张三']
]
];
$r = $es->update($params);
dump($r);die;
预期结果:
array(8) {
["_index"] => string(10) "test_index"
["_type"] => string(9) "test_type"
["_id"] => string(3) "100"
["_version"] => int(2)
["result"] => string(7) "updated"
["_shards"] => array(3) {
["total"] => int(2)
["successful"] => int(1)
["Failed"] => int(0)
}
["_seq_no"] => int(1)
["_primary_term"] => int(1)
}
3.2.4 删除文档
$es = \Elasticsearch\ClientBuilder::create()->setHosts(['127.0.0.1:9200'])->build();
$params = [
'index' => 'test_index',
'type' => 'test_type',
'id' => 100,
];
$r = $es->delete($params);
dump($r);die;
预期结果:
array(8) {
["_index"] => string(10) "test_index"
["_type"] => string(9) "test_type"
["_id"] => string(3) "100"
["_version"] => int(3)
["result"] => string(7) "deleted"
["_shards"] => array(3) {
["total"] => int(2)
["successful"] => int(1)
["Failed"] => int(0)
}
["_seq_no"] => int(2)
["_primary_term"] => int(1)
}
3.3 封装工具类
封装操作es的工具类:项目目录/extends/tools/es/MyElasticsearch.PHP
<?PHP
namespace tools\es;
use Elasticsearch\ClientBuilder;
class MyElasticsearch
{
//ES客户端链接
private $client;
/**
* 构造函数
* MyElasticsearch constructor.
*/
public function __construct()
{
$params = array(
'127.0.0.1:9200'
);
$this->client = ClientBuilder::create()->setHosts($params)->build();
}
/**
* 判断索引是否存在
* @param string $index_name
* @return bool|mixed|string
*/
public function exists_index($index_name = 'test_ik')
{
$params = [
'index' => $index_name
];
try {
return $this->client->indices()->exists($params);
} catch (\Elasticsearch\Common\Exceptions\BadRequest400Exception $e) {
$msg = $e->getMessage();
$msg = json_decode($msg,true);
return $msg;
}
}
/**
* 创建索引
* @param string $index_name
* @return array|mixed|string
*/
public function create_index($index_name = 'test_ik') { // 只能创建一次
$params = [
'index' => $index_name,
'body' => [
'settings' => [
'number_of_shards' => 5,
'number_of_replicas' => 0
]
]
];
try {
return $this->client->indices()->create($params);
} catch (\Elasticsearch\Common\Exceptions\BadRequest400Exception $e) {
$msg = $e->getMessage();
$msg = json_decode($msg,true);
return $msg;
}
}
/**
* 删除索引
* @param string $index_name
* @return array
*/
public function delete_index($index_name = 'test_ik') {
$params = ['index' => $index_name];
$response = $this->client->indices()->delete($params);
return $response;
}
/**
* 添加文档
* @param $id
* @param $doc ['id'=>100, 'title'=>'phone']
* @param string $index_name
* @param string $type_name
* @return array
*/
public function add_doc($id,$doc,$index_name = 'test_ik',$type_name = 'goods') {
$params = [
'index' => $index_name,
'type' => $type_name,
'id' => $id,
'body' => $doc
];
$response = $this->client->index($params);
return $response;
}
/**
* 判断文档存在
* @param int $id
* @param string $index_name
* @param string $type_name
* @return array|bool
*/
public function exists_doc($id = 1,$index_name = 'test_ik',$type_name = 'goods') {
$params = [
'index' => $index_name,
'type' => $type_name,
'id' => $id
];
$response = $this->client->exists($params);
return $response;
}
/**
* 获取文档
* @param int $id
* @param string $index_name
* @param string $type_name
* @return array
*/
public function get_doc($id = 1,$index_name = 'test_ik',$type_name = 'goods') {
$params = [
'index' => $index_name,
'type' => $type_name,
'id' => $id
];
$response = $this->client->get($params);
return $response;
}
/**
* 更新文档
* @param int $id
* @param string $index_name
* @param string $type_name
* @param array $body ['doc' => ['title' => '苹果手机iPhoneX']]
* @return array
*/
public function update_doc($id = 1,$index_name = 'test_ik',$type_name = 'goods', $body=[]) {
// 可以灵活添加新字段,最好不要乱添加
$params = [
'index' => $index_name,
'type' => $type_name,
'id' => $id,
'body' => $body
];
$response = $this->client->update($params);
return $response;
}
/**
* 删除文档
* @param int $id
* @param string $index_name
* @param string $type_name
* @return array
*/
public function delete_doc($id = 1,$index_name = 'test_ik',$type_name = 'goods') {
$params = [
'index' => $index_name,
'type' => $type_name,
'id' => $id
];
$response = $this->client->delete($params);
return $response;
}
/**
* 搜索文档 (分页,排序,权重,过滤)
* @param string $index_name
* @param string $type_name
* @param array $body
* $body = [
'query' => [
'bool' => [
'should' => [
[
'match' => [
'cate_name' => [
'query' => $keywords,
'boost' => 4, // 权重大
]
]
],
[
'match' => [
'goods_name' => [
'query' => $keywords,
'boost' => 3,
]
]
],
[
'match' => [
'goods_introduce' => [
'query' => $keywords,
'boost' => 2,
]
]
]
],
],
],
'sort' => ['id'=>['order'=>'desc']],
'from' => $from,
'size' => $size
];
* @return array
*/
public function search_doc($index_name = "test_ik",$type_name = "goods",$body=[]) {
$params = [
'index' => $index_name,
'type' => $type_name,
'body' => $body
];
$results = $this->client->search($params);
return $results;
}
}
4.商品搜索功能
4.1 搜索规则
可根据关键词对商品名称、商品介绍、商品分类进行全文搜索
4.2 创建商品全量索引
项目目录/application/cli/controller/Es.PHP
<?PHP
namespace app\cli\controller;
use think\Controller;
use think\Request;
class Es extends Controller
{
/**
* 创建商品索引并导入全部商品文档
* cd public
* PHP index.PHP /cli/Es/createallGoodsDocs
*/
public function createallGoodsDocs()
{
try{
//实例化ES工具类
$es = new \tools\es\MyElasticsearch();
//创建索引
if($es->exists_index('goods_index')) $es->delete_index('goods_index');
$es->create_index('goods_index');
$i = 0;
while(true){
//查询商品数据 每次处理1000条
$goods = \app\common\model\Goods::with('category')->field('id,goods_name,goods_desc, goods_price,goods_logo,cate_id')->limit($i, 1000)->select();
if(empty($goods)){
//查询结果为空,则停止
break;
}
//添加文档
foreach($goods as $v){
unset($v['cate_id']);
$es->add_doc($v['id'],$v, 'goods_index', 'goods_type');
}
$i += 1000;
}
die('success');
}catch (\Exception $e){
$msg = $e->getMessage();
die($msg);
}
}
}
切换到public目录 执行命令
PHP index.PHP /cli/Es/createallGoodsDocs
注:其中,使用了封装的ES工具类 : 项目目录/extends/tools/es/MyElasticsearch.PHP
4.3 搜索
4.3.1 页面部分
项目目录/application/home/view/layout.html中,修改搜索框表单如下:
<form action="{:url('home/goods/index')}" method="get">
<!--searchAutoComplete-->
<div>
<input type="text" id="autocomplete"name="keywords" value="{$Request.param.keywords}" />
<buttontype="submit">搜索</button>
</div>
</form>
4.3.2 控制器部分
项目目录/application/home/controller/Goods.PHP中,修改index方法如下:
public function index($id=0)
{
//接收参数
$keywords = input('keywords');
if(empty($keywords)){
//获取指定分类下商品列表
if(!preg_match('/^\d+$/', $id)){
$this->error('参数错误');
}
//查询分类下的商品
$list = \app\common\model\Goods::where('cate_id', $id)->order('id desc')->paginate(10);
//查询分类名称
$category_info = \app\common\model\Category::find($id);
$cate_name = $category_info['cate_name'];
}else{
try{
//从ES中搜索
$list = \app\home\logic\GoodsLogic::search();
$cate_name = $keywords;
}catch (\Exception $e){
$this->error('服务器异常');
}
}
return view('index', ['list' => $list, 'cate_name' => $cate_name]);
}
4.3.3 搜索逻辑部分
项目目录/application/home/logic/GoodsLogic.PHP中,代码如下
<?PHP
namespace app\home\logic;
use think\Controller;
class GoodsLogic extends Controller
{
public static function search(){
//实例化ES工具类
$es = new \tools\es\MyElasticsearch();
//计算分页条件
$keywords = input('keywords');
$page = input('page', 1);
$page = $page < 1 ? 1 : $page;
$size = 10;
$from = ($page - 1) * $size;
//组装搜索参数体
$body = [
'query' => [
'bool' => [
'should' => [
[ 'match' => [ 'cate_name' => [
'query' => $keywords,
'boost' => 4, // 权重大
]]],
[ 'match' => [ 'goods_name' => [
'query' => $keywords,
'boost' => 3,
]]],
[ 'match' => [ 'goods_desc' => [
'query' => $keywords,
'boost' => 2,
]]],
],
],
],
'sort' => ['id'=>['order'=>'desc']],
'from' => $from,
'size' => $size
];
//进行搜索
$results = $es->search_doc('goods_index', 'goods_type', $body);
//获取数据
$data = array_column($results['hits']['hits'], '_source');
$total = $results['hits']['total']['value'];
//分页处理
$list = \tools\es\EsPage::paginate($data, $size, $total);
return $list;
}
}
4.3.4 ES分页类
借鉴模型的分页查询方法,封装用于ES搜索的分页类: 项目目录/extends/tools/es/EsPage.PHP
<?PHP
namespace tools\es;
use think\Config;
class EsPage
{
public static function paginate($results, $listRows = null, $simple = false, $config = [])
{
if (is_int($simple)) {
$total = $simple;
$simple = false;
}else{
$total = null;
$simple = true;
}
if (is_array($listRows)) {
$config = array_merge(Config::get('paginate'), $listRows);
$listRows = $config['list_rows'];
} else {
$config = array_merge(Config::get('paginate'), $config);
$listRows = $listRows ?: $config['list_rows'];
}
/** @var Paginator $class */
$class = false !== strpos($config['type'], '\\') ? $config['type'] : '\\think\\paginator\\driver\\' . ucwords($config['type']);
$page = isset($config['page']) ? (int) $config['page'] : call_user_func([
$class,
'getCurrentPage',
], $config['var_page']);
$page = $page < 1 ? 1 : $page;
$config['path'] = isset($config['path']) ? $config['path'] : call_user_func([$class, 'getCurrentPath']);
return $class::make($results, $listRows, $page, $total, $simple, $config);
}
}
商品列表页 商品分类展示位置
4.4 商品文档维护
新增商品后,在ES中添加商品文档
更新商品后,在ES中修改商品文档
删除商品后,在ES中删除商品文档
使用MVC的后台测试,则在admin/model/Goods.PHP中
使用前后端分离接口api测试,则写在common/model/Goods.PHP中
项目目录/application/admin/model/Goods.PHP中,init方法代码如下:
protected static function init()
{
//实例化ES工具类
$es = new \tools\es\MyElasticsearch();
//设置新增回调
self::afterInsert(function($goods)use($es){
//添加文档
$doc = $goods->visible(['id', 'goods_name', 'goods_desc', 'goods_price'])->toArray();
$doc['cate_name'] = $goods->category->cate_name;
$es->add_doc($goods->id, $doc, 'goods_index', 'goods_type');
});
//设置更新回调
self::afterUpdate(function($goods)use($es){
//修改文档
$doc = $goods->visible(['id', 'goods_name', 'goods_desc', 'goods_price', 'cate_name'])->toArray();
$doc['cate_name'] = $goods->category->cate_name;
$body = ['doc' => $doc];
$es->update_doc($goods->id, 'goods_index', 'goods_type', $body);
});
//设置删除回调
self::afterDelete(function($goods)use($es){
//删除文档
$es->delete_doc($goods->id, 'goods_index', 'goods_type');
});
}
5.总结
分布式全文搜索解决方案:是基于MysqL数据库 、 Hadoop生态(可选)、 ElasticSearch搜索引擎三大数据系统实现一个分布式全文搜索系统。
MysqL数据库用于结构化存储项目数据。
Hadoop生态用于备份关系型数据库的所有版本,还存储用户行为,点击,曝光,互动等海量日志数据,用于数据分析处理。
ElasticSearch搜索引擎用于对MysqL或者Hadoop提供的数据进行索引和全文搜索。
其中核心功能,包括全量创建索引、增量创建索引、实时同步数据(文档的curd)、全文搜索等。
48 套 Java 大型分布式电商项目实战 \ 高并发 \ 集群 \ 分布式 \ 系统架构视频教程电商项目
48 套 Java 大型分布式电商项目实战 \ 高并发 \ 集群 \ 分布式 \ 系统架构视频教程电商项目 48 套 Java 项目架构视频教程 - 高并发,微服务,分布式,需求分析,业务选型,项目部署,架构设计,架构师,源码分析,设计模式,数据结构,数据库,业务选型,中间件,并发编程,需求分析,需求设计,项目部署,云原生,企业架构,架构设计,大型项目实战视频课程
JAVA 高级架构师技术包含:SpringBoot3.0,SpringCloudAlibaba,JDK11~19,Spring6,IOC,AOP,JavaWeb,SpringMVC,Mybatis,Docker,k8s,Devops,Vue3.0,Nginx,Redis7,MongoDB,JDBC,ShardingJDBC,Zookeeper,Dubbo,Activiti7,ES8,RabbitMQ,Redisson,Shiro,Paas,Neo4j,Kafka,Mycat,Tcp,ELK,SpringData,Tcp,JWT, POI,JVM 项目实战,电商项目,金融项目,商业代驾项目,网约车项目,在线教育项目,头条项目,12306 售票系统,医疗云平台项目,数字货币交易项目,自媒体项目实战,游戏开发项目,Es 搜索项目,支付项目,外卖项目,防抖音短频项目,云尚办公系统,租房网项目,交友项目,房产项目,人力资源管理系统,餐掌柜项目,基础框架,源码分析,设计模式,数据结构,数据库,业务选型,中间件,并发编程,高并发,分布式,微服务,性能优化,分库分表,日志开发,需求分析,需求设计,项目部署,云原生,企业架构,架构设计,高级架构等视频教程……
下载链接:https://www.soft1188.com/javajg/6252.html
总目录:2023 年 48 套 Java 项目架构视频教程 - 高并发,微服务,分布式,需求分析,业务选型,项目部署,架构设计,架构师,源码分析,设计模式,数据结构,数据库,业务选型,中间件,并发编程,需求分析,需求设计,项目部署,云原生,企业架构,架构设计,大型项目实战视频课程
第 01 套:SpringBoot3.0 最新深入浅出从入门到项目实战,突出 Web 应用痛点解决方案视频教程
第 02 套:新一代微服务全家桶 AlibabaCloud+Docker+JDK11 阿里云容器部署零基础到项目实战课程
第 03 套:Spring6 深入 IoC 和 AOP 底层实现,手写框架实现 IoC,老鸟可以进一步掌握 Spring 底层
第 04 套:Vue3.0 前端全套视频教程(Kerwin 精通,Vue.js 零基础,Vue3 入门到精通到项目实战)
第 05 套:最新 Java 23 种设计模式详解教程(图解 + 框架源码剖析)内容全面通俗易通视频教程
第 06 套:Java 算法突击训练营,6 周彻底攻克数据结构与算法,40 道高频真题大厂算法面试视频教程
第 07 套:Java 架构师之源码分析专题 SpringBoot2.x、Spring5、SpringMVC、Mybatis 源码分析课程
第 08 套:深入浅出 JDK 安装及 Java9 到 Java19 新版本特性深度剖析视频课程,多版本讲解 一套拿捏
第 09 套:JavaWeb 课程精华版 Springmvc+Nginx+Redis+Docker+Mybatis+Mysql+JDBC+Zookeeper
第 10 套:Docker 企业级实战从入门到高阶(7 个深度 3 个全面)- 基础篇 + 提升篇 + 高级篇视频教程
第 11 套:K8S+Docker (安全网络存储监控)+Devops+GitOPS+Istio+Containerd 容器大师进阶之旅
第 12 套:新版 ShardingJDBC 分库分表 mysql 数据库实战,深入浅出核心知识点 + 高级 超多案例实战
第 13 套:构建 JVM 知识体系 解决 Java 工程师必会的工作面试难点,关于 JVM 的问题通通解决教程
第 14 套:全网最强 Redis7 十大专题分类讲解,20 年老司机高薪 & 实战一把过视频教程
第 15 套:Java 进阶 Activiti7 工作流系统精讲教程 Activiti 和 Spring 及 Springboot 框架项目整合视频课程
第 16 套:ES8 搜索引擎从入门到深度原理,实现综合运用实战 - 音乐 App 搜索项目 + 本地生活类 App 搜索项目
第 17 套:云原生架构进阶:基于工业级 PaaS 云平台的 Spring Cloud Alibaba 和 JDK 11 综合项目实战
第 18 套:6 大数据库,挖掘 7 种业务场景的数据库解决方案 MySQL、Redis、Neo4j、HBASE、MongoDB、ES 选型与开发
第 19 套:最新 Java 日志框架教程由浅入深全面精讲多种日志框架视频课程(log4j slf4j logback jul juc springboot )
第 20 套:Java 微服务体系 自媒体实战视频课程 SpringCloudAlibaba+Nginx+Zuul+Mysql+RabbitMQ+ES+Vue
第 21 套:多端全栈项目实战:大型商业级代驾业务全流程落地 SpringCloudAlibaba+Mysql+Redis+Docker+Uniapp+Vue3
第 22 套:Java 网约车实战 - 以网约车为例,切入分布式项目,互联网高并发项目需求分析(乘客端、司机端、车机端、大屏端)
第 23 套:Java 企业级实战开发《学成在线》微服务项目 SpringBoot+SpringCloud+MyBatis-Plus+Nginx+MQ+Redis+ES
第 24 套:亿级流量 Java 电商秒杀项目架构企业级视频课程 SpringCloud+Redis+Mycat+DDD+Docker+K8s+ShardingSphere
第 25 套:Java 企业级项目《尚上优选》SpringCloudAlibaba+Mybatis-Plus+Redisson+MQ+ES+Kibana+OSS+Knife4j+Nginx
第 26 套:Java 大型企业级 头条项目实战 Springboot+SpringCloudAlibaba+Docker+Vue+Mysql+Redis+Kafka+ES+MongoDB
第 27 套:体系化掌握 Java 分布式架构设计与开发实战,打通后端进阶关键一环,高性能、高并发、高可用的分布式架构
第 28 套:Java 零基础实训项目(东宝商城)课程 - 商品需求分析 + 商品中心设计 + 代码生成 + 验证码 + 代码安全 + 接口防篡改
第 29 套:Java 前后端分离分布式高并发医疗云平台 SpringCloudAlibaba+Shiro+RocketMQ+Docker+Mycat+Redis+Nginx
第 30 套:新版 Springboot3.0 打造能落地的高并发仿 12306 售票系统,带你学习各种高并发场景的解决方案视频课程
第 31 套:Java 企业级前后端分离 - 数字货币交易所项目 SpringCloud+MongoDB+Mysql+Redis+Kafka+MybatisPlus
第 32 套:Java 企业级瑞吉外卖项目实战 SpringBoot+Nginx+Mysql+Mybatis-Plus+Redis+VUE+H5+Git+Linux
第 33 套:P8 商城 - 大型互联网架构进行设计 - 三大部分:需求分析、软件设计开发、软件实施自动化部署架构视频课程
第 34 套:云尚办公系统 Java 企业级项目实战 SpringBoot+Vue+MybatisPlus+SpringSecurity+Redis+Activiti+Mysql
第 35 套:SpringBoot+Uniapp 实战开发仿抖音 App, 抓住短视频 Mybatis+MinIO+Nacos+MQ+MongoBD+redis+Nginx
第 36 套:SpringCloud+Vertx+Disruptor 证券金融业撮合交易系统实战,做金蝶动技领域的 IT 工程师视频课程
第 37 套:Java 前后端分离电商商城项目 SpringCloudAlibaba+RabbitMQ+Mysql+Solr+Redis+VSFTPD+Vue
第 38 套:Java 前后端分离企业级租房网项目 SpringBoot+Spring Cloud+SpringData+ES+MongoDB+Redis
第 39 套:Java 前后端分离探花交友项目 VUE+Dubbo+RabbitMQ+Redis+Mysql+MongoDB+SparkMllib+SpringCache
第 40 套:Java 尚好房项目 + 高薪提升课 SPringBoot+SpringCloud+Redis+Nginx+RabbitMQ+Docker+ES+Dubbo+Docker
第 41 套:Java 在线支付开发教程支付宝支付 & 微信支付项目实战视频课程,梳理流程关系,手把手的编写代码
第 42 套:SaaS-iHRM 人力资源管理系统 SpringBoot+SpringCloud+SpringData+Vue+Shiro+JWT+Activiti7+POI
第 43 套:MSB-Java 游戏开发真实项目 — 英雄传说 高并发游戏后端真实项目视频课程
第 44 套:多端基于 SaaS 的餐掌柜项目实战 - SpringCloudAlibaba+Vue+MQ+Redis+ES+TCP+Mysql+ELK+Docker
第 45 套:2023 版 Java 面试宝典 Java 面试 200 题(含美团 字节 阿里大厂真题及面试答题技巧)
第 46 套:资深 CTO & 架构师讲 Java 亿级项目架构设计与落地应用 - 需求分析 + 高层架构设计 + 系统架构设计 + 架构落地课程
第 47 套:MY-Java 架构师精英学习实战营 - 微服务 分布式 高并发 性能优化 企业架构 源码分析 运维部署 项目实战 设计框架
第 48 套:狂野架构师 - Java 架构师起步篇 + 进阶篇 + 深入篇 + 云原生篇 + 架构百宝箱篇 + 源码分析篇 + 架构设计篇 + 项目实战篇课程
48 套 Java 大型分布式电商项目实战 \ 高并发 \ 集群 \ 分布式 \ 系统架构视频教程电商项目 48 套 Java 大型分布式电商项目实战 \ 高并发 \ 集群 \ 分布式 \ 系统架构视频教程电商项目 48 套 Java 大型分布式电商项目实战 \ 高并发 \ 集群 \ 分布式 \ 系统架构视频教程电商项目 48 套 Java 大型分布式电商项目实战 \ 高并发 \ 集群 \ 分布式 \ 系统架构视频教程电商项目
Java电商项目-1.构建数据库,搭建项目环境
[toc]
到Github获取源码请点击此处
一. 数据库还原
- 新建Mysql数据库, 你可以使用自己熟悉的Mysql图形界面操作工具快速建库.
- 在新创建的ashop数据库中执行脚本文件
ashop.sql
. 该脚本存放在创建数据库的sql脚本
目录下.
- 成功导入后, 数据库将拥有11张表
二. Mybatis逆向生成工具的使用
- 接下来我们通过Mybatis逆向生成工具根据数据库表生成对应的pojo类和与Mybatis有关的文件.
- 首先在IDE中导入
Mybatis逆向生成工具/MybatisGenerator
项目, 修改generatorConfig.xml
文件中连接数据库的信息.
- 设置好后运行
GeneratorSqlmap
- 运行结束后我们会在
mapper
与pojo
包下获得逆向生成的与数据库有关的数据. - 我们先保留着这些文件, 在下面项目环境搭建的过程中将会拷贝这些文件. 有了逆向生成工具就不用手动生成这些数据了.
三. 搭建项目环境
- 项目的Maven结构如下:
- 在idea中先创建
ashop
Maven项目, 然后依次按层级创建好各个模块. 最后的结果如下图:
- 创建好Maven项目后需要为各个子模块添加依赖, 具体的依赖放在
项目中各个模块的pom依赖
目录下. - 接下来在
ashop-rpc-service-impl
模块的src/main/resource
目录下添加配置文件, 所有配置文件均放在resource(配置文件)
目录下.
- 接下来, 把之前用逆向生成工具生成的
pojo
类放到pojo
模块中(在java目录下创建com.ashop.pojo包
), 并把逆向工程生成的mapper
包下的mapper文件放到mapper模块中, 注意.java
和.xml
文件是要分开放的,.java
放在源码位置,.xml
放在resource
资源目录下 - 我项目做到这里的时候遇到了错误, Mapper文件报错, 原因是编译打包后mapper接口文件和.xml文件不在同一个包内. 原因是我在resources目录下建包的时候建错了...
- 至此为止项目的框架搭建完成.
四. 在linux虚拟机上部署zookeeper, 搭建Dubbo服务.
- 先新建一台linux虚拟机, 然后使用类似Xshell等工具将jdk和zookeeper的安装包上传到虚拟机中.
linux虚拟机安装JDK
- 下面是JDK的安装过程:
- 首先你需要把linux版本的JDK上传到虚拟机上.
- 创建java安装目录:
mkdir /usr/local/jdk
- 解压JDK压缩包:
tar zxvf 跟上JDK压缩包名
- 拷贝解压后的JDK到安装目录中:
cp -rf 解压JDK文件名 /usr/local/jdk/
- 配置环境变量: 打开编辑器
vi /etc/profile
, 追加以下内容
- 退出编辑器, 输入指令让环境变量生效:
source /etc/profile
- 最后输入
java
或javac
等指令检查是否配置成功.
安装zookeeper
- 首先把zookeeper的压缩包上传到linux虚拟机上
- 创建存放zookeeper的目录:
mkdir /usr/local/zookeeper
- 解压上传到虚拟机的zookeeper压缩包:
tar zxvf 压缩包名
- (演示拷贝)拷贝解压文件到安装目录:
cp -rf 解压文件名 /usr/local/zookeeper/zk1
- 进入
zk1
目录, 在当前目录下创建data目录:mkdir data
- 进入
data
目录, 并创建myid文件, 并在文件中输入1(作为第一个zookeeper的唯一标识):vi myid
, 输入1后保存退出
- 回到zk1目录, 进入conf目录, 拷贝默认配置文件:
cp zoo_sample.cfg zoo.cfg
. - 修改新的配置文件, 主要修改三个地方: 1. dataDir 2. client 3. 集群信息
- 配置完后继续拷贝2份zookeeper到
/usr/local/zookeeper
目录中, 我们要搭建集群, 三份zookeeper分别命名为zk1, zk2, zk3
- 注意zk2和zk3同样对配置文件要进行配置.
- 其中zk2的端口号配置为2182, zk3的端口号配置为2183, 除此之外配置文件最下面的集群部署三个配置文件都保持一致.
- 接着, 关闭防火墙:
service iptables stop
- 启动3个zookeeper服务:
./zk1/bin/zkServer.sh start
, 还要启动zk2和zk3... - 查看某个zookeeper的状态:
./zk1/bin/zkServer.sh status
- 连接zookeeper集群查看信息:
./zk1/bin/zkCli.sh
- 查看某个节点的信息:
ls /路径
- 查看某个节点保存的具体内容:
get /路径
- 提示: 你可以设置防火墙开放2181, 2182, 2183三个端口, 这样就不需要每次去手动关闭防火墙了.
五. 搭建ashop-manager-web项目
ashop-manager-web
模块的作用相当于普通BS项目中的后台. 只不过ashop-manager-web
通过调用远程方法完成对数据库的操作. 这就是SOA架构中面向服务的思想.- 首先在ashop项目下创建模块ashop-manager-web, 打包模式选择war包
- 给后端管理系统添加依赖, 首先需要依赖
service
模块, 然后导入相关的依赖, 依赖样本在后台管理系统的配置文件
目录中. - 在模块的
src/main/resource
目录下, 完成spring配置文件的配置. - 首先需要给出
applicationContext-service.xml
配置文件. - 然后是
applicationContext-dubbo.xml
配置文件 - 最后创建
springmvc.xml
配置文件 - 拷贝提供的静态资源到
ashop-manager-web
模块中. (拷贝到webapp中)
- 接下来在后端管理系统的java目录下创建
com.ashop.manager.controller
包, 并创建PageController
类, 在类中编写代码完成页面跳转以及管理后台首页的加载.
- 然后对
ashop
总项目进行install, 你可能会在install时遇到一些小错误, 静下心根据错误提示修改即可. - install完后到
ashop-manager-web
项目中, 使用tomcat7插件进行发布. (Maven命令-Tomcat7:run)
- 启动完毕后我们到浏览器的地址栏中输入
http://localhost:8080
, 即可进入商城的后台管理页面
- 到此为止, 环境搭建暂时告一段落. 下面补充数据库表的介绍
六. 数据库表分析
- 内容分类表:tb_content_category
列名 | 类型 | 含义 |
---|---|---|
id | bigint(20) | 内容分类 |
parent_id | bigint(20) | 父类目 ID=0 时,代表的是一级的类目 |
name | varchar(50) | 分类名称 |
status | int(1) | 状态:可选值:1(正常),2(删除) |
sort_order | int(4) | 排列序号,表示同级类目的展现次序,如数值相等 则按名称次序排列。取值范围:大于零的整数 |
is_parent | tinyint(1) | 该类目是否为父类目,1 为 true,0 为 false |
created | datetime | 创建时间 |
updated | datetime | 更新时间 |
- 内容表: 内容表:tb_content
列名 | 类型 | 含义 |
---|---|---|
id | bigint(20) | 主键 |
category_id | bigint(20) | 内容分类 ID |
title | varchar(200) | 内容标题 |
sub_title | varchar(100) | 子标题 |
title_desc | varchar(500) | 标题描述 |
url | varchar(500) | 链接 |
pic | varchar(300) | 图片绝对路径 |
pic2 | varchar(300) | 图片 2 |
content | text | 内容 |
created | datetime | 创建时间 |
updated | datetime | 更新时间 |
- 1.3 商品表:tb_item
列名 | 类型 | 含义 |
---|---|---|
id | bigint(20) | 商品 id,同时也是商品编号 |
title | varchar(100) | 商品标题 |
sell_point | varchar(500) | 商品卖点 |
price | bigint(20) | 商品价格,单位为:分 |
num | int(10) | 库存数量 |
barcode | varchar(30) | 商品条形码 |
image | varchar(500) | 商品图片,以逗号分隔的多个图片的 url 地址字符 串 |
cid | bigint(10) | 所属类目,叶子类目 |
status | tinyint(4) | 商品状态,1-正常,2-下架,3-删除 |
created | datetime | 创建时间 |
updated | datetime | 更新时间 |
- 1.4 商品分类表:tb_item_cat
列名 | 类型 | 含义 |
---|---|---|
id | bigint(20) | 商品分类 ID |
parent_id | bigint(20) | 父类目 ID=0 时,代表的是一级的类目 |
name | varchar(50) | 类目名称 |
status | int(1) | 状态。可选值:1(正常),2(删除) |
sort_order | int(4) | 排列序号,表示同级类目的展现次序,如数值相等 则按名称次序排列。取值范围:大于零的整数 |
is_parent | tinyint(1) | 该类目是否为父类目,1 为 true,0 为 false |
created | datetime | 创建时间 |
updated | datetime | 更新时间 |
- 商品描述表:tb_item_desc
列名 | 类型 | 含义 |
---|---|---|
item_id | bigint(20) | 商品 ID |
item_desc | text | 商品描述 |
created | datetime | 创建时间 |
updated | datetime | 更新时间 |
- 商品规格参数模板表:tb_item_param
列名 | 类型 | 含义 |
---|---|---|
id | bigint(20) 主键 | |
item_cat_id | bigint(20) | 商品分类 ID |
param_data | text | 规格参数模板信息 |
created | datetime | 创建时间 |
updated | datetime | 更新时间 |
- 商品规格参数信息表:tb_item_param_item
列名 | 类型 | 含义 |
---|---|---|
id | bigint(20) | 主键 |
item_id | bigint(20) | 商品 ID |
param_data | text | 规格参数信息 |
created | datetime | 创建时间 |
updated | datetime | 更新时间 |
- 订单表:tb_order
列名 | 类型 | 含义 |
---|---|---|
order_id | varchar(50) | 订单 id |
payment | varchar(50) | 实付金额。精确到 2 位小数;单位:元。如:200.07, 表示:200 元 7 分 |
payment_type | int(2) | 支付类型,1、在线支付,2、货到付款 |
post_fee | varchar(50) | 邮费。精确到2 位小数;单位:元。如:200.07,表示:200 元 7 分 |
status | int(10) | 状态:1、未付款,2、已付款,3、未发货,4、已 发货,5、交易成功,6、交易关闭 |
create_time | datetime | 订单创建时间 |
update_time | datetime | 订单更新时间 |
payment_time | datetime | 付款时间 |
consign_time | datetime | 发货时间 |
end_time | datetime | 交易完成时间 |
close_time | datetime | 交易关闭时间 |
shipping_name | varchar(20) | 物流名称 |
shipping_code | varchar(20) | 物流单号 |
user_id | bigint(20) | 用户 id |
buyer_message | varchar(100) | 买家留言 |
buyer_nick | varchar(50) | 买家昵称 |
buyer_rate | int(2) | 买家是否已经评价 |
- tb_order_item
列名 | 类型 | 含义 |
---|---|---|
id | varchar(20) | 主键 |
item_id | varchar(50) | 商品 id |
order_id | varchar(50) | 订单 id |
num | int(10) | 商品购买数量 |
title | varchar(200) | 商品标题 |
price | bigint(50) | 商品单价 |
total_fee | bigint(50) | 商品总金额 |
pic_path | varchar(200) | 商品图片地址 |
- 物流表:tb_order_shipping
列名 | 类型 | 含义 |
---|---|---|
order_id | varchar(50) | 订单 ID |
receiver_name | varchar(20) | 收货人全名 |
receiver_phone | varchar(20) | 固定电话 |
receiver_mobile | varchar(30) | 移动电话 |
receiver_state | varchar(10) | 省份 |
receiver_city | varchar(10) | 城市 |
receiver_district | varchar(20) | 区/县 |
receiver_address | varchar(200) | 收货地址,如:xx 路 xx 号 |
receiver_zip | varchar(6) | 邮政编码,如:310001 |
created | datetime | 创建时间 |
updated | datetime | 更新时间 |
- 用户表:tb_user
列名 | 类型 | 含义 |
---|---|---|
id | bigint(20) | 用户表主键 |
username | varchar(50) | 用户名 |
password | varchar(32) | 密码,加密存储 |
phone | varchar(20) | 注册手机号 |
varchar(50) | 注册邮箱 | |
created | datetime | 创建时间 |
updated | datetime | 更新时间 |
PHP 用redis做电商项目中的秒杀商品功能
参与过抢购活动就知道,很明显的一点是即便商品实际没有了也是可以下单成功的,但是在支付的时候会提示你商品没有了。
实现原理:list双向链表
使用redis队列,因为pop操作是原子的,即使有很多用户同时到达,也是依次执行.(mysql事务在高并发下性能下降很厉害,文件锁的方式也是).
此处用到了Redis中的链表(list)数据类型:
- ‘栈’:从链表的头部添加元素,先进后出
‘队列’:从链表的尾部添加元素,先进先出
redis保存数据时都有key和value,key和value要么是String类型的,要么是byte[]类型的
第一步:先将商品库存存入队列
<?php
//链接redis
$redis = new Redis();
$result = $redis->connect("127.0.0.1",6379);
//设置100件商品库存
$goods_number = 100;
//将100件商品存入到Redis链表中
for($i=0;$i<$goods_number;$i++){
//lpush从链表的头部添加元素
$redis->lpush(''goods_store'',1);
}
//llen返回列表key的长度
echo $redis->llen(''goods_store'');
?>
第二步:抢购开始,设置库存的缓存周期
<?php
//第二步,抢购开始,设置库存的缓存周期
//设定一个key的活动时间
$redis->setTimeout(''goods_store'',60);
?>
第三步:客户端执行下单操作,下单前判断redis队列库存量
<?php
//第三步,客户端执行下单操作,下单前判断redis队列库存量
$redis = new Redis();
$redis->connect("127.0.0.1",6379);
//从链表的头部删除一个元素,返回删除的元素,$count为true
$count = $redis->lpop(''goods_store'');
if(!count){
echo "抢购失败";
return;
}
PHP-电商项目-4
十九、添加完整商品数据
使用后台管理系统,添加完整商品数据。用于测试及前台页面展示。
添加三级商品分类(一般有现成的测试数据)
添加品牌(在一个三级分类下添加至少一个品牌)
添加商品类型(商品模型)(至少两个规格,每个规格至少两个规格值。至少两个属性)
添加商品(选择分类、选择品牌、上传logo图片、上传相册图片、选择商品类型、每种规格至少选择两个规格值)
一、前台模板整合
以home模块作为前台网站模块。
设置默认模块:application/config.PHP
// 默认模块名
'default_module' => 'home',
模板整合思路:
①确定页面的访问路径(模块、控制器、方法)
②新建对应的控制器方法,在方法中调用模板
③将模板页面移动到对应的视图目录下(创建子目录)
④将静态资源文件移动到public/static/home目录下
⑤修改模板文件中静态资源路径
页面分布:
首页 Index控制器index方法 JD-index.html -> index.html
商品列表 Goods控制器index方法 list.html -> index.html
商品详情 Goods控制器detail方法 item.html ->detail.html
登录页 Login控制器login方法 login.html
注册页 Login控制器register方法 register.html
成功加入购物车 Cart控制器addcart方法 success-cart.html -> addcart.html
购物车列表 Cart控制器index方法 cart.html -> index.html
结算页 Order控制器create方法 getorderInfo.html -> create.html
1、前台首页
①确定页面的访问路径(模块、控制器、方法)
home模块 Index控制器 index方法
②新建对应的控制器方法,在方法中调用模板
home模块新建index控制器,index方法,并调用模板
③将模板页面移动到对应的视图目录下
将JD-index.html移动到application/home/view/index目录下 改名为index.html
注:TP框架中,模板中的静态资源路径,不能使用相对路径./ ,必须使用以/开头的路径。
2、其他页面
重复步骤①②③⑤
3、全局布局
(见手册–模板–模板布局)
使用模板布局,就是把许多模板页面都有的公共代码给抽取出来,放到一个公共位置开发维护,这样做的好处是:相同的代码只维护一份,减少代码工作量
①使用全局布局
修改配置文件application/home/config.PHP,加入以下设置
'template' => [
'layout_on' => true,//开启布局
'layout_name' => 'layout',//布局文件名称
]
在home模块view目录下创建layout.html文件,将前台页面公共的头部、底部HTML代码提取到layout.html中,在中间位置放一个特殊字符串“{_CONTENT_}”,
表示此位置,替换为原始要访问的页面内容。
layout.html中 css和js文件 只放 all.css 和 all.js
原始模板页面保留主体部分代码和页面独有的css、js引入代码即可:
首页 view/index/index.html中,保留首页需要的js和css
注:绝对不能把所有的js、css文件全部放到layout.html中,这样容易互相影响。
4、临时关闭模板布局
全局布局设置,对所有页面全部生效。
特殊页面(不需要使用布局的页面),可以在控制器方法中,临时关闭模板布局。
$this->view->engine->layout(false);
比如登录页面,不需要使用布局
创建控制器
PHP think make:controller home/Login --plain
模板整合过程同首页。
注意:如果页面显示效果不对,可以考虑先删除缓存 runtime目录
二、手机号注册
1、简单注册
步骤:
整合模板
完善表单
提交表单添加用户
页面跳转
实现:
创建用户User模型
PHP think make:model common/User
整合模板(home模块Login控制器register方法)(具体步骤略)
完善表单
js提交表单
提交表单(home模块Login控制器phone方法)
2、短信接口
场景:通常在使用手机号注册时需要发送短信验证码,在修改密码等敏感操作时也需要验证手机号发送短信验证码。
短信验证码的目的:验证用户的身份是否本人
在项目代码中发送短信,通常要调用第三方短信商的短信发送接口。
提供短信接口的平台:百度Apistore数据平台、聚合数据平台、京东万象等等
一般情况下,短信接口需要企业认证用户才能申请、一般都是收费的。
以京东万象为例:个人可以购买使用
进入短信API页面
选择一个短信接口
接口介绍:(请求地址、请求方式、请求参数、返回参数等)
接口的购买使用注意事项:
短信接口一般都有一个 模板报备 的概念,需要把发送的短信内容的格式先报备给短信商,
后续发短信的过程,只有满足报备格式的短信才能发送成功。
京东万象的短信接口需要APP KEY, 可以使用京东的帐号进行登录,登录之后可以查看到APPKEY
3、封装发送短信功能
发送短信功能:
将接口地址和appkey放在配置文件application/config.PHP
封装使用curl发送请求的函数curl_request函数 application/common.PHP
封装一个函数sendmsg用于发送短信application/common.PHP
4、手机号注册-发送短信验证码
功能点:发送短信验证码、基本的注册效果、倒计时效果
需要创建User模型
PHP think make:model common/User
①修改view/login/register.html,在手机号注册时,点击“发送验证码”,
发送ajax请求
②login控制器sendcode方法,用于ajax请求发送短信验证码
③浏览器上测试时,在调试工具栏Network查看验证码
5、手机号注册-校验短信验证码
sendcode方法发送验证码时,将验证码保存到缓存(手机号–验证码)
Login控制器phone方法,处理表单提交(验证码校验)
6、短信发送限制
①前端限制发送频率-倒计时效果
思路:
给“发送验证码”标签绑定的点击事件中
设置一个定时器,每隔1s执行一次代码(setInterval)
执行的代码中,需要修改标签的内容并禁用button的点击效果(表单元素disabled属性)
当倒计时结束,将标签的内容还原,设置button可以继续点击
②后端限制发送频率(同一个手机号,一分钟只能发一次)
原理:
每次发送成功,记录发送时间。
每次发送之前,进行频率检测。( 当前时间 - 上次发送时间 < 60 发送太频繁)
实现:
每次发送成功,记录发送时间
每次发送之前,检测发送频率
③设置验证码有效期(记录验证码时,在缓存中设置有效期)
④设置验证码验证成功一次后,失效
在注册的表单提交后,验证码验证成功,将其从缓存中删除
更多验证:
限制ip(同一个ip一天只能发送多少次) 框架中请求对象request的ip方法获取ip地址
限制手机号(同一个手机号一天只能发送多少次)
三、账号密码登录
1、前台用户登录
①整合模板:访问路径 Login控制器login方法login.html
②确认表单完整性 name属性值 提交地址
给“登录”a标签绑定事件,使用js提交表单
③Login控制器dologin方法,处理表单提交
第一种写法:根据用户名和密码一起查询用户表
混合查询(where 条件中包含or条件,使用闭包函数方式)
第二种写法:根据用户名查询用户表,比对密码
2、前台用户退出
退出时,清空所有的session, 跳转到登录页或者首页。
3、优化前台首页头部显示
根据登录状态,页面头部显示的信息需要对应变化:
封装一个对手机号加密的函数 application/common.PHP
注册时,将加密手机号设置为默认昵称
修改view/layout.html, 根据登录状态显示
四、QQ互联接口
1、介绍
现在很多网站都集成了第三方帐号登录的功能,比如QQ登录、微信登录、微博登录。
使用第三方帐号登录目的,简化用户注册的流程,实现快速的注册登录。
第三方登录基本流程:①跳转到第三方认证页面 ②回调地址中的处理
2、签约
QQ登录接口,使用也需要申请。
腾讯开放平台:https://open.tencent.com/
腾讯开放平台注册:http://open.qq.com/reg
QQ互联平台网站:https://connect.qq.com/
点击应用管理,会要求登录
登录之后,点击应用管理,第一次登录此平台会要求注册成为开发者
分为公司接入和个人接入。
公司接入需要营业执照信息。这里我们平时使用可以选择个人接入
注册成功之后等待审核,通过之后进入应用管理
审核通过之后可以创建应用了。
选择创建网站应用
进入资料填写页面,填写完成提交
提交成功之后,需要继续完善相关信息
创建成功,进入应用管理页面,可以看到刚创建的应用处于审核中状态
审核成功和审核失败状态下,操作栏都有一个查看按钮,可以点击查看应用详情
参考:
APP ID :101542020
APP Key :539cd4f7784f107fa74ad58d87b5c916
回调地址:http://www.tpshop.com/index.php/home/login/qqcallback
说明:不管审核成功还是审核失败,qq登录的接口都可以使用,区别是,审核成功后所有人的qq都可以登录,审核失败只有申请人的qq可以正常登录。
为了测试qq登录,重新配置一个域名 www.tpshop.com 指向 pyg/public目录
3、SDK的下载和配置
在QQ互联平台网站,点击 “文档资料”
在页面找到网站接入 sdk PHP版本
SDK配置:
①将解压后的目录,移动到public/plugins/目录下,改名为qq
②在浏览器直接访问:域名/plugins/qq/index.PHP
③点击“设置配置项”,进入配置页面
按照要求填写相关的信息,点击“配置”
③点击“查看example”,打开测试页面。
点击“用QQ帐号登录”,可以打开qq登录的小窗口。
④按照回调域,在Home模块Login控制器新增qqcallback方法
⑤重新测试,使用qq帐号登录,小窗口会发生跳转,访问qqcallback方法。
4、QQ互联接口的集成
①分析SDK中的example页面index.html中的代码
参考:public/plugins/qq/example/index.html文件
②参考example中的做法,修改view/login/login.html
预期效果:点击登录页面“QQ登录”,当前页面跳转到qq登录页面
③修改Login控制器qqcallback方法,获取用户信息
获取用户信息
用户数据如下:
④修改Login控制器qqcallback方法,实现第三方用户登录后自动注册登录
⑤预期效果:登录成功,跳转到首页。
五、商品相关页面显示
1、商品分类展示
两个概念:
商品类型(商品模型):用于后台,管理商品规格属性的,只有一级。
商品分类:用于前台,展示商品的,有多级(三级)。
如果尚未创建Category商品分类模型,则执行以下命令创建Category模型
PHP think make:model common/Category
商品分类在前台展示:(商品分类属于公共头部代码)
1)父子级分类树结构:(最终读取数据时,遍历次数少)
查询到所有分类数据后,先将数组转化为分类树结构,方便页面展示
树结构示例:
需要用到封装的处理函数application/common.PHP中的get_tree_list函数
2)功能实现
①在前台模块创建Base控制器,在其构造方法,查询商品分类数据并转化为树结构
PHP think make:controller home/Base --plain
②所有其他控制器(Login控制器除外),继承Base控制器
比如 Index控制器,继承Base
③修改view/layout.html, 展示商品分类数据
展示二级、三级分类
2、商品列表展示
如果尚未创建商品模型,则执行以下命令创建商品模型:
PHP think make:model common/Goods
商品列表,展示某个分类下的商品。比如分类id为187的 “手机” 分类
页面整合(略):Home模块Goods控制器index方法 list.html -> index.html
创建Goods控制器,需要继承Base控制器
PHP think make:controller home/Goods --plain
①在Goods控制器index方法,查询分类下的商品数据以及分类名称
②在view/goods/index.html,展示分类下的商品
遍历展示商品列表:
展示分页栏:
③当前分类名称展示
3、商品详情页
整合页面(略): Home模块 Goods控制器 detail方法,item.html ->detail.html
1)分析商品详情页需要的数据。
①商品基本信息,查询商品表pyg_goods表,以goods_id为条件 主键id
②商品相册图片,查询商品相册表pyg_goods_images表,以goods_id为条件
③规格商品SKU,查询规格商品表pyg_spec_goods表,根据goods_id条件
④根据规格商品信息,查询对应规格名称规格值信息
2)如果尚未创建模型,则创建GoodsImages、SpecGoods、Spec、SpecValue模型
3)商品信息展示:
①基本信息展示:
Goods控制器detail方法,查询商品基本信息
home/view/goods/detail.html,展示商品基本信息
商品名称、商品价格
商品属性、商品详情
②商品相册信息展示
home/view/goods/detail.html 展示商品相册图片
③商品SKU(规格商品)展示
Goods控制器detail方法,查询商品SKU、查询对应规格名称规格值
转化数组结构: 取出所有相关的规格值ids
查询规格值规格名称信息,组装数组结构
home/view/goods/detail.html展示商品SKU
4、商品详情页-规格值选中效果
view/goods/detail.html中,规格值选中效果
Goods控制器detail方法中,组装数组,描述 规格值组合对应的规格商品SKU的id 的映射关系
将映射关系数组 转化为json字符串
view/goods/detail.html 中 给规格值a标签,添加自定义属性spec_value_id 保存规格值id, 用于js中获取
在规格值的点击事件中,根据选中的规格值的组合,在页面显示对应的价格。
页面默认显示 商品的第一个SKU的价格
view/goods/detail.html 中 给“加入购物车” 加id属性,禁用href属性
加入购物车,绑定点击事件,获取选中的规格商品id值。
关于PHP-电商项目-8和php 电商的问题我们已经讲解完毕,感谢您的阅读,如果还想了解更多关于48 套 Java 大型分布式电商项目实战 \ 高并发 \ 集群 \ 分布式 \ 系统架构视频教程电商项目、Java电商项目-1.构建数据库,搭建项目环境、PHP 用redis做电商项目中的秒杀商品功能、PHP-电商项目-4等相关内容,可以在本站寻找。
本文标签: