对于用过smarty做过php开发的朋友来说,应该都知道在smarty模板里面判断foreach循环是否是最后一个可以$smarty.foreach.name.last来判断循环是否到了最后一条记录,在thinkphp的模板中常见的循环是volist,但是volist的各种属性中并没有直接判断最后一条记录的属性,那么在thinkphp中如何判断呢?下面的代码可以实现ThinkPHP中volist断最后一条记录。

举例代码如下:

<volist name='lists' id='list'>
<li <if condition="$i eq count($lists)">class="last"</if>>
<a href="http://www.cnweed.com/">野草博客</a>
</li>
</volist>

转载:http://www.jb51.net/article/51718.htm

GROUP BY语法可以根据给定数据列的每个成员对查询结果进行分组统计,最终得到一个分组汇总表。SELECT子句中的列名必须为分组列或列函数。列函数对于GROUP BY子句定义的每个组各返回一个结果。

某个员工信息表结构和数据如下:

id  name  dept  salary  edlevel  hiredate
1 张三 开发部 2000 3 2009-10-11
2 李四 开发部 2500 3 2009-10-01
3 王五 设计部 2600 5 2010-10-02
4 王六 设计部 2300 4 2010-10-03
5 马七 设计部 2100 4 2010-10-06
6 赵八 销售部 3000 5 2010-10-05
7 钱九 销售部 3100 7 2010-10-07
8 孙十 销售部 3500 7 2010-10-06

例如,我想列出每个部门最高薪水的结果,sql语句如下:

SELECT DEPT, MAX(SALARY) AS MAXIMUM
FROM STAFF
GROUP BY DEPT

查询结果如下:

DEPT  MAXIMUM
开发部 2500
设计部 2600
销售部 3500

解释一下这个结果:
1、满足“SELECT子句中的列名必须为分组列或列函数”,因为SELECT有GROUP BY DEPT中包含的列DEPT。
2、“列函数对于GROUP BY子句定义的每个组各返回一个结果”,根据部门分组,对每个部门返回一个结果,就是每个部门的最高薪水。
注意:计算的是每个部门(由 GROUP BY 子句定义的组)而不是整个公司的 MAX(SALARY)。
例如,查询每个部门的总的薪水数:

SELECT DEPT, SUM( SALARY ) AS total
FROM STAFF
GROUP BY DEPT

查询结果如下:

DEPT  total
开发部 4500
设计部 7000
销售部 9600

将 WHERE 子句与 GROUP BY 子句一起使用
分组查询可以在形成组和计算列函数之前具有消除非限定行的标准 WHERE 子句。必须在GROUP BY 子句之前指定 WHERE 子句。
例如,查询公司2010年入职的各个部门每个级别里的最高薪水

SELECT DEPT, EDLEVEL, MAX( SALARY ) AS MAXIMUM
FROM staff
WHERE HIREDATE > ’2010-01-01′
GROUP BY DEPT, EDLEVEL
ORDER BY DEPT, EDLEVEL

查询结果如下:

DEPT  EDLEVEL  MAXIMUM
设计部 4 2300
设计部 5 2600
销售部 5 3000
销售部 7 3500

注意:在SELECT语句中指定的每个列名也在GROUP BY子句中提到。未在这两个地方提到的列名将产生错误。

GROUP BY子句对DEPT和EDLEVEL的每个唯一组合各返回一行
在GROUP BY子句之后使用HAVING子句可应用限定条件进行分组,以便系统仅对满足条件的组返回结果。为此,在GROUP BY子句后面包含一个HAVING子句。HAVING子句可包含一个或多个用AND和OR连接的谓词。每个谓词将组特性(如AVG(SALARY))与下列之一进行比较:
例如:寻找雇员数超过2个的部门的最高和最低薪水:

SELECT DEPT, MAX( SALARY ) AS MAXIMUM, MIN( SALARY ) AS MINIMUM
FROM staff
GROUP BY DEPT
HAVING COUNT( * ) >2
ORDER BY DEPT

查询结果如下:

DEPT  MAXIMUM  MINIMUM
设计部 2600 2100
销售部 3500 3000

例如:寻找雇员平均工资大于3000的部门的最高和最低薪水:

SELECT DEPT, MAX( SALARY ) AS MAXIMUM, MIN( SALARY ) AS MINIMUM
FROM staff
GROUP BY DEPT
HAVING AVG( SALARY ) >3000
ORDER BY DEPT

查询结果如下:

DEPT MAXIMUM MINIMUM
销售部 3500 3000

转载:https://blog.phpha.com/backup/archives/353.html

thinkphp volist循环嵌套if标签判断
今天用volist循环嵌套if标签判断的时候,if判断不能成功,报错,如下示例:

