smarty循环foreach,section实例详解

php里面的数组或者对像都可以有for,foreach,while,list each来循环出来,smarty里面也有这套方法,要不然php的数组对像数据,smarty就不知道怎么把显示出来。习惯的php里面的for,foreach,while的用法,刚一开始的时候,smarty里面循环数组老是忘,好记性不如烂笔头,还是把它记下来才是最好的。下面定界变量符号,我就用默认的大括号了。
一,foreache,foreacheelse,/foreache方法
1,它是section 之外处理循环的另一种方案(根据不同需要选择不同的方案).用于处理简单数组(数组中的元素的类型一致),它的格式比 section 简单许多,缺点是只能处理简单数组.
2,foreach 必须和 /foreach 成对使用,且必须指定 from 和 item 属性.

3,foreach可以圈套不过name必须为一
4,from 待循环数组的名称,key数组下标,item当前处理元素的变量名称,name该循环的名称,用于访问该循环
5,foreachelse 语句在 from 后面的数组对像没有值的时候被执行.
二,section,sectionelse,/section方法
section 用于遍历数组中的数据. section 标签必须成对出现. 必须设置 name 和 loop 属性. 名称可以是包含字母、数字和下划线的任意组合. 可以嵌套但必须保证嵌套的 name 唯一. 变量 loop (通常是数组)决定循环执行的次数. 当需要在 section 循环内输出变量时,必须在变量后加上中括号包含着的 name 变量. sectionelse 当 loop 变量无值时被执行.
section里面可以带的参数如下
1,name单次循环的名称,必须有的选项
2,loop循环的变量名称,必须有的选项
3,start 循环开始的KEY值 ,默认是从第一个开始,
4,step设置循环的跳跃数,step=2将只遍历下标为0、2、4等的元素.
5,max循环的次数,默认为1,
6,show是不是显示该循环
从上面参数中我们可以看到,没有提到下标,我们经常会用到数组下标。但是smarty里面带的有.
下面的arrayname是section里面的单次循环名称
a,$smarty.section.arrayname.index 数组下标,根foreach 的key差不多
b,$smarty.section.arrayname.index_prev 上次循环的下标 根$smarty.section.arrayname.loop差不多
c,$smarty.section.arrayname.index_next 下次循环的下标
d,$smarty.section.arrayname.iteration 第几次循环了 根rownum一样
e,$smarty.section.arrayname.first 第一次循环
f,$smarty.section.arrayname.last 最后一次循环
g,$smarty.section.arrayname.show 循环是否显示
h,$smarty.section.arrayname.total 总共循环了多少次
section得到数组对像里面的值
{section name=arrayname loop=$array}
{$array[arrayname.index]} ,{$array[arrayname]}二者是等价的,由起可见,有了上面的a-h是多么的重要
三,应用举例
1,一维数组

array (  
   "0" => 'home',  
   '1' => 'who',  
   '2'=> 'tank',  
   '3'=> 'what'  
  );  
$this->tpl->assign("onearray", $this->onearray);  

a),foreach来读取

{foreach from=$onearray kkey=k item=value }  
 一维key={$k}  一维value={$value}
{foreachelse} nothing {/foreach}

显示的结果是
一维key=0 一维value=home
一维key=1 一维value=who
一维key=2 一维value=tank
一维key=3 一维value=what
b),section来读取

{section name=one loop=$onearray start=0 step=1}  
 index={$smarty.section.one.index},  
 index_prev={$smarty.section.one.index_prev},  
 index_next={$smarty.section.one.index_next},  
 first={$smarty.section.one.first},  
 last={$smarty.section.one.last},  
 iteration ={$smarty.section.one.iteration},  
 total={$smarty.section.one.total},  
 value={$onearray[one]}
{sectionelse} nothing {/section}

显示的结果是
index=0, index_prev=-1, index_next=1, first=1, last=, iteration =1, total=4, value=home
index=1, index_prev=0, index_next=2, first=, last=, iteration =2, total=4, value=who
index=2, index_prev=1, index_next=3, first=, last=, iteration =3, total=4, value=tank
index=3, index_prev=2, index_next=4, first=, last=1, iteration =4, total=4, value=what
2,二维数组

array (  
   "test" => 'home',  
   '2' => 'who',  
   array (  
    "上海",  
    "born" => "安徽",  
    "name" => "海底苍鹰"  
   ),  
   array (  
    "1583456",  
    "fax" => "12345678",  
    "cell" => "13256478414"  
   )  
  );  
$this->tpl->assign("twoarray", $this->twoarray);  

a),foreach

