SQL的CONCAT()函数实例:无限级分类排序

SQL语句:
SELECT * FROM `shop_catalog` order by CONCAT(`path`, `id`)

Select Code
1
2
3
4
5
6
7
8
9
10
/*
  遍历分类
  */
  $sql = "SELECT * FROM `shop_catalog` order by CONCAT(`path`, `id`)";
  $res = mysqli_query($conn, $sql);
  while ($row=mysqli_fetch_assoc($res)) {
    $list_cata[] = $row;
    $list_catapid[] = $row['pid'];
  }
  mysqli_free_result($res);

查询结果如图:
concat_01

分类列表下拉效果:

Select Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<table border="0" width="80%">
<tr>
  <td width="100" align="right">所属分类</td>
  <td><select name="cata_id" class="form-control" style="width:200px;">
  <option value="0">---选择所属的分类---</option>
  <?php 
    foreach ($list_cata as $key => $val) {
      $path = $val['path'];
      $num = substr_count($path, ',');
      $str_blank = str_repeat('+    ', $num-1);
      $value_id = " value='".$val['id']."'";
      $disabled = NULL;
      if (in_array($val['id'], array_unique($list_catapid))) {
        $value_id = null;
        $disabled = " disabled class='disabled'";
      }
      echo "<option{$value_id}{$disabled}>{$str_blank}{$val['name']}</option>";
    }
  ?>
  </select></td>
</tr>

concat_02

PHP实现无限级分类实例数据分析演示

无限级分类的数据库结构设计:
unlimited_catagories1

测试数据下载地址:
https://github.com/webjust/case-study/tree/master/unlimited%20catagories

测试数据库表结构:

Select Code
1
2
3
4
5
6
7
8
9
CREATE TABLE `shop_catalog` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `pid` int(11) unsigned NOT NULL,
  `name` varchar(255) NOT NULL,
  `title` varchar(255) NOT NULL,
  `description` varchar(255) NOT NULL,
  `path` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

在网页上显示的效果:
unlimited_catagories2

部分源代码如下:

第1步:从数据库遍历pid=0的分类

Select Code
1
2
3
4
5
6
7
8
9
10
11
12
13
<?php 
$conn = mysqli_connect('localhost', 'root', '', 'ishop') or die("数据库连接失败");
mysqli_set_charset($conn, 'utf8');

// 一级分类
$sql = "SELECT id,pid,name,path FROM `shop_catalog` WHERE `pid` = 0";
$res = mysqli_query($conn, $sql);
if ($res) {
	while($row = mysqli_fetch_assoc($res)){
		$cata1_list[] = $row;
	}
}
?>

第2步:嵌套循环遍历全部的分类

Select Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?php foreach($cata1_list as $val): ?>
<div style="width:180px; margin: 5px; float:left">
<div class="level01"><h1><?php echo $val['name'] ?></h1></div>
<div>
<?php 
	// 嵌套:遍历2级分类
	// 遍历父ID为上一级的ID的分类
	$sql2 = "SELECT id,pid,name,path FROM `shop_catalog` WHERE `pid` = {$val['id']}";
	// echo $sql;
	$res2 = mysqli_query($conn, $sql2);
	$cata2_list = [];
	if ($res2) {
		while ($row2 = mysqli_fetch_assoc($res2)){
			$cata2_list[] = $row2;
		}
	}
	foreach($cata2_list as $val2):
?>
	<div style="border:1px solid #ddd; margin-bottom:10px; padding:10px;">
	<div class="level02"><h2><?php echo $val2['name']; ?></h2></div>

	<?php 
		// 嵌套:遍历3级分类
		$sql3 = "SELECT id,pid,name,path FROM `shop_catalog` WHERE `pid` = {$val2['id']}";
		$res3 = mysqli_query($conn, $sql3);
		$cata3_list = [];
		if ($res3) {
			while ($row3 = mysqli_fetch_assoc($res3)){
				$cata3_list[] = $row3;
			}
		}
		// print_r($cata2_list);
		foreach($cata3_list as $val3):
	?>
		<a href="./catalog.php?cid=<?php echo $val3['id'] ?>" class="level03"><?php echo $val3['name'] ?></a>
	<?php endforeach ?>
	</div>
<?php endforeach; ?>
</div>
</div>
<?php endforeach;?>

测试Opencart的MVCL运行过程

Opencart是一个轻量级、强大的,严格遵守MVC设计模式的开源PHP商城系统,支持多语言,所以有MVCL的说法,L是Language的层(多语言的翻译文件)。

新的项目基于TP开发一个商城系统,准备模仿OpenCart的一些模块,所以有了这篇文章。

以下以一个示例,介绍OpenCart的运行过程,适合入门的新手。主要是测试控制器、传递变量、模板显示的操作。

首页默认是加载common下的home控制器里面的index方法:
C:\wamp\www\x1.com\catalog\controller\common\home.php
common是公共模块

路由结构:http://x1.com/index.php?route=模块/控制器

第1步:在common下添加了test控制器
C:\wamp\www\x1.com\catalog\controller\common\test.php

