如无特别说明,以下题目均可用各种技术方案来解答。

Posted by & filed under 每日一题.

【四脚猫】每日一题(5月13日): 为了节省服务器带宽,有时候不得不去设置资源的防盗链规则,不管你目前用的是IIS、Apache还是Nginx或者其它,你能给出png、gif、jpg等图片的防盗链规则吗,要求每条规则给予解释。

1
2
3
4
5
6
7
8
9
10
11
# 防盗链配置
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^$ [NC]
RewriteCond %{HTTP_REFERER} !sijiaomao.com [NC]
RewriteCond %{HTTP_REFERER} !google.com [NC]
RewriteCond %{HTTP_REFERER} !baidu.com [NC]
RewriteCond %{HTTP_REFERER} !sogou.com [NC]
RewriteCond %{HTTP_REFERER} !so.com [NC]
RewriteCond %{HTTP_REFERER} !youdao.com [NC]
RewriteCond %{HTTP_REFERER} !yahoo.cn [NC]
RewriteRule .*\.(gif|jpg|png)$  http://www.sijiaomao.com/images/no.gif [R,NC,L]

简单的解释一下上述语句:

1、RewriteCond %{HTTP_REFERER} !^$ [NC]

允许空“HTTP_REFERER”的访问,即允许用户在浏览器地址栏中直接输入图片地址时图片文件的显示。一般而言,这是可选的,不过,建议这么设置,如果强迫必须具有“HTTP_REFERER”才能访问,可能会带来某些问题,比如说在用户通过代理服务器访问时。

2、RewriteCond %{HTTP_REFERER} !sijiaomao.com [NC]

设置允许访问的HTTP来源,包括我们的站点自身、Google、Baidu、sogou、youdao等。

3、RewriteRule .*\.(gif|jpg|png)$ http://www.sijiaomao.com/images/no.gif [R,NC,L]

定义被盗链时替代的图片,让所有盗链 jpg、gif、png 等文件的网页,显示根目录下的 no.png 文件。注意:替换显示的图片不要放在设置防盗链的目录中,并且该图片文件体积越小越好。当然你也可以不设置替换图片,而是使用下面的语句即可:

RewriteRule .*\.(gif|jpg|png)$ – [F]

4、说明一下其中的R、NC 和 L

R 就是转向的意思
NC 指的是不区分大小写
L 的作用是指明本次转向到此结束,后续的转向不受先前判断语句的影响

5、防止盗链的文件类型

上例中是 gif、jpg、png,而根据需要,可更改或添加其他文件类型,如rar、mov等,不同文件扩展名间使用“|”分割。

这样的话,就可以基本做到简单的防止被盗链情况的发生,而且可以尽最大可能的减少服务器流量的无畏消耗,当然了,如果你不在意这点流量的话,那么可以不用考虑上述设置啦!

Posted by & filed under 每日一题.

【四脚猫】每日一题(5月12日): 11日的高级课程里面讲到了PHP5.5的新特性-生成器,它提供了一种更容易的方法来实现简单的对象迭代,试着用yield来创建一个生成器,然后逐行读取文件内容。

追忆初见果然是高手,新特性都掌握了!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function getLines($path)
{
$f = fopen($path,'r');
while(!feof($f))
{
$data = fgets($f);
yield $data;
}

fclose($f);

}

foreach(getLines($path) as $line=>$val)
{
if($line>100000) break;
echo $val."<br />";
}

Posted by & filed under 每日一题.

【四脚猫】每日一题(5月10 日):在PHP中define和const都能定义常量,他们有什么区别呢,如何选择呢?

风兮的答案比较完善了:
const
1. 在5.3+版本可以使用.
2. const 是语法
3. 使用 const 关键字定义常量必须处于最顶端的作用区域
4. 常量名字要符合命名规则
5. 区分大小写

define
1. 不限版本
2. 是一个函数
3. 随处可以定义
4. 如果第三个参数设为true, 则此常量不区分大小写
5. 任何字符串都可以当名字, 如果这个名字不符合PHP命名规则, 可以用constant()函数来取常量的值.

Posted by & filed under 每日一题.

【四脚猫】每日一题(5月8日): 经常有phper问,在yii框架中,我自己定义全局的函数如何,为什么非要用类呢?为什么非要用面向对象编程呢?你能给他们一个心服口服的解释吗?

面向对象和面向过程的区别,实在是难用一两句话说明白。

面向过程是一种直接的编程方法,它是按照编程语言的思路考虑问题。尤其是想C语言这种过程式语言,它就是通过顺序执行一组语句来实现一个功能,这些语句的执行过程就是整个程序。不同的语言解决同一个问题的过程是不一样的。

面向对象是一种抽象度更高的编程方法。它把眼光集中在了要解决问题本身而不是语言上。它的目标是使模块的抽象度更高,可复用性更好。面向对象的目的就是可复用。
举个例子,比如我们要写一个计算器程序。这个计算机目前只要求有加减乘除四种运算。

用面向过程的方法,我们可能直接就写一个main函数。然后就开始定义一些数据结构,然后就开始写add,sub,multi,div等函数,去实现功能。

用面向对象的方法,我们会先定义一个Calculator类。然后定义一些必要的数据成员,然后在定义add,sub,multi,div这四个成员函数(这四个函数的功能实现和上面四个应该是基本一样的)。