{foreach from=$twoarray kkey=k item=value }  
 {if is_array($value)}  
  {foreach from=$value key=tk item=tv }  
   二维tkey={$tk}  二维value={$tv}
{foreachelse} 二维数组为空 {/foreach} {else} 一维key={$k} 一维value={$value}
{/if} {foreachelse} nothing {/foreach}

显示结果如下:
一维key=test 一维value=home
一维key=2 一维value=who
二维tkey=0 二维value=上海
二维tkey=born 二维value=安徽
二维tkey=name 二维value=海底苍鹰
二维tkey=0 二维value=1583456
二维tkey=fax 二维value=12345678
二维tkey=cell 二维value=13256478414
b),section

{section loop=$twoarray name=two }  
 {if is_array($twoarray[two])}  
  {section loop=$twoarray[two] name=aaa }  
   二维tkey={$smarty.section.aaa.index}  二维value={$twoarray[two][aaa]}
{sectionelse} 二维数组为空 {/section} {else} 一维key={$smarty.section.two.index} 一维value={$twoarray[two]}
{/if} {sectionelse} nothing {/section}

显示结果如下:
一维key=0 一维value=
一维key=1 一维value=
一维key=2 一维value=who
二维tkey=0 二维value=上海
二维tkey=1 二维value=
二维tkey=2 二维value=
如果是一维数组,并且带有下标的话,并且不是按0,1,2这样的顺序的话就取不到东西。这个能不能理解成foreach存在的理由。不过一般从数据库取数据都是二维数组,并且外层都是以0开始的。看下面的这个例子

array (  
 array (  
  'name' => 'tank',  
  'sex' => '男',  
  'old' => '28'  
 ),  
 array (  
  'name' => 'joyce',  
  'sex' => '女',  
  'old' => '111'  
 )  
);  

section循环

{section loop=$twoarray name=two}  
 name={$twoarray[two].name},sex={$twoarray[two].sex},old={$twoarray[two].old}
{sectionelse} nothing {/section}

显示结果
name=tank,sex=男,old=28
name=joyce,sex=女,old=111
5

转载请注明
作者:海底苍鹰
地址:http://blog.51yip.com/smarty/903.html

上海驾考笔记:小路

小路第一项目:倒车入库 操作步骤和要令
1、观察目标:起点后倒至右门中段红色标对准右边标杆(即三点一线)、立刻向右打死方向
2、待车转弯入库时、从左侧后视镜观察、待左侧库位线露出长达50cm时、即刻判断出车身和库位线夹角角度大小、(有三种角度大下,如下1、2、3种)、再根据角度大小就知道方向盘进行回转多少量的调整
a、当夹角>30度时、方向盘回至9点
b、当夹角=30度时、方向盘回至12点
C、当夹角<30度时、方向盘不回
待左侧车尾完全进入库位边缘线(不得远离边缘线)、立即回正方向盘
4、后倒进行直线调整、紧贴左侧边缘线、保持在20~30cm宽度、观察左侧后视镜、车身和库位边缘线是否平行
操作动作:若不平行采用“小推大拉”方法修正、看左侧后视镜(后方窄小则推,后方宽大则拉)推拉方向盘的量只能45度、待车辆完全平行于左侧边缘线后回正方向盘、再观察左侧停车线平行于肩膀中心制动停车
【注:以上为右边倒车入库的方法、左边倒车入库方法其实一样、是对称的】
注意技巧:慢、稳、修正
考试要求:1、按规定线路行驶
2、不得压线
3、中途不得停车
失误防范:1、开把打方向时机把握不准
2、转向左右易搞错
3、后倒修正车辆方向易搞错

小路第二项目:侧方停车 操作步骤和要令
第一步
首先调整车辆距右边库位边缘线保持在30厘米左右往前行进、车头凸筯对准地上参照线、横向肩膀平行于右侧的参照标杆停车
第二步
挂倒档后向右打死方向盘倒车、观察左侧后视镜、看到车门把手碰触到地上的白色虚线时、立即回正方向盘、倒至后轮直径垂直压线后、立即向左打死方向盘、观察左后视镜车身和地上的库位边线平行后刹停、不用回正方向盘、倒车入库便完成
第三步
挂一档、开左转向灯起步、当车开出库位时倾斜大约在40度时立即回正方向盘、待车向前稍走动1.5米向右打一圈、待车行正直后向左回正方向盘即可驶离
考试要求:1、不得中途停车
2、入库后四周边缘线不压
3、按规定线路行驶
4、出库前开启左转向灯
失误防范:1、倒档未彻底挂入跳档
2、易熄火 中途停车
3、掌握转向开把 回正时间
4、出库时忘开启左转向灯
训练重点:左后轮直径垂直压白色虚线的判断

