场景:
有一个饭店表 restaurant,存放所有饭店记录。我需要一个功能,将饭店按照不同的条件进行多重查询。就象这样:
 
氛围:浪漫 / 商务会谈 / 茅草屋
菜系:川菜 / 鲁菜 / 家常菜...
区域:东区 / 西区 / 南区 / 北区...
 
我点击一个或多个条目,则下方自动刷出符合条件的饭店来。
例如我点击了 浪漫、商务会谈、鲁菜,由于浪漫、商务会谈是同属于氛围的,应该认为用户想查找的是“或”的关系,不管出现二者的哪一个,都属于查询范围;而鲁菜是属于菜系的,那么与前两个条件来说,应该是“与”的关系,即:用户想查(氛围==浪漫 || 氛围==商务会谈)&& (菜系==鲁菜)的所有饭馆的集合。
这里有一个逻辑上的小别扭:如果我氛围选了浪漫,菜系不选,那么是不是要选择(氛围==浪漫)&& (菜系==none)吗?这样的结果肯定为空。实际上,不选菜系表示对菜系无要求,所以范围应该是(氛围==浪漫)&& (菜系==所有)。
 
考虑到这个功能比较常见,打算做一个通用的东西出来
感觉这是个难度比较大的功能,来做一下吧。
 
1、建立几个表:tag_tablename、tag_title、tag_text、tag_refer。其中
tag_tablename - 在这里只有一条记录 restaurant,但将来可能会有其它的,如article、user等
tag_title - 这是大的分类,分别为氛围、菜系、区域,每一条的tablename_id为1,即restaurant
tag_text - 这是具体的tag,如浪漫、川菜、鲁菜、东区。。等等
tag_refer - 这是一个多对多的表,它记录了restaurant表中的记录与tag_text表中的记录的多对多的对应关系
 
2、创建 Model。这里,TagTablename里实现了tag_titles,TagTitle里面实现了tag_texts。
 
3、写实现的类 CAnjoTag
    // 生成:
// 氛围:浪漫 / 商务会谈 / 茅草屋...
// 菜系:川菜 / 鲁菜 / 家常菜...
// 区域:东区 / 西区 / 南区 / 北区...
// 这样的样式,并且最好能接受点击,并且最好在点击后调用ajax更新下面的查询结果
public static function tag_list($tablename, $options=array()) {
$r=' <ul class="select">';
。。。
return $r;
}
这里面的具体实现就不贴出来了,主要是一步步生成html代码,显示前面的那些内容,并接受点击,点击一次选择,再次点击则取消选择。点击会触发一个javascript函数,它回调另一个javascript函数,用以 Ajax 方式更新查询区域的内容。
 
然后,这样调用和更新ajax获取的内容
<?php echo CAnjoTag::tag_list('Restaurant', array('click_callback'=>'tag_clicked')); ?>
<script>
function tag_clicked(ids)
{
// console.log(ids);
$('#rest-grid').load('?r=rest/ajaxAction&action=rest_query', {tagtext_ids: ids});
}
</script>
 
在RestController中这样实现:
    public function actionAjaxAction($action)
{
$r='';
switch ($action)
{
case 'rest_query':
$ids=Yii::app()->request->getParam('tagtext_ids');
if (substr($ids, -1)==',') $ids=substr($ids, 0, -1); //删除结尾的 ,
$ids=trim($ids);
if ($ids!='')
{
$cond="id in (select record_id from {{tag_refer}} where tag_text_id in ($ids))";
$criteria = new CDbCriteria;
$criteria->condition=$cond; $count = Restaurant::model()->count($criteria);
$pager = new CPagination($count);
$pageSize=10;
$pager->params = array('tagtext_ids'=>$ids, 'action'=>'rest_query');//分页中添加其他参数
$pager->pageSize=$pageSize;
$pager->applyLimit($criteria);
$dataProvider=new CActiveDataProvider('Restaurant', array(
'criteria'=>$criteria,
'sort'=>array(
'defaultOrder'=>'id desc',
),
'pagination'=>$pager,
));
$this->renderPartial('_query_result', array('dataProvider'=>$dataProvider));
die();
}
break;
} echo $r;
}
 
4、ajax换页问题
调试ajax换页时费了很大劲。总是做不到按Ajax方式显示下一页,一点页码的链接就跳到新页上了。看一下console的错误信息,不能ajax调用的原因是在 jquery.yiigridview.js 中,出现了错误:
$.param.querystring is not a function
 
网上解释说:这个错误会导致你无论怎么选择filter,都不会发送请求道cintroll去取数据,解决办法就是,无论在什么地方调用jquery,最好使用Yii的registe来注册,而不要使用<script>来引入.
 
<?php Yii::app ()->clientScript->registerCoreScript ( 'jquery' ); ?>
但bootstrap提示,
Uncaught Error: Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 3
于是找到 Yii的核心script所在的位置:
D:\xampp\htdocs\yii-1.1.14.f0fee9_201505\framework\web\js\source
 
这个jquery.js 是1.8.3的,我复制了一个1.11.3的进来,一切正常了。
 
这个jquery的问题,真的要改变习惯了。以前也会因为jquery的多次引用而造成类似的这种莫名其妙的错误,试着改变jquery的位置或显式地引用一下它,有时也能解决,但终归不是正途。
(另:看了 jquery.yiigridview.js的源码,原来是Yii的作者写的。真牛~前端也很强嘛)
 