从上面的实现来看,这两种实现方法的差别不是很大,甚至第二种看上去还有些多此一举。

接下来,我们要扩展这个计算器,让它能计算指数。

用面向过程的方法,我们会将上面实现的代码全部copy过来,然后再增加一个power函数。

用面向对象的方法,我们会定义一个CalculatorEx类公有继承自Calculator,再在CalculatorEx中实现Power函数。

上面只是一个简单的扩展,二者的区别就明显起来。面向过程是纯代码级的复用。面向对象的复用方式更为优雅,它可以是代码级的,也可以是类级的,也可以是接口级的,也可以是组件级的,甚至是服务级的。抛下这些复用概念不说。我们假设第一次实现的并不是简单的四个功能,而是一个复杂的库,第二次增加的也不是一个功能而是一个扩展库。这时候面向对象的优势就会比较明显的体现出来。面向过程是松散部件,而面向对象是一个体系。

我说的这些都是自己的理解,可能并不完全正确。对于面向对象有一个官方的定义,但是不同人有不同的理解。所以里面的很多东西都需要在学习的过程中去理解体会。但是,如果不动手做点东西,对这些概念很难理解到位。

还有就是,C,C++,Java这些都是语言,他们之间并没有是不是面向对象的区别。用C同样可以写面向对象的程序,看看Linux的内核代码就知道了。C++,Java一样可以写面向过程的程序,他们之所以叫面向对象的编程语言是因为他们提供的语言特性更易于实现面向对象的编程方法,并不是说他们只能做面向对象编程。

还有就是并不是说面向对象一定优于面向过程。在很多领域是无法实施面向对象的方法,如硬件编程和嵌入式编程这种实时性和效率要求高的领域就无法用到面向对象。面向对象的主要领域还是用在大型,复杂型的软件系统中。

更加详细的分析参见 :http://202.120.43.103/downloads2/d2f78503-9f23-4867-a6ea-0bc61ba83f57.pdf

Posted by & filed under 每日一题.

【四脚猫】每日一题(5月7日): 单例模式是比较常见的一种设计模式,试试看,能否实现一个比较完美的单例模式?

以下是“Web程序猿” 的版本:

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
<?php
/**
+-----------------------------------------
* 四脚猫每日一题-用PHP实现一个单例模式
+-----------------------------------------
* @description   完美的单例模式????
* @author   诺天  thinkercode@sina.com
* @date 2014年5月7日
+-----------------------------------------
*/

class singleton{
public static $instance = null;

/**
* 对象初始化方法,防止继承覆盖和new该类
* @access private
* @return void
*/

final private function __construct(){}

/**
* 获取对象实例
* @access public
* @return object
*/

static public function getInstances(){
if(!(self::$instances instanceof self)){
self::$instance = new self;
}
return self::$instance ;
}

/**
* 让克隆也实现单例
* @access public
* @return void
*/

final public function __clone(){
return self::$instance ;
}

/**
* 让克隆不能使用
* @access private
* @return void
*/

//final private function __clone(){}
}

Posted by & filed under 每日一题.

【四脚猫】每日一题(5月5日): 在数组中判断 array(“name” => 3333, “id” => 3) 是否存在二维数组中。

1
2
3
4
5
6
7
$items = [
    0 => ["name" => 1111, "id" => 1],
    1 => ["name" => 2222, "id" => 2],
    2 => ["name" => 3333, "id" => 3],
    3 => ["name" => 4444, "id" => 4],
    4 => ["name" => 5555, "id" => 3]
];

有什么好办法?

答案思路:
Ateoa 的 array_search 和 hua 的 in_array 都能快速的解决这个问题。
Zjmainstay 的 serialize 方法也是另外的一种技巧。

Posted by & filed under 每日一题.

【四脚猫】每日一题(5月4日): 目前移动互联网比较火,做网站开发的时候有时候需要判断访问来源是否手机?试着写写如何判断呢,尽可能让自己的代码比较完备。

以下代码来自wordpress,供大家参考。

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
/**
 * Test if the current browser runs on a mobile device (smart phone, tablet, etc.)
 *
 * @return bool true|false
 */

function wp_is_mobile() {
    static $is_mobile;

    if ( isset($is_mobile) )
        return $is_mobile;

    if ( empty($_SERVER['HTTP_USER_AGENT']) ) {
        $is_mobile = false;
    } elseif ( strpos($_SERVER['HTTP_USER_AGENT'], 'Mobile') !== false
        || strpos($_SERVER['HTTP_USER_AGENT'], 'Android') !== false
        || strpos($_SERVER['HTTP_USER_AGENT'], 'Silk/') !== false
        || strpos($_SERVER['HTTP_USER_AGENT'], 'Kindle') !== false
        || strpos($_SERVER['HTTP_USER_AGENT'], 'BlackBerry') !== false
        || strpos($_SERVER['HTTP_USER_AGENT'], 'Opera Mini') !== false
        || strpos($_SERVER['HTTP_USER_AGENT'], 'Opera Mobi') !== false ) {
            $is_mobile = true;
    } else {
        $is_mobile = false;
    }

    return $is_mobile;
}