小路第三项目:坡道定点停车和起步 操作步骤和要令
1、定点停车:待车进入坡道前20米矫正车辆距中进入、上了坡道用离合器控制车速、不准踩刹车、车头凸筋点对准坡道上的l参照线后、此时把稳方向盘不动、观察右侧的定点停车参照物、当右侧门板上的标签和右侧参照物三点一线后、即刻刹车停下(千万别踩离合器、离合器保持原有高度不动)这样定点停车就完成了
2、坡道起步:因刚停车离合器没动过、基本保持在动力半联动状态、刹车就停车了、此时只要微微轻抬一下刹车、车辆就直接起步了、自然也就完成了坡道起步
注意技巧:慢、稳、准
考试要求:1、上坡定点停车准确
2、坡道起步时不准熄火、溜车
3、熄火后30秒内发动车辆重新
起步(超时不合格)
失误防范:1、坡道起步时及易熄火
训练重点:a、离合器保持不动、直接刹车停
车技巧掌握
b、熄火后直接启动起步训练

小路第四项目:曲线行驶 操作步骤和要令
→进入曲线前10米前先矫正车辆、距中略偏右进入曲线入口(靠住圆孤大的一边行进)
1、待车头左上角抵触到前方孤线时、即刻向左打一圈、观察左侧后视镜、行进过1/2弧线时、若车身离左侧边线大于30厘米宽度时、方向盘加至9点钟、小于15厘米宽度最后加
2、待车往前行进时车头左侧离左侧边缘弧线在20厘米时、立刻回正方向盘
3、待车头右上角抵触到前方孤线时、即刻向右打一圈、观察右侧后视镜、行进过1/2弧线时、若车身离右侧边线大于30厘米宽度时、方向盘加至3点钟、小于15厘米宽度最后加
4、待曲线出口时车头凸筯点对准前方参照物回正方向盘驶离
考试要求:1、不得压线
2、中途不得停车
失误防范:1、打方向时机掌握不好
2、曲线弧度判断有误造成车轮
轨迹异常压线
3、内外轮差判断不足
训练重点:a、前提左右角抵触前方弧线判断
b、出口时对准参照物回正方向

小路第五项目:直角转弯 操作步骤和要令
1、进入直角转弯前10米先矫对车辆距中垂直进入直角口(略靠右侧)、矫对车头凸筯对准前方参照点后、把握方向盘不动
2、待肩膀中心平行于左侧参照点(注意:完全平行后)、即刻向左打死方向盘(打方向速度要快)
3、转弯过后左侧内角成15~25度夹角先回半圈、待平行边缘线立刻回正方向盘驶离
考试要求:1、不准压线
2、不得中途停车、熄火
失误防范:1、简单易轻心
2、车速过快未对齐右侧参照
时易提前 打方向盘
3、判断前后内外轮差能差、
后轮容易压左侧凸出点
训练重点:1、肩膀中心完全平行于左边参
照物后打死方向盘、绝不能
提前、打方向要快速

小路第六项目:窄路调头 操作步骤和要令
说白了就是车辆行驶在很窄的路上车辆调个头而已、通过二进一退完成整个过程、三次打死方向盘。耗时2分钟(超时不合格、科目二就此项目限时)
第一步
车辆沿着右侧边缘线30厘米往前行进、车头凸筋对准正前方参照物、待车辆行进至前方边缘线距离剩余30厘米时、向左打死方向盘、前进至车窗直角和地上左边黄直线交叉在同一个角落时刹停
第二步
挂倒档,向右打死方向盘起步后倒、观察左后视镜、后轮没压线前刹停
第三步
挂一档、向左打死方向盘起步驶离
考试要求:1、不得压线、熄火
2、不得中途停车、空档滑行
3、用时规定2分钟
4、按线路规定行驶
失误防范:1、易挂错档
2、倒档没挂好易跳档
3、易向左向右搞错方向
训练重点:a、左侧黄线交叉同一角落判断
b、右后轮未压线判断

小路第七项目:模拟高速公路收费站 操作步骤和要令
转弯进入模拟高速公路前、先调整车辆靠左侧边缘线大概在15~30厘米以內(车身必须和左侧边线平行)、而后车头前凸筯对准正前方地上的参照线顺延着(一档低速前进、身份和头部不得左右摇摆)、待肩膀中心平行于左侧起降按键制动停车
1.置空档+拉手刹+按起降键
2.挂一档+放手刹+车辆起步
考试要求: 1、不准中途停车、熄火
2、左侧车身离边缘线(15~30cm)
失误防范: 1、左侧边缘线保持不好
2、起步前易忘手刹车
3、起步易熄火