<volist name="list" id="vo">
<volist name="slist" id="s">
<if condition="$s.sid eq $vo.id">
内容。。。。。
</if>
</volist>
</volist>

如果if语句像上面那样写,数据永远也取不出来,因为condition里面写的是PHP原生代码,所以如果是数组要换成中括号的写法,将IF语里的condition表达式换成:$s[‘id’] eq $vo.sid 或者:$s[‘id’] eq $vo[‘sid’],当前的volist的值可不用换成PHP原生数组的形式,上一级的换就OK,也可两个都换成原生数组的形式进行比较。以下是正确代码:

<volist name="list" id="vo">
<volist name="slist" id="s">
<if condition="$s.sid eq $vo['id']">   //或者<if condition="$s['sid'] eq $vo['id']">
内容。。。。。
</if>
</volist>
</volist>

转载:http://www.web-fish.com/program/535.html

今日我生日,小黄25日23点40左右给我电话,让我快下来,在西兜旁边等我。我当然知道狗儿给我准备了礼物,满怀期待的跑下去,脸都笑裂了。

我下去还没找到她,躲起来了,囧。像个三岁的孩子,囧。躲也不会躲好点儿,一看就知道了好嘛!囧。能不能不要这么蠢!囧。我还要假装不那么快找不到给她挽尊。囧。捧着一小个蛋糕,蜡烛已经灭了好多根,一脸蠢萌,可爱的我都化了,心里像开花了一样。:)

var time_range = function (beginTime, endTime, nowTime) {
    var strb = beginTime.split (":");
    if (strb.length != 2) {
        return false;
    }

    var stre = endTime.split (":");
    if (stre.length != 2) {
        return false;
    }

    var strn = nowTime.split (":");
    if (stre.length != 2) {
        return false;
    }
    var b = new Date ();
    var e = new Date ();
    var n = new Date ();

    b.setHours (strb[0]);
    b.setMinutes (strb[1]);
    e.setHours (stre[0]);
    e.setMinutes (stre[1]);
    n.setHours (strn[0]);
    n.setMinutes (strn[1]);

    if (n.getTime () - b.getTime () > 0 && n.getTime () - e.getTime () < 0) {
        return true;
    } else {
        alert ("当前时间是:" + n.getHours () + ":" + n.getMinutes () + ",不在该时间范围内!");
        return false;
    }
}
time_range ("21:30", "23:30", "3:22");

效果

2012091317403446

var time_range = function (beginTime, endTime) {
    var strb = beginTime.split (":");
    if (strb.length != 2) {
        return false;
    }

    var stre = endTime.split (":");
    if (stre.length != 2) {
        return false;
    }

    var b = new Date ();
    var e = new Date ();
    var n = new Date ();

    b.setHours (strb[0]);
    b.setMinutes (strb[1]);
    e.setHours (stre[0]);
    e.setMinutes (stre[1]);

    if (n.getTime () - b.getTime () > 0 && n.getTime () - e.getTime () < 0) {
        return true;
    } else {
        alert ("当前时间是:" + n.getHours () + ":" + n.getMinutes () + ",不在该时间范围内!");
        return false;
    }
}
time_range ("21:30", "23:30");

下载:wget http://mysqltuner.pl/ -O mysqltuner.pl

运行:perl mysqltuner.pl 结果:

>>  MySQLTuner 1.4.0 - Major Hayden <major@mhtx.net>
 >>  Bug reports, feature requests, and downloads at http://mysqltuner.com/
 >>  Run with '--help' for additional options and output filtering
Please enter your MySQL administrative login: root
Please enter your MySQL administrative password:
[OK] Currently running supported MySQL version 5.5.41-0+wheezy1
[OK] Operating on 64-bit architecture

-------- Storage Engine Statistics -------------------------------------------
[--] Status: +ARCHIVE +BLACKHOLE +CSV -FEDERATED +InnoDB +MRG_MYISAM
[--] Data in InnoDB tables: 1M (Tables: 11)
[--] Data in PERFORMANCE_SCHEMA tables: 0B (Tables: 17)
[!!] Total fragmented tables: 11

-------- Security Recommendations  -------------------------------------------
[OK] All database users have passwords assigned