Select Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
class ControllerCommonTest extends Controller {
	public function index() {
		// 设置data[]变量
		$data['name'] = 'jack';

		// 加载其他模块
		$data['test_left'] = $this->load->controller('common/test_left');
		$data['test_right'] = $this->load->controller('common/test_right');

		// 模板渲染
		$this->response->setOutput($this->load->view('common/test', $data));
	}
}

1.1 变量赋值:opencart的每个控制器都会定义一个$data的数组,所有的变量都存储在$data[‘变量名’]中。
1.2 控制默认加载的是index方法,一般index方法都会最后渲染模板,并把$data传递过去。
1.3 在index方法中,可以加载其他的子控制器。$this->load->controller(‘common/test_left’)。

第2步:新建2个控制器test_left和test_right。
C:\wamp\www\x1.com\catalog\controller\common\test_left.php

Select Code
1
2
3
4
5
6
7
8
9
10
<?php
class ControllerCommonTestLeft extends Controller {
	public function index() {
		// 设置data[]
		$data['nav'] = 'left nav';

		// 返回视图文件
		return $this->load->view('common/test_left', $data);
	}
}

C:\wamp\www\x1.com\catalog\controller\common\test_right.php

Select Code
1
2
3
4
5
6
7
8
9
10
<?php
class ControllerCommonTestRight extends Controller {
	public function index() {
		// 设置data[]
		$data['nav'] = 'right block';

		// 返回视图文件
		return $this->load->view('common/test_right', $data);
	}
}

这2个子控制器,也有自己的子模板文件,最终返回字符串。每个控制器就好像网站上的每一个小块,所以Opencart的输出页面,就是由一个个的小块组合拼接而成。

这里画了一个示意图,重点是理解这个模块的思维(就好像函数的结构化流程)。

opencart_01

第3步:建立3个模板文件,默认的访问的是test.tpl

$data[‘变量’]的值传入模板后,直接使用php的echo输出变量即可。见下

test.tpl: C:\wamp\www\x1.com\catalog\view\theme\default\template\common\test.tpl

Select Code
1
2
3
4
5
6
7
<table border="1" width="600" align="center">
	<tr>
		<td><?php echo $test_left; ?></td>		//子模块test_left传递的值
		<td width="50%"><?php echo $name; ?></td>      //test模块定义的变量
		<td><?php echo $test_right; ?></td>		//子模块test_right传递的值
	</tr>
</table>

test_left.tpl:C:\wamp\www\x1.com\catalog\view\theme\default\template\common\test_left.tpl

Select Code
1
2
3
4
<div id="left">
	<p>test left</p>
	<div><?php echo $nav ?></div>
</div>

test_right.tpl:C:\wamp\www\x1.com\catalog\view\theme\default\template\common\test_right.tpl

Select Code
1
2
3
4
<div id="right">
	<p>test right</p>
	<div><?php echo $nav ?></div>
</div>

第4步:访问前台
访问路径:http://x1.com/index.php?route=common/test

效果演示:

opencart_02

第5步:补充:整理的更多访问方法
这为了解部分(不为这篇文章的重点),结合其他控制器文件、模板文件,作为进一步的了解

Select Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!-- 加载language常量设置 -->
$this->load->language('common/footer');

<!-- 赋值 -->
$data['text_information'] = $this->language->get('text_information');

<!-- 可能是:需要设置的js代码,为空-->
$data['scripts'] = $this->document->getScripts('footer');

<!-- 加载模块 -->
$this->load->model('catalog/information');

<!-- 访问model -->
foreach ($this->model_catalog_information->getInformations() as $result){
	...
}

<!-- 设置url -->
$data['contact'] = $this->url->link('information/contact');

<!-- 访问全局常量 -->
$ip = $this->request->server['REMOTE_ADDR'];

<!-- 设置变量 -->
$this->document->setTitle($this->config->get('config_meta_title'));

小结:通过测试MVC的运行过程,理解Opencart的结构,是这篇文章的重点!

附件:Opencart首页的控制器访问方法源码如下:

Select Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
class ControllerCommonHome extends Controller {
	public function index() {
		$this->document->setTitle($this->config->get('config_meta_title'));
		$this->document->setDescription($this->config->get('config_meta_description'));
		$this->document->setKeywords($this->config->get('config_meta_keyword'));

		if (isset($this->request->get['route'])) {
			$this->document->addLink(HTTP_SERVER, 'canonical');
		}

		$data['column_left'] = $this->load->controller('common/column_left');
		$data['column_right'] = $this->load->controller('common/column_right');
		$data['content_top'] = $this->load->controller('common/content_top');
		$data['content_bottom'] = $this->load->controller('common/content_bottom');
		$data['footer'] = $this->load->controller('common/footer');
		$data['header'] = $this->load->controller('common/header');

		$this->response->setOutput($this->load->view('common/home', $data));
	}
}

WAMP环境使用Composer安装Laravel 5详细步骤,与Laravel目录介绍

1、安装Laravel 5:
通过 Composer 安装工具安装 Laravel:
composer create-project laravel/laravel –prefer-dist