小路第八项目:模拟隧道行驶 操作步骤和要令
进入隧道前10米先开启大灯(灯开关有二档拨到底)、选择好车道一档行进、中途不准变道超车、换档、不准停车、不准加油、不准压线(两侧边缘线)、待车辆行驶至隧道出口前10米关闭大灯(灯关到底)、出隧道口驶离。
考试要求 1、不准中途停车
2、进隧道前开大灯
3、进入隧道不准变道、压
线、换档、超速、加油
4、出隧道口关闭大灯
失误防范 1、进出隧道口时易忘记开启或关
闭大灯
2、开启、关闭大灯易不到
位、注意开关位置状态
训练重点:a、进隧道前开启大灯、出隧道前
关闭大灯
b、大灯开关位置需体验易搞错

小路第九项目:紧急情况处置 操作步骤和要令
特别注意:此项目系统不会提前播报提示语、不象其它8个项目都会提前播报眼前要进入的是什么项目、然后进行操作、这一定要搞清楚。只因是紧急情况、一旦进入门襟糸统会随时随地播报语音、一旦听到播报语音立即制动停车。(语音提示语是:“前方紧急情况、请立即停车”)
其实就是假定前方有40米的路长内一定会出现紧急状况、然后考生去处置
操作步骤
从驶入门襟开始、在这0~40米任意路段糸统会随时播报语音”紧急情况处理”、当学员只要听到“前方紧急情况、请立即停车”。在听到“前方”二字学员即刻制动停车、然而开启危险警示灯、等待6秒后放开刹车轻抬离合器起步、起步后关闭危险警示灯、随后糸统播报语音“成绩合格”整个考试过程完毕、安全驶向终点停车。
考试要求:1、一档进入门襟
2、不准加油、换档
失误防范:1、停车后忘记开启危险警示灯、起步时会忘记关闭危险警示灯 2、因为是最后一个项目完成、放轻警惕起步过急易熄火

打开FLASH(SWF)失败,提示Error #2046的解决办法汇总

RSL编译方式的FLEX站点出现#2046错误的解决办法

先简单解释下背景知识:
从FLEX4开始,所有web程序都默认使用RSL的编译方式。那用RSL编译的FLEX站点和普通FLEX站点有什么区别呢?简单的说就是,flash player会在你第一次访问任何一个这种FLEX站点时,缓存下大约1M的类库在系统里。下次用户访问这个站点或者任何其他flex站点时都不用再下载类库这部分文件。RSL编译方式就是在编译时把类库都分离出去了。这种编译方式,在同类flash程序通常大小要接近1M的情况下,可以编出100K左右的整站程序,比一张图片都小。好处自然是非常节省带宽和加载时间。我现在做的几个FLEX站点都采用这种编译方式,加上皮肤也采用全矢量绘图,编译出来的整站程序都保持在100K左右,有效的解决了FLASH加载慢的最大问题。

但问题出来了,有一小部分用户第一次访问站点时,总是出现无法缓存类库的问题,表现就是报错”ERROR:#2046″。或者有些用户原来能够访问成功(说明已经成功缓存过类库了),但突然也开始报错了。直接导致的后果就是根本不能加载程序,想要节省加载时间反而导致不能加载,让我一直很苦恼。从做第一个FLEX4程序开始,我就发现了这个问题,当时只有我的电脑不能访问我写的站点,而大家都能,并且我重装了系统几次,都不行。后来不知道怎么的,我又突然就能访问了,就没有太在意这个问题。现在想想,那时候我干了一件他们都没干的事:我修改过系统时间。调整到2008年了。

正好最近又无意中在论坛上看到高人解答,原来报错的用户也都存在同样的问题:系统时间出错了。因为用户系统的时间早于缓存的类库的有效签名时间,被flash player拒绝加载了。那时我刚好在实验室,又这么刚好就有台电脑就不能访问,查下它的时间是2000年。旁边的电脑都能访问。就修改了下时间测试,马上加载成功了~