5. 待改进:
在actionAjaxAction中,$cond="id in (select record_id from {{tag_refer}} where tag_text_id in ($ids))"; 这个写法是不严谨的。它把所有的条件都当做“或”来处理了,没有实现前面分析的结论。这是小问题,以后再细细实现。
 
另一个是,在饭店信息的修改界面,我需要调用 CAnjoTag 的另一个方法,显示饭店的相关tag属性并可以修改。这同样是我的初衷之一,下一步会去做。
 
 
 

用YII实现多重查询(基于tag)的更多相关文章

  1. YIi 权限管理和基于角色的访问控制

    验证和授权(Authentication and Authorization) 定义身份类 (Defining Identity Class) 登录和注销(Login and Logout) 访问控制 ...

  2. php yii多表查询

    一个Company记录可以对应多个CompanyUser纪录Company表: [['id', 'nature_id', 'scale_id', 'pro_id', 'created_at', 'up ...

  3. Yii Active Record 查询结果转化成数组

    使用Yii 的Active Record 来获取查询结果的时候,返回的结果集是一个对象类型的,有时候为了数据处理的方便希望能够转成数组返回.比如下面的方法: // 查找满足指定条件的结果中的第一行 $ ...

  4. day056-58 django多表增加和查询基于对象和基于双下划线的多表查询聚合 分组查询 自定义标签过滤器 外部调用django环境 事务和锁

    一.多表的创建 from django.db import models # Create your models here. class Author(models.Model): id = mod ...

  5. 基于Tag的Docker自动构建

    构建规则 一旦您的Tag符合“release-v$version"的形式,将触发自动构建:1)若您有$version相关的Tag构建规则,则以$version的Tag规则帮您构建:2)若您没 ...

  6. hbase查询基于标准sql规范中间件Phoenix

    Phoenix是个很好的hbase 查询工具,在hbase中安装也很简单,可以按照 http://www.cnblogs.com/laov/p/4137136.html 这个连接中进行配置客户端和服务 ...

  7. Yii 之数据库查询

    模型代码: <?php namespace app\models; use yii\db\ActiveRecord; class Test extends ActiveRecord{ } 控制器 ...

  8. Django day08 多表操作 (三) 基于对象的跨表查询 基于双下划线的多表查询

    一: 基于对象的跨表查询 1. 一对一 正向: 反向: 2. 一对多 正向: 反向: 3.多对多 正向: 反向: 4.*****基于对象的多表查询 二: 基于双下划线的多表查询 1. 连表查询 一对一 ...

  9. YII进行数据查询及类库追踪

    一般处理过程: 模型进行数据操作,继承自CActiveRecord (活跃记录) AR数据库向上的封装.AR通过OOP面向对象方式操作数据库.AR须要终于转变为详细的sql语句.通过一个中间类(cri ...

随机推荐

  1. eclipse的工程里的*.properties文件默认以unicode的编码形式显示

    今天发现导入eclipse的工程里的*.properties文件无法显示中文,是unicode的编码形式显示的. 原因是Eclipse的.properties文件的默认编码为iso-8859-1. 选 ...

  2. 2.7 HBase架构深入剖析

    一. 1.client 整个HBase集群的访问入口: 使用HBase RPC机制与HMaster和HRegionServer进行通信: 与HMaster进行通信进行管理类操作: 与HRegionSe ...

  3. 洛谷 - P5030 - 长脖子鹿放置 - 二分图最大独立集

    https://www.luogu.org/problemnew/show/P5030 写的第一道黑色题,图建对了. 隐约觉得互相攻击要连边,规定从奇数行流向偶数行. 二分图最大独立集=二分图顶点总数 ...

  4. SQL 语句(原生)

    //查 //查询表里的所有数据 select * from 表名 //根据id等字段查询数据 select * from 表名 where 字段 = 值 or 字段 = 值 (例):select * ...

  5. VR相关学习资源

    ptgui全景图制作工具 http://blog.csdn.net/xoyojank mems陀螺误差补偿的算法研究 http://www.docin.com/p-619540171.html 极客工 ...

  6. WindApi2 , WindOriginalApiLibrary 突然不兼容问题

    1. 在新的电脑上从tfs拉下代码后编译, windoriginalapilibrary 这个工程弹出对话框,要求转为vs2013编译,选择同意,编译成功 2.WindApi2 的Reference列 ...

  7. DB2 学习--(1)--安装教程

    db2 linux 安装部署 1 解压文件 tar -zxvf db2_v101_linuxx64_expc.tar.gz 2 切换路径 cd expc/ 3 启动安装程序 ./db2_install ...

  8. Luogu P1514引水入城【搜索】 By cellur925

    题目传送门 这道题开始看好像并没有什么思路,和搜索好像也并没有什么关系.但是我们手玩下样例就会发现,思路其实就三句话:(写这道题的时候在代码里写的) //我们想知道从第1行的每列往下到干旱区的范围 / ...

  9. 对单片机C语言的一些误用和总结

    在学习单片机的时候才真正知道C语言是什么它是来干什么的~但是C语言用到嵌入式只是它小小的一部分他的应用还有很多地方呢,呵呵我们这里就不讨论这个了.我们是不是在写程序的时候错误很多就算编译通过了也达不到 ...

  10. C - How Many Tables

    #include <cstdio> #include <cstdlib> #include <iostream> #include <algorithm> ...