创建一个名为blog的Laravel项目:
composer create-project laravel/laravel blog –prefer-dist

Laravel_1

2、安装位置:wamp的根目录www下
安装成功后:server.php文件重命名为index.php

如图所示为Laravel目录:
Laravel_2

3、绑定vhost域名

ServerAdmin wbo86@126.com
DocumentRoot “c:/wamp/www/blog”
ServerName laravel1.com
ErrorLog “logs/laravel1.com.log”
CustomLog “logs/laravel1.com.log” common

4、环境配置:
4.1 wamp版本要求(PHP>5.5.9 | WAMP 2.5)
4.2 开启rewrite和vhost
4.3 开启php扩展
extension = php_openssl.dll
extension = php_mbstring.dll
extension = php_pdo_mysql.dll

最终成功的效果:
Laravel_3

4、目录结构(仅仅罗列重要的目录,详见另外的文档):

Select Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
app	           //包括控制器、路由、Model等在内的应用目录,大部分的业务在此目录下进行	
app/Http	   //HTTP传输层的类目录(包括控制器,中间件,请求类目录,强大的路由等) >>(重要)<<
app/User.php   //自带的模型实例
bootstrap      //框架启动载入目录
config         //各种配置文件 >>(重要)<<
database	   //数据库相关目录
public		   //入口文件
resources      //资源文件目录
storage        //存储目录(如缓存等)
storage/views  //视图文件 >>(重要)<<
tests		   //测试目录
vendor         //源码包,第三方扩展
.ENV           //配置文件
.gitignore     //git提交忽略文件放在这里配置
composer.json  //存放依赖关系的文件,用于安装和升级
composer.lock  //锁文件,存放安装时依赖包的真实版本
gulpfile.js    //gulp(一种前端构建工具)配置文件
package.json   //gulp配置文件
phpspec.yml    //phpspec配置文件(一种PHP测试框架)
phpuniu.xml    //phpunit配置文件(一种PHP测试框架)
server.php     //PHP内置的web服务器把这个文件作为入口

6、composer.json文件简介:

Select Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
{
	    "name": "laravel/laravel",			//项目名称
	    "description": "The Laravel Framework.",     //项目描述
	    "keywords": ["framework", "laravel"],        //关键词
	    "license": "MIT",                   //许可协议
	    "type": "project",                  //类型
	    "require": {
	        "php": ">=5.5.9",               //PHP版本
	        "laravel/framework": "5.2.*"    //框架版本
	    },
	    "require-dev": {				    //依赖包
	        "fzaninotto/faker": "~1.4",
	        "mockery/mockery": "0.9.*",
	        "phpunit/phpunit": "~4.0",
	        "symfony/css-selector": "2.8.*|3.0.*",
	        "symfony/dom-crawler": "2.8.*|3.0.*"
	    },
	    "autoload": {   		//自动加载
	        "classmap": [
	            "database"
	        ],
	        "psr-4": {			//一种自动加载的规范
	            "App\\": "app/"
	        }
	    },
	    "autoload-dev": {		//加载测试
	        "classmap": [
	            "tests/TestCase.php"
	        ]
	    },
	    "scripts": {			//执行脚本
	        "post-root-package-install": [
	            "php -r \"copy('.env.example', '.env');\""
	        ],
	        "post-create-project-cmd": [
	            "php artisan key:generate"
	        ],
	        "post-install-cmd": [
	            "Illuminate\\Foundation\\ComposerScripts::postInstall",
	            "php artisan optimize"
	        ],
	        "post-update-cmd": [
	            "Illuminate\\Foundation\\ComposerScripts::postUpdate",
	            "php artisan optimize"
	        ]
	    },
	    "config": {				//配置项
	        "preferred-install": "dist"		//优先安装压缩包
	    }
	    "repositories": {					//配置composer镜像
	        "packagist": {
	            "type": "composer",
	            "url": "https://packagist.phpcomposer.com"
	        }
	    }
	}

Composer中国全量镜像安装方法,及检测方法

更新:推荐使用国内镜像 https://laravel-china.org/composer

官方教程:http://pkg.phpcomposer.com/

第1次安装Laraver这个框架,首先需要安装Composer工具,设置中国镜像,下面是一篇介绍如何安装Composer镜像的测试文章。

第1步:创建了一个空的composer.json文件

路径:D:\code\composer.json

内容:
{
}

Composer_01

第2步:修改当前项目的 composer.json 配置文件:

命令行:
composer config repo.packagist composer https://packagist.phpcomposer.com

Composer_02

第3步:vim composer.json打开文件

自动加入了:

“repositories”: {
“packagist”: {
“type”: “composer”,
“url”: “https://packagist.phpcomposer.com”
}
}

Composer_03

第4步:演示成功。

更详细的内容请查看官网。

备注:
例1:修改 composer 的全局配置文件(推荐方式):

composer config -g repo.packagist composer https://packagist.phpcomposer.com

例2:修改当前项目的 composer.json 配置文件:

composer config repo.packagist composer https://packagist.phpcomposer.com