困扰我很久的问题终于解决了,非常之高兴,遂写了个js脚本加在网页里,加载前先判断下服务器和客户机的时间差。如果太大就弹出提示。让用户把时间改正确,或者就直接跳转到我准备好的无类库缓存版站点。我有给每个flex站点都加上这种无缓存的版本,供应急用。就是简单再写一个full.html,把引用的程序改成对应的非RSL编译方式生成的swf即可。访问方法为:URL后加上full.html,使用上不会有任何差别。
那么RSL的问题算是完美解决了,顺便也把另一个问题解决了吧:在FLEX站点访问时,还会出现另一个问题,就是很多客户机的FLASH PLAYER版本过低,导致FLEX程序不加载,表现为一片空白,不提示任何信息(只有没有安装FP时,浏览器才会自动提示)。这会让用户误以为站点不能访问了。解决办法也是加上个JS脚本,判断一下FP的版本先。下面附上两个JS脚本,在IE/Firefox/chrome测试均完美通过。

脚本及引用地址:http://blog.csdn.net/chen98qqkk/article/details/5916002

——————————————————
Flash出现Error #2046常用解决办法
1、查看本机时间是否是或接近于internet时间,时间的差错会导致Error #2046的出现
2、清除浏览器缓存,swf文件的更改会导致Error #2046的出现,清除缓存可以读取最新的swf文件
3、Flash过低的版本可能会导致Error #2046的出现(建议解决方案)
4、恶意软件可能会导致Error #2046的出现
5、浏览器崩溃可能会导致Error #2046的出现
6、访问站点维护可能会导致Error #2046的出现

引用地址:http://aajiang.lin.blog.163.com/blog/static/750980312013102395628728/

———————————————————–

打开FLASH(SWF)失败,提示Error #2046的解决办法。

猎豹浏览器:
C:\Users\玛\AppData\Local\liebao\User Data\用户名\Pepper Data\Shockwave Flash\CacheWritableAdobeRoot\AssetCache\?????\*.SWZ

Chrome:
C:\Documents and Settings\Administrator\Local Settings\Application Data\Google\Chrome\User Data\Default\Pepper Data\Shockwave Flash\CacheWritableAdobeRoot\AssetCache\……

百度浏览器:
C:\Users\玛\AppData\Roaming\baidu\browser\profile\Pepper Data\Shockwave Flash\CacheWritableAdobeRoot\AssetCache

百度浏览器(WinXP)
C:\Documents and Settings\Administrator\Application Data\Baidu\browser\profile\Pepper Data\Shockwave Flash\CacheWritableAdobeRoot\AssetCache

其他
C:\Users\玛\AppData\Roaming\Adobe\Flash Player\AssetCache

C:\Documents and Settings\Administrator\Application Data\Adobe\Flash Player\AssetCache

根据不同浏览器,位置略有不同,但在都是AssetCache目录下有个临时目录,把这个目录下面的文件删除后就可以正常了。

部分路径会是这个:
%appdata%\Adobe\Flash Player
%appdata%\Macromedia\Flash Player

引用地址:http://blog.sina.com.cn/s/blog_50d48c190102vvhb.html

———————————————-
注:本人最后解决问题用的是最后一个方法,删除%appdata%\Adobe\Flash Player\AssetCache目录下面的文件,然后再用ie访问时就不会报#2046错误了

 

在Mac OS X中使用mtr诊断路由节点问题

1. 下载地址:http://rudix.org/packages/mtr.html

2. 下载后运行mtr-0.85-0.pkg进行安装

3. cd /usr/local/sbin ,就会看mtr文件。

4. 运行mtr出现提示
-bash: mtr: command not found

解决方法:
alias mtr=/usr/local/sbin/mtr

5. 继续运行mtr出现提示
mtr: unable to get raw sockets.

解决方法:
sudo chown root mtr
sudo chmod u+s mtr

6. 运行mtr进行诊断
mtr www.baidu.com

http://www.cnblogs.com/dudu/p/mac_mtr.html

菜谱收藏:松茸鸡饭

1、准备好简单的食材:洗净泡水后的松茸和鸡枞(我没有西藏松茸,专程去一家菌类火锅店强买的新鲜松茸和鸡枞),去皮的鸡腿肉(有少许脂肪无所谓,这样能带一点油气更好)。

2、把鸡腿肉切成条,用生抽腌制二十分钟。这道工序老陈用的是手撕,鸡腿在他手里比餐巾纸还脆弱,我终于明白为啥当年群众们都盼着他去主演抗日神剧了。

3、用手将松茸撕成条,不要用刀切,那样松茸会沾染上金属的气味。我恶狠狠地撕着松茸,不得不承认它的手感真的很像黑丝,以至于我撕到后面根本停不下来,见啥撕啥,我家厨房被我弄得一片狼藉。