-------- Performance Metrics -------------------------------------------------
[--] Up for: 47s (113 q [2.404 qps], 42 conn, TX: 19K, RX: 7K)
[--] Reads / Writes: 100% / 0%
[--] Total buffers: 192.0M global + 2.7M per thread (151 max threads)
[OK] Maximum possible memory usage: 597.8M (60% of installed RAM)
[OK] Slow queries: 0% (0/113)
[OK] Highest usage of available connections: 0% (1/151)
[OK] Key buffer size / total MyISAM indexes: 16.0M/99.0K
[!!] Query cache efficiency: 0.0% (0 cached / 71 selects)
[OK] Query cache prunes per day: 0
[OK] Temporary tables created on disk: 25% (54 on disk / 213 total)
[OK] Thread cache hit rate: 97% (1 created / 42 connections)
[OK] Table cache hit rate: 24% (52 open / 215 opened)
[OK] Open file limit used: 4% (48/1K)
[OK] Table locks acquired immediately: 100% (62 immediate / 62 locks)
[OK] InnoDB buffer pool / data size: 128.0M/1.2M
[OK] InnoDB log waits: 0
-------- Recommendations -----------------------------------------------------
General recommendations:
    Run OPTIMIZE TABLE to defragment tables for better performance
    Enable the slow query log to troubleshoot bad queries
Variables to adjust:
    query_cache_limit (> 1M, or use smaller result sets)

第一,需要添加一个 php 文件来实现删除功能,文件添加到:ueditor\php\action_delete.php 代码内容:

<?php

/*---------------------------
 * Flyヽ
 * http://lfei.org
 * 2016-02-04
 * action_delete.php
 * 删除 Ueditor 目录下的文件
 *---------------------------*/

try {
    //获取路径
    $path = $_POST['path'];
    $path = str_replace('../', '', $path);
    $path = str_replace('/', '\\', $path);
    
    //安全判断(只允许删除 ueditor 目录下的文件)
    if(stripos($path, '\\ueditor\\') !== 0)
    {
        return '非法删除';
    }
    
    //获取完整路径
    $path = $_SERVER['DOCUMENT_ROOT'].$path;
    if(file_exists($path)) {
        //删除文件
        unlink($path);
        return 'ok';
    } else {
        return '删除失败,未找到'.$path;
    }
} catch (Exception $e) {
    return '删除异常:'.$e->getMessage();
}

第二,需要在ueditor\php\controller.php文件的switch中添加命令 deleteimage 的处理:

....

switch ($action) {

    ....
   
    /* 删除图片命令处理 */
    case 'deleteimage':
         $result = include('action_delete.php');
         break;
    
    /* 在 default 之前添加 */
    default:
        $result = json_encode(array(
            'state'=> '请求地址出错'
        ));
        break;

}

....

第三,在图片上添加删除按钮,需要修改 Js 文件:ueditor\dialogs\image\image.js

....

/* 在这两句之后添加 */
item.appendChild(img);
item.appendChild(icon);

/* 添加删除功能 */
item.appendChild($("<span class='delbtn' url='" + list[i].url + "'>✖</span>").click(function() {
    var del = $(this);
    try{
        window.event.cancelBubble = true; //停止冒泡
        window.event.returnValue = false; //阻止事件的默认行为
        window.event.preventDefault();    //取消事件的默认行为  
        window.event.stopPropagation();   //阻止事件的传播
    } finally {
        if(!confirm("确定要删除吗?")) return;
        $.post(editor.getOpt("serverUrl") + "?action=deleteimage", { "path": del.attr("url") }, function(result) {
            if (result == "ok") del.parent().remove();
            else alert(result);
        });
    }
})[0]);

/* 在这一句之前添加 */
this.list.insertBefore(item, this.clearFloat);

....

第四,为删除按钮添加一个样式,修改文件:ueditor\dialogs\image\image.css在最底部添加如下代码:

/* 在线管理删除按钮样式 */
#online li .delbtn {      
    position: absolute;
    top: 0;
    right: 0;
    border: 0;   
    z-index: 3;
    color: #ffffff;
    display: inline;
    font-size: 12px;
    line-height: 10.5px;
    padding:3px 5px;
    text-align: center;
    background-color: #d9534f;
}

效果如下:
1454606856781543

转自:http://lfei.org/ueditor-manage-image-delete/

刚刚收到警告通知,一台机器的宽带使用率异常。通过top和ps aux等却看不出异常用户,负载正常;且低于常规。通过iftop看到基本都是一个IP在发送数据出去,请求数据的IP(攻击IP)有十多个段,封锁了请求IP后。查了下这些IP是CloudFlare和百度云加速的,很明显是被CC但CloudFlare和百度云加速没过滤掉发送给后端了。

发送数据的IP(被攻击网站IP)是共享的,下面有很多网站,直接封这IP会导致这IP下的所有网站挂掉。所以只能找到具体被攻击的网站和用户进一步操作,一个个看明显是不可能的。

DirectAdmin 用户的每个网站都有单独的apache日记,我们可以根据这特性,把请求数据持续时间相对长、大的ip拿出来,对所有用户的网站日记进行过滤搜索。

[root@****** ~]# grep -c 141.101.98.211 /var/log/httpd/domains/*.log | grep -v :0

