分类 PHP 下的文章

一、多阅读手册和源代码
  没什么比阅读手册更值得强调的事了–仅仅通过阅读手册你就可以学习到很多东西,特别是很多有关于字符串和数组的函数。就在这些函数里面包括许多有用的功能,如果你仔细阅读手册,你会经常发现在以往的项目开发过程中,很多时候你在“重复发明轮子”,而实际上你只需要一个核心函数就可以完成相应的功能。手册是你的朋友。另外,现在有很多使用PHP开发的开源程序。为什么不去学习和借鉴呢?下载一份开源的PHP应用程序的源代码,仔细阅读它吧。也许越大的项目越值得去阅读,虽然它们也许有更复杂的结构和系统,但也有更详细的解释文档。
  
二、编写模块化代码
  良好的PHP代码应该是模块化的代码。PHP的面向对象的编程功能是一些特别强大的工具,可以把你的应用程序分解成函数或方法。你应该尽可能多的从你的应用程序的服务器端分开前端的HTML/CSS/JavaScript代码,你也可以在任何PHP框架上遵循MVC(模型-视图-控制器)模式。
  
三、代码编写规范
  良好的PHP代码应该有一套完整的代码编写规范。通过对变量和函数的命名,统一的方法访问数据库和对错误的处理,以及同样的代码缩进方式等来达到编程规范,这样可以使你的代码更具可读性。
 
四、编写可移植代码
  良好的PHP代码应该是可移植的。你可以使用php的现有功能,如魔术引号和短标签。试着了解你的需求,然后通过适应PHP特性来编写代码让代码独立、可移植。
  
五、编写安全代码
  良好的PHP代码应该是安全的。PHP5提供了出色的性能和灵活性。但是安全问题完全在于开发人员。对于一个专业的PHP开发人员来说,深入理解重大安全漏洞是至关重要的,如:跨站点脚本(XSS)、跨站请求伪造(CSRF)、代码注入漏洞、字符编码漏洞。通过使用PHP的特殊功能和函数,如:mysql_real_escape_string等等,你可以编写出安全的代码。
  
六、代码注释
  代码注释是代码的重要组成部分。通过代码注释可以知道该变量或函数是做什么的,这将在今后的代码维护中十分有用。
  
七、使用单引号代替双引号
  字符串始终使用单引号代替双引号,以避免PHP搜索字符串内的变量导致的性能下降。用单引号代替双引号来包含字符串,这样做会更快一些。因为PHP会在双引号包围的字符串中搜寻变量,单引号则不会
  