4、将几种食材倒入锅里拌匀,然后加入酱油、砂糖、料酒和清水,搅拌均匀。这一步最好能加入日本料理用的刺身酱油,国内的酱油相对更咸。大火烧开后用小火进行煨煮,直到鸡肉煮熟(10分钟以内)。

5、不要煮得太干,如果快干锅了记得再加入清水。关火后将汤汁滤出,倒进碗里。这是一碗香得快出人命的菌汤,千万要忍住你的食欲,它是焖饭的关键材料,喝不得。这道菜的烹饪者必须启用老陈或者我这样的硬汉,寻常成年男子很难拒绝这种诱惑。

6、把煮好的松茸鸡枞还有鸡肉盛碗里待用。

7、准备好一电饭煲的大米,如果想吃软糯的米饭用糯米亦可。我这人习惯了说硬话,吃硬菜,所以选的是尿性的东北米。把菌汤倒入电饭煲里,执行煮饭流程。

8、米饭煮熟后,加入菌类和米饭,拌匀即可食用。这道松茸鸡枞鸡肉饭混合了菌类和鸡肉的香味,简直令人发指。连我这种平时严格控制碳水化合物摄入的人都把一大碗米饭吃了个精光,那些饿了半天肚子的大妈岂不是为了这碗饭能够出卖灵魂。真不知那天她们是怎样报答老陈的,不敢想。

http://dapenti.com/blog/more.asp?name=agile&id=99490

使用android手机ssh软件ConnectBot免密码登陆管理linux服务器

出门在外时电脑不是随时都在身边,万一服务器出现问题,可以在手机上安装ConnectBot来ssh登陆
ConnectBot是一个Android操作系统上的Shell客户端。它可以让用户安全地远程连接到运行着SSH守护程序的服务器中。用户可以从Android设备输入命令,并在远程服务器上执行。
使用方法也很简单,打开软件后出入“用户名@主机名:端口”就可以连接服务器进行管理。但是这样每次连接都需要重新输入密码,而这个密码通常都会很长,这时我们就可以用公钥来进行登陆,步骤如下:
1.在软件菜单中选择 管理公钥–产生


2.输入昵称,其他默认即可,如果怕别人使用自己的手机登入服务器,可以为公钥设置一个简单的密码,我们为了方便就不设置密码了

3.点击产生,然后用手指在方框内滑动生成即可

4.在公钥列表界面长按刚才生成的密钥,选择复制公钥,将复制的文本保存出来

5.登陆服务器,找到”/root/.ssh/authorized_keys”文件,如果没有就新建一个,将刚才复制的密钥追加到文件最后

完成以上步骤以后再使用ConnectBot连接服务器时就不需要输入密码了。

sql多关键字匹配,优先权显示的算法

http://hi.baidu.com/%CB%AD%BB%E1%D4%DA%CE%D2%CA%D6%D0%C4/blog/item/de1b0c38d9068827b8998f2a.html

 

假设只有一个table,名为pages,有四个字段,id, url,title,body。里面储存了很多网页,网页的url地址,title和网页的内容,然后你用一个sql查询将url匹配的排在最 前,title匹配的其次,body匹配最后,没有任何字段匹配的,不返回。

就是上面这道面试题,让我想了一个下午,在网上找资料,最后用下面方法实现
SELECT *
FROM page where url like ‘%baidu%’ or title like ‘%baidu%’ or like ”
ORDER BY CHARINDEX(‘baidu’, url) DESC, CHARINDEX(‘baidu’, title) DESC,
CHARINDEX(‘baidu’, body) DESC

但我感觉这种方法并不是最简单的,后来把这个方法发给面试的人,他给我了一种更简单方法,只要用基本的Sql语句就可以实现。代码如下

 

select a.[id],a.mark from
(
select [page].[id],100 as mark from [page] where [page].[url] like ‘%baidu%’
union
select [page].[id],50 as mark from [page] where [page].[title] like ‘%baidu%’
union
select [page].[id],10 as mark from [page] where [page].[body] like ‘%baidu%’
) as a   order by mark desc

用union 实现联合查询,在每个查询语句中定义一个临时变量mark 并给mark赋值,在最后的输出时采用mark来排序,这样实现真的好简单。其实这都考验我们对Sql的编程思想。

PHP采集程序相关

采集程序最简单的思路就是:获取页面代码——分析代码——获取需要的部分——写入数据库。

当然,在获取页面代码之前我们首先要获得被采集页面的url,这里我们从百度新闻获取某关键词最新新闻列表。