/var/log/httpd/domains/****1g.com.log:1
/var/log/httpd/domains/****1g.com.error.log:30
/var/log/httpd/domains/****xv.com.log:12266

[root@****** ~]# grep -c 162.158.88.52 /var/log/httpd/domains/*.log | grep -v :0
/var/log/httpd/domains/****xv.com.log:6385

只拿出2个IP就找到了,很明显的是:****xv.com,然后具体检查该网站日记,发现从凌晨1点30分开始,到50分拒绝百度加速的请求,其实封十几个段还只是部分,这之间GET请求量已经有35万多次了,请求的IP数量未统计,非常之多,尾巴也是特别随机定制为穿透百度CDN的。之后联系到该用户,要求马上把百度云加速CC防护开到最高。然后解除刚刚封锁的IP段恢复该CDN的正常请求。算是解决了。

也许会问为什么服务器本身不能做防护?这次是比较特殊的,用户使用CDN隐藏了后端真实IP,所以攻击者不能直接对我们进行攻击,而是请求CDN,最终导致宽带占用异常的是CDN的IP,同样我们也无法正确获取到攻击者的IP,也无法对真实攻击者ip进行屏蔽,当然有方案可以做到,但我们屏蔽并没有用,CDN还是会放行;除非获取到真实攻击IP后反扑。CDN很多在用,我们肯定是不能封的。即使制定规则丢弃CC请求返回301给CDN,结局也是一样的;因为请求不会因此停止和减少,会继续对301页面请求,因为量大,宽带占用率并不会下降。只能与用户共同处理该问题。

这里只列出比较常用的参数,详细的请查看man iptables

1、查看
iptables -nL --line-number

-L 查看当前表的所有规则,默认查看的是filter表,如果要查看NAT表,可以加上-t NAT参数
-n 不对ip地址进行反查,加上这个参数显示速度会快很多
-v 输出详细信息,包含通过该规则的数据包数量,总字节数及相应的网络接口
–line-number 显示规则的序列号,这个参数在删除或修改规则时会用到

2、添加
添加规则有两个参数:-A和-I。其中-A是添加到规则的末尾;-I可以插入到指定位置,没有指定位置的话默认插入到规则的首部。

当前规则:

[root@test ~]# iptables -nL --line-number
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 DROP all -- 192.168.1.1 0.0.0.0/0
2 DROP all -- 192.168.1.2 0.0.0.0/0
3 DROP all -- 192.168.1.4 0.0.0.0/0

添加一条规则到尾部:

[root@test ~]# iptables -A INPUT -s 192.168.1.5 -j DROP再插入一条规则到第三行,将行数直接写到规则链的后面:

[root@test ~]# iptables -I INPUT 3 -s 192.168.1.3 -j DROP查看:

[root@test ~]# iptables -nL --line-number
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 DROP all -- 192.168.1.1 0.0.0.0/0
2 DROP all -- 192.168.1.2 0.0.0.0/0
3 DROP all -- 192.168.1.3 0.0.0.0/0
4 DROP all -- 192.168.1.4 0.0.0.0/0
5 DROP all -- 192.168.1.5 0.0.0.0/0

可以看到192.168.1.3插入到第三行,而原来的第三行192.168.1.4变成了第四行。

3、删除

删除用-D参数

删除之前添加的规则(iptables -A INPUT -s 192.168.1.5 -j DROP):

[root@test ~]# iptables -D INPUT -s 192.168.1.5 -j DROP有时候要删除的规则太长,删除时要写一大串,既浪费时间又容易写错,这时我们可以先使用–line-number找出该条规则的行号,再通过行号删除规则。

[root@test ~]# iptables -nv --line-number
iptables v1.4.7: no command specified
Try `iptables -h' or 'iptables --help' for more information.
[root@test ~]# iptables -nL --line-number
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 DROP all -- 192.168.1.1 0.0.0.0/0
2 DROP all -- 192.168.1.2 0.0.0.0/0
3 DROP all -- 192.168.1.3 0.0.0.0/0

删除第二行规则

[root@test ~]# iptables -D INPUT 24、修改

修改使用-R参数

先看下当前规则:

[root@test ~]# iptables -nL --line-number
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 DROP all -- 192.168.1.1 0.0.0.0/0
2 DROP all -- 192.168.1.2 0.0.0.0/0
3 DROP all -- 192.168.1.5 0.0.0.0/0

将第三条规则改为ACCEPT:

[root@test ~]# iptables -R INPUT 3 -j ACCEPT再查看下:

[root@test ~]# iptables -nL --line-number
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 DROP all -- 192.168.1.1 0.0.0.0/0
2 DROP all -- 192.168.1.2 0.0.0.0/0
3 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0

第三条规则的target已改为ACCEPT。

参考:http://yh.512876.com/diannao/462.html