八、转义字符串输出
  使用ENT_QUOTES作参数传递给htmlspecialchars函数,以确保单引号(')也转换成HTML实体,这是一个好习惯。
  
九、使用逗号分隔字符串输出
  通过echo语句输出使用逗号(,)分隔的字符串,要比使用字符串连接操作符(.)的性能更好。
  
十、输出前检查传来的值
  输出前检查传过来的值$_GET['query']。使用isset或empty函数,可以用来检查变量是否为null值。

工厂模式

工厂模式是最常用也是最简单的一种设计模式了,不需要用关键字new就可以获取实例,减少代码耦合,提高代码的可扩展性。
例如你想修改某个实例化的类名,不需要去每个实例化的地方改,可以直接在工厂模型修改即可。

简单的例子:

class Factory
{
    public static function get Instance (string $newclass)
    {
        return new $class;
    }
}
$object = Factory::getInstance('class1')

单例模式

单例模式,最大的特点是,在整个应用进程中,只会存在一个该类的实例,一旦创建,就会一直保存在内存中。
一般具备以下几个特征,1、私有的静态变量,用来存放实例,2、私有的构造和克隆方法,3、公有的静态方法对外界提供获取实例入口,俗称三私一公。
最常用的场景应该是数据库模型了,使用单例模式,只需连接一次数据库,节约资源。

简单的例子:

class SingleCase 
{
    private static $_instance;

    private function __construct(){}

    private function __clone(){}

    public static function getInstance()
    {
        return self::$_instance = new self();
    }

}
$instance = SingleCase::getInstance();

观察者模式

当一个对象状态发生变化时,依赖他的对象全部会收到通知,并自动更新。是一种低耦合,非入侵式的通知和更新机制。
一个事件发生后,要执行一连串更新操作,传统的编程方式,就是在事件的代码之后直接加入处理的逻辑。当更新的逻辑越来越多的时候,代码会变得难以维护,观察者模式解决了这个问题。
简单的例子

//主题接口
interface Subject 
{
    public function register(Observer $observer);
    public function notify();
}

// 观察者接口
interface Observer 
{
    public function watch();
}

//主题
class Action implements Subject 
{
    public $_observers = [];
    public function register(Observer $observer)
    {
        $this->_observers[] = $observer; 
    }

    public function notify()
    {
        foreach ($this->_observers as $o) {
            $o->watch();
        }
    }
}


//观察者
class Cat implements Observer
{
    public function watch ()
    {
        echo 'cat watch';
    }
}

class Dog implements Observer 
{
    public function watch()
    {
        echo 'dog watch';
    }
}

class People implements Observer 
{
    public function watch()
    {
        echo 'people watch';
    }
}

//注册动作
$act = new Action();
$act->register(new Cat);
$act->register(new Dog);
$act->register(new People);


//调用实例
$act->notify();

#注册模式
注册模式,解决了全局共享和交换对象问题。已经创建好的对象,挂在到某个全局可以使用的数组上,在需要使用的时候,直接从该数组上获取即可。将对象注册到全局的树上。任何地方直接去访问。

代码示例

class Register
{
    protected static  $objects;
        function set($alias,$object)//将对象注册到全局的树上
        {
            self::$objects[$alias]=$object;//将对象放到树上
        }
        static function get($name){
        return self::$objects[$name];//获取某个注册到树上的对象
    }
    function _unset($alias)
  {
        unset(self::$objects[$alias]);//移除某个注册到树上的对象。
    }
}

适配器模式

将各种不同的函数接口封装成统一的api
例如php的数据库操作有mysql、mysqli、pdo三种,可以使用适配器统一成一个对外接口
首先定义个接口,有几种不同的情况,就写几个类实现该接口。将完成相似功能的函数,统一成一致的方法。

/**
 * 目标角色
 */
interface Target {
 
    /**
     * 源类也有的方法1
     */
    public function sampleMethod1();
 
    /**
     * 源类没有的方法2
     */
    public function sampleMethod2();
}
 
/**
 * 源角色
 */
class Adaptee {
 
    /**
     * 源类含有的方法
     */
    public function sampleMethod1() {
        echo 'Adaptee sampleMethod1 <br />';
    }
}
 
/**
 * 类适配器角色
 */
class Adapter extends Adaptee implements Target {
 
    /**
     * 源类中没有sampleMethod2方法,在此补充
     */
    public function sampleMethod2() {
        echo 'Adapter sampleMethod2 <br />';
    }
 
}
 
class Client {
 
    /**
     * Main program.
     */
    public static function main() {
        $adapter = new Adapter();
        $adapter->sampleMethod1();
        $adapter->sampleMethod2();
 
    }
 
}

一般来说,cookie与session被认为是两种不同的缓存机制。cookie采用的是在客户端存储方案, 而session采用的是在服务器端存储方案。
但是,一般情况下,如果浏览器禁用了cookie,session同样也无法使用了!这是为什么呢?原来,服务器在每次session_start()开启session的时候会先检测一下session_id,如果存在则继续使用之前创立的session文件,如果不存在则重新创建一个session文件来存储新的缓存,从而之前session也就失效了,而这个session_id默认是通过cookie传递的,所以浏览器一禁用cookie,session_id得不到传递,session也就失效了。

那么,如何解决客户端禁用cookie的问题呢!

1、设置php.ini中的session.use_trans_sid = 1 让php自动跨页传递session_id。
2、手动通过url传递session_id
3、用文件、数据库等形式保存session_id,在跨页的时候手动调用。

为了验证下以上三点,特意从网上找了三个例子:

示例1:
s1.php

 <?php
    session_start();
    $_SESSION[’var1’]="测试user_trans_sid";
    $url="<a href=".""s2.php">下一页</a>";
    echo $url;
    ?>

s2.php

 <?php
    session_start();
    echo "传递的session变量var1的值为:".$_SESSION[’var1’];
    ?>

运行以上代码,在客户端cookie正常的情况下,应该可以在得到结果“测试user_trans_sid”。
现在你手动关闭客户端的cookie,再运行,可能得不到结果了吧。如果得不到结果,再“设置php.ini中的session.use_trans_sid = 1或者编译时打开打开了--enable-trans-sid选项”,又得到结果“测试user_trans_sid”
ps:这里需要补充一下,部分服务器设置完session.use_trans_sid=1之后session仍然无效,原因是php.ini中还有这么一个选项 session.use_only_cookies=1 表示是否只开启基于cookie的session,如果想要设置生效必须把它设为 session.use_only_cookies=0

示例2:
s1.php

 <?php
    session_start();
    $_SESSION[’var1’]="url传值测试";
    $sn = session_id();
    $url="<a href=".""s2.php?s=".$sn."">下一页</a>";
    echo $url;
    ?>

s2.php

<?php
session_id($_GET[’s’]);
session_start();
echo "传递的session变量var1的值为:".$_SESSION[’var1’];
?> 

基础函数

count 计算数组的长度
current 返回当前指针指向的元素值
each 返回数组中当前的键值对,并将内部指针向前移动
end 将内部指针指向数组中的最后一个元素,并输出
next 将内部指针指向数组中的下一个元素,并输出
prev 将内部指针指向数组中的上一个元素,并输出
reset 将内部指针指向数组的第一个元素,并输出

排序相关

sort 对数组进行升序排列
rsort 对数组进行降序排列
asort 根据数组的值,对数组进行升序排列
ksort 根据数组的键,对数组进行升序排列
arsort 根据数组的值,对数组进行降序排列
krsort 根据数组的键,对数组进行降序排列

比较函数

in_array 判断某数值是否存在数组里
array_diff 比较数组,返回差集
array_diff_key 比较数组键名,返回差集
array_diff_assoc 比较数组键名和键值,返回差值
array_intersect 比较数组键值,返回交集
array_intersect_key 比较数组键名,返回交集
array_intersect_assoc 比较数组键名和键值,返回交集