function get_baidu_news_url($str){
    if(!$str) return;
    $str = gbk($str);

    //使用正则匹配出列表中的新闻URL
    $html = utf8(file_get_contents('http://news.baidu.com/ns?tn=newstitle&cl=2&rn=20&word=' . urlencode($str)));
    preg_match_all("/<a href=http:\/\/(.+?)  mon=(.+?)>(.+?)<\/a>/is",$html,$match);

    $urlarr = $match[1];
    if($urlarr){
        //URL前面补上http://
        array_walk($new_urlarr, create_function('&$v', '$v = "http://".$v ;'));
        cache_write($cachename, $new_urlarr, CACHE_PATH);
    }
    return $new_urlarr;
}

拿到新闻页面的URL之后,下一步就是采集页面上的新闻,当然这一步要针对各个网站定制不同的匹配规则,这里以新浪为例。新浪新闻以“<!– 正文内容 begin –>”开始,“<!– 正文内容 end –>”结束,所以匹配正文的正则为

preg_match_all("/<!-- 正文内容 begin -->([\s|\S]*?)<!-- 正文内容 end -->/is",$html,$match);

同理,匹配标题的正则为

preg_match_all("/<h1 id=\"artibodyTitle\"(.*?)>(.+?)<\/h1>/is",$html,$title_match);

函数完整代码:

function news_content_sina($url){
    if(!$url) return;
    $html = utf8(file_get_contents($url));
    preg_match_all("/<!-- 正文内容 begin -->([\s|\S]*?)<!-- 正文内容 end -->/is",$html,$match);
 preg_match_all("/<h1 id=\"artibodyTitle\"(.*?)>(.+?)<\/h1>/is",$html,$title_match);

    $title = $title_match[2][0];
    $content = news_content_format($match[1][0]);
    if($title && $content) return compact('url','title','content');
}

上面方法中用到了 news_content_format(),这个方法是用来格式化采集到的正文,去掉js、css、iframe、注释以及站内链接,下面代码中可以看到,我们去除了站内链接但保留了其他的<a>标签链接,这样就可以避免某些重要外链丢失影响新闻完整性,比如某考试报名地址链接。

function news_content_format($content){
    $search = array ("'<script[^>]*?>.*?</script>'si",   // 去掉 javascript
                    "'<style[^>]*?>.*?</style>'si",   // 去掉 css
                    "'<iframe[^>]*?>.*?</iframe>'si",   // 去掉 iframe
                    "'<!--[/!]*?[^<>]*?>'si",           // 去掉 注释 标记
     "'<a(.*?) href=(.*?)(sina.com|weibo.com)(.*?)>(.*?)<\/a>'si",  // 去掉 内部 链接
    );
    $replace = array ("","","","","","\${5}"); 
    $content = preg_replace($search, $replace, $content);
 $content = strip_tags($content, '<p> <br> <img> <table> <tr> <td> <strong> <a>');
 return $content;
}

到这里,采集的功能基本上就完成了,但是还有一点要注意,就是新闻中的图片如果也需要采集到本地的话,就要用到下面这个方法。

