
要构建的无限分类的模型 电子产品是最大的分类家用电器 ,数码产品是其子分类可以看到子分类是被父分类包含起来的每个分类都有左右 两个节点编号分别是1、2、3
根据上面的图mysql中建立表和插入数据
CREATE TABLE `product_categories` (
`id` MEDIUMINT( 8 ) NOT NULL AUTO_INCREMENT PRIMARY KEY ,`name` VARCHAR( 20 ) NOT NULL ,
`left_node` MEDIUMINT( 8 ) NOT NULL ,
`right_node` MEDIUMINT( 8 ) NOT NULL
) ENGINE = MYISAM CHARACTER SET utf8 COLLATE utf8_general_ci;INSERT INTO `product_categories` (`id`, `name`, `left_node`, `right_node`) VALUES(1, '电子产品', 1, 20),
(2, '家用电器', 2, 9),
(3, '电视机', 3, 4),
(4, '电冰箱', 5, 6),
(5, '空调', 7, 8),
(6, '数码产品', 10, 19),
(7, '电脑', 11, 18),
(8, '台式电脑', 12, 13),
(9, '笔记本电脑', 14, 15),
(10, '平板电脑', 16, 17);
表结构如下:
下面是PHP的实例代码:
1、获取所有节点
<php
$pdo = new PDO(
'mysql:host=localhost;dbname=test',
'root',
''
);
$pdo->exec("SET NAMES UTF8");
$stmt = $pdo->prepare("SELECT cname FROM product_categories as c, product_categories as pWHERE cleft_node BETWEEN pleft_node AND pright_nodeAND pname='电子产品' ORDER BY cleft_node");$stmt->execute();
$rs=$stmt->fetchAll(PDO::FETCH_ASSOC);
foreach($rs as $v){
echo $v['name']'<br />';
}
输出:
电子产品
家用电器
电视机
电冰箱
空调
数码产品
电脑
台式电脑
笔记本电脑
平板电脑
2、 获取某个父节点以及其所有子节点
<php
$pdo = new PDO(
'mysql:host=localhost;dbname=test',
'root',
''
);
$pdo->exec("SET NAMES UTF8");
$stmt = $pdo->prepare("SELECT cname FROM product_categories as c, product_categories as pWHERE cleft_node BETWEEN pleft_node AND pright_nodeAND pname='数码产品' ORDER BY cleft_node");$stmt->execute();
$rs=$stmt->fetchAll(PDO::FETCH_ASSOC);
foreach($rs as $v){
echo $v['name']'<br />';
}
输出:
数码产品
电脑
台式电脑
笔记本电脑
平板电脑
3、获取所有的叶子节点
<php
$pdo = new PDO(
'mysql:host=localhost;dbname=test',
'root',
''
);
$pdo->exec("SET NAMES UTF8");
$stmt = $pdo->prepare("SELECT name FROM product_categories where right_node-left_node=1");$stmt->execute();
$rs=$stmt->fetchAll(PDO::FETCH_ASSOC);
foreach($rs as $v){
echo $v['name']'<br />';
}
输出:
电视机
电冰箱
空调
台式电脑
笔记本电脑
平板电脑
4、获取某个子节点及其所有父节点
<php
$pdo = new PDO(
'mysql:host=localhost;dbname=test',
'root',
''
);
$pdo->exec("SET NAMES UTF8");
$stmt = $pdo->prepare("SELECT pname FROM product_categories AS c, product_categories AS p WHERE cleft_node BETWEEN pleft_node AND pright_node AND cname = '平板电脑' ORDER BY pleft_node");$stmt->execute();
$rs=$stmt->fetchAll(PDO::FETCH_ASSOC);
foreach($rs as $v){
echo $v['name']'<br />';
}
输出:
电子产品
数码产品
电脑
平板电脑
5、获取所有节点极其所处的层级
<php
$pdo = new PDO(
'mysql:host=localhost;dbname=test',
'root',
''
);
$pdo->exec("SET NAMES UTF8");
$stmt = $pdo->prepare("SELECT cname, (COUNT(pname) - 1) AS level FROM product_categories AS c, product_categories AS p WHERE cleft_node BETWEEN pleft_node AND pright_node GROUP BY cname ORDER BY cleft_node");$stmt->execute();
$rs=$stmt->fetchAll(PDO::FETCH_ASSOC);
var_dump($rs);
echo '<br />';
foreach($rs as $v){
echo $v['name']' level:'$v['level']'<br />';}
输出:
电子产品 level:0
家用电器 level:1
电视机 level:2
电冰箱 level:2
空调 level:2
数码产品 level:2
电脑 level:2
台式电脑 level:3
笔记本电脑 level:3
平板电脑 level:3
6、获取某个节点的层级
<php
$pdo = new PDO(
'mysql:host=localhost;dbname=test',
'root',
''
);
$pdo->exec("SET NAMES UTF8");
$stmt = $pdo->prepare("SELECT cname, (COUNT(pname) - 1) AS level FROM product_categories AS c, product_categories AS p WHERE cleft_node BETWEEN pleft_node AND pright_node and cname='平板电脑' GROUP BY cname ORDER BY cleft_node");$stmt->execute();
$rs=$stmt->fetchAll(PDO::FETCH_ASSOC);
var_dump($rs);
echo '<br />';
foreach($rs as $v){
echo $v['name']' level:'$v['level']'<br />';}
输出:
平板电脑 level:3
7、在某个节点后平行的插入一个节点
<php
$pdo = new PDO(
'mysql:host=localhost;dbname=test',
'root',
''
);
$pdo->exec("SET NAMES UTF8");
function addNode($left_node,$new_node){
global $pdo;
$stmt = $pdo->prepare("SELECT right_node FROM product_categories WHERE name = '$left_node'");$stmt->execute();
$rs=$stmt->fetch(PDO::FETCH_ASSOC);
$right_node=$rs['right_node'];
$pdo->exec("UPDATE product_categories SET right_node = right_node + 2 WHERE right_node > $right_node");$pdo->exec("UPDATE product_categories SET left_node = left_node + 2 WHERE left_node > $right_node");$pdo->exec("INSERT INTO product_categories(name, left_node, right_node) VALUES('$new_node', $right_node + 1, $right_node + 2)");}
addNode('家用电器','办公用品');
完成之后表结构如下:
8、删除某个节点及其所有子节点
<php
$pdo = new PDO(
'mysql:host=localhost;dbname=test',
'root',
''
);
$pdo->exec("SET NAMES UTF8");
function deleteNode($node_name){
global $pdo;
$stmt = $pdo->prepare("SELECT left_node,right_node, right_node - left_node + 1 as width FROM product_categories WHERE name ='$node_name'");$stmt->execute();
$rs=$stmt->fetch(PDO::FETCH_ASSOC);
$left_node=$rs['left_node'];
$right_node=$rs['right_node'];
$width=$rs['width'];
$pdo->exec("DELETE FROM product_categories WHERE left_node BETWEEN $left_node AND $right_node");$pdo->exec("UPDATE product_categories SET right_node = right_node - $width WHERE right_node > $right_node");$pdo->exec("UPDATE product_categories SET left_node = left_node - $width WHERE left_node > $right_node");}
deleteNode('数码产品');
完成之后表结构如下:
可以看到用多叉树的方式构建无限分类,查询的时候是非常简便的但是在插入新的节点和删除节点时就比较麻烦了
解决办法:
就是修改thinkphp的源码中的Library/Db/Driverclassphp文件,把
PDO::ATTR_CASE => PDO::CASE_LOWER 改为 PDO::ATTR_CASE => PDO::CASE_NATURAL,
或者在配置文件里面增加
DB_PARAMS’ => array(\PDO::ATTR_CASE => \PDO::CASE_NATURAL) 这一句。
第一次使用的时候这种解决方法果然可以,但是做另外一个项目的时候却始终不生效,无奈,百度了半天,找到一个方法,因为thinkphp执行的时候默认会把大写转换成小写,所以我们找到它的源码不让它转换就行。
修改Common/functionsphp里面的parse_name函数源码为:
function parse_name($name, $type=0) {
/ if ($type) {
return ucfirst(preg_replace_callback('/_([a-zA-Z])/', function($match){return strtoupper($match[1]);}, $name));
} else {
//这里会将数据库表名里的大写转换为 _小写,修改成不转换
return strtolower(trim(preg_replace("/[A-Z]/", "_\\0", $name), "_"));
}/
return $name;
}
其中注释掉的是原来的,未注释是新增的。
修改Library/Think/Modelclassphp里面的getTableName函数:
//$this->trueTableName = strtolower($tableName); //这里会将表名转换成小写,修改成不转换
$this->trueTableName = $tableName;
修改其中一句,这样就可以解决数据库字段名大写的问题。
以上就是关于话说php中PDO驱动切换数据库问题全部的内容,包括:话说php中PDO驱动切换数据库问题、php连接数据库关于PDO类和PDOStatement类的区别是什么、ThinkPHP 3.2 版本升级了哪些内容等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)