function getimage($body){
 global $img_dir,$img_webhost;//本站图片目录、主机

 if(!empty($body)){  
  $body = stripslashes($body);
  $img_array = array();
        //匹配出采集内容中的图片地址
  preg_match_all("/(src|SRC)=[\"|'|]{0,}(http:\/\/(.*)\.(gif|jpg|jpeg|bmp|png))/isU",$body,$img_array);
  $img_array = array_unique($img_array[2]);
  set_time_limit(0);
        //定义图片名,创建目录
  $imgPath = $img_dir."/".strftime("%Y%m%d",time());
  $imgUrl = "http://".$img_webhost."/".$imgPath;
  $milliSecond = strftime("%H%M%S",time());
  if(!is_dir($imgPath)) @mkdir($imgPath,0777);
  foreach($img_array as $key =>$value)
  {
   $value = trim($value);
            //抓取图片并保存
   $get_file = @file_get_contents($value);
   $rndFileName = $imgPath."/".$milliSecond.$key.".".substr($value,-3,3);
   $fileurl = $imgUrl."/".$milliSecond.$key.".".substr($value,-3,3);
   if($get_file)
   {
    $fp = @fopen($rndFileName,"w");
    @fwrite($fp,$get_file);
    @fclose($fp);
   }
   $body = ereg_replace($value,$fileurl,$body);
  }
  return $body;
 }

写入数据库等常规的操作在这里就不再赘述。

『天涯杂谈』说一说河南胡辣汤

无意中从天涯扒出的一篇神文,与喜欢喝胡辣汤的朋友共享之。
引用地址:http://www.tianya.cn/publicforum/Content/free/1/383504.shtml

说起河南的比较有名的小吃,就不能不提起胡辣汤。

自从17岁离开家,很少吃到地道的家乡风味了。前几年一直住集体宿舍,味觉已然到了麻木的地位,对所有美食失去了兴趣。现在生活稳定了,不再漂泊了,对家乡风味的思念却是越来越重,最忘不了的,就是家乡小吃胡辣汤。

盛胡辣汤的的大铝盆就放在蜂窝煤的炉子上,咕嘟咕嘟地冒着热气,那一股股的香气也随着飘散在空中,不时往人们鼻子里钻,于是人们的脚步被香气牵引过来,纷纷围坐在小圆桌上。那边咖啡色的汤里滚动着深绿色的海带,白的粉条和豆腐丝,黄的黄花菜,红的花生仁儿和肉丁,看起来色彩斑斓煞是好看。色香俱全了,人们迫切地想尝尝味道。

盛汤的人手里拿着一柄奇怪的木勺,先深深伸进汤里,来回使劲的搅动几下,然后再溜着锅边把刚好搅的不稠不稀的胡辣汤盛进碗里。盛汤人再熟练的滴点香油和醋,一碗如岩浆般的热汤就摆在你的眼前了。望着这一碗期待中的汤,看其表,暗红色透着些许土色的汤面浮着木耳粉条等原料。低头闻其味,一股热气夹带着香油、醋和汤特有的辣味不由分说奔进你的鼻腔里,通五官,过六腑势如破竹。拿着小勺轻轻搅动两下,有轻微的糊状感。舀上一勺,弯腰伸过头去,吹几下,匝起嘴来,做预备Kiss装,眼望前方,准备和勺子来个荡气回肠的热吻。小嘴就着勺边轻轻地吸几口(当然这几口可能加起来还不到一口),待嘴适应了那股热劲和辣劲,再一口把剩在勺中的木耳等吃尽。身上立刻暖和起来,精神气儿也足了,声调也就提高了八度:再来一碗!喝这一碗的速度显然就慢了不少,慢悠悠的一小口一小口地抿,这时才品出酸辣香的醇厚味道来。

我不知道是否有人考证正确品汤之法?不会是像品葡萄酒时周星星所说的应该把舌头卷成卷吧?不过品葡萄酒时是应该让酒在嘴里来回流动,这样才能品出酒的不同层次。可是我把胡辣汤在嘴里逛荡了N圈,除了汤的温度有点降低外,仍然是浓烈的辣味。不过这种辣不是像四川那种麻辣,也不同于湖南的辛辣,他们靠的是辣椒刺激味蕾。而胡辣汤好像更多的是靠汤的滚烫温度来增加嘴里辣椒般的灼热感,为汤的辣味推波助澜。不过许多种胡辣汤里的辣都是靠的胡椒粉,但我光顾那家店的汤里好像胡椒粉并不是很浓。不过这汤要凉了就只剩辣味了,也使我明白为什么这汤要不断的加热。这胡辣汤里的原料好像有面筋、粉条、黄花菜、长的奇怪的木耳和少许牛杂,大部分其他胡辣汤的原料也基本是这样,也许可能有些海带等其他原料,但主要就是这些了。也许这些原料并不十分的精贵和营养,但却显示了做汤之人的巧夺天工,也正是这点才造就了胡辣汤平民身份,才能使大众享受这份难得的早餐。

卖胡辣汤的摊点,基本上都喜欢打着逍遥镇的牌子,说起来还有缘故。逍遥镇胡辣汤据传其始创于明朝中叶,由由名贵中药和主料熬制而成,一度被封为宫廷饮品。明末清初,天下大乱,御厨赵杞为避战祸,遂携秘方隐居于西华县逍遥镇,从此之后逍遥胡辣汤普及民间,香泽大河南北。而逍遥镇也因此成为胡辣汤的原产地。

两掺,胡辣汤主热辣;而豆腐脑则主清爽;胡辣汤的汤是一种暗红色夹带着其他原料的颜色;而豆腐脑通身洁白一尘不染;胡辣汤如同代表了北方大汉粗犷,豪放的性格;而豆腐脑则代表了南方小家碧玉的特有的细腻温柔。真不知是那位聪明的店家有这神来之笔,把这两样看似不相容的搭上了红线,不过搭配的到十分的有特色。在碗中两位也刹是好看,喝汤时豆腐脑的白色带给我一种视觉和感觉上的放松。味道上豆腐脑的清淡也把胡辣汤的热辣冲淡了不少,也许是这适应南方人的口味,才使胡辣汤的领地扩大到长江以南。