场景介绍:以下是自己开发一个框架必备的一些基础知识点。
一、PHP常用的四种数据结构
简介:spl是php的一个标准库。
官方文档:http://php.net/manual/zh/book.spl.php
<?php
//spl(php标准库)数据结构
/**
* 栈(先进后出)
*/
$stack = new SplStack();
$stack->push('data1');//入栈(先进后出)
$stack->push('data2');//入栈
$stack->push('data3');//入栈
echo $stack->pop();//出栈
echo $stack->pop();//出栈
echo $stack->pop();//出栈
/**
*队列(先进先出)
*/
$queue = new SplQueue();
$queue->enqueue('data4');//入队列
$queue->enqueue('data5');//入队列
$queue->enqueue('data6');//入队列
echo $queue->dequeue();//出队列
echo $queue->dequeue();//出队列
echo $queue->dequeue();//出队列
echo $queue->dequeue();//出队列
/**
* 堆
*/
$heap = new SplMinHeap();
$heap->insert('data8');//入堆
$heap->insert('data9');//入堆
$heap->insert('data10');//入堆
echo $heap->extract();//从堆中提取数据
echo $heap->extract();//从堆中提取数据
echo $heap->extract();//从堆中提取数据
/**
* 固定数组(不论使不使用,都会分配相应的内存空间)
*/
$array = new SplFixedArray(15);
$array['0'] = 54;
$array['6'] = 69;
$array['10'] = 32;
var_dump($array);
二、PHP链式操作的实现(原理)
1、入口文件 index.php
<?php
/**
* 框架入口文件
*/
define('BASEDIR',__DIR__);//项目根目录
include BASEDIR.'/Extend/Loader.php';//引入项目自动加载类文件
spl_autoload_register('\\Extend\\Loader::autoload');//执行自动加载函数,完成类的自动加载
$db = new \Extend\Database();
$db->where('uid < 100000')->->order('uid desc')->limit(100);
2、自动加载类 Loader.php
<?php
namespace Extend;
/**
* 实现框架的自动加载
*/
class Loader
{
/**
* 实现文件的自动载入
*/
static function autoload($class)
{
require BASEDIR.'/'.str_replace('\\','/',$class).'.php';
}
}
3、数据库类Database.php
注:只是原理,并没有对方法进行具体的封装,具体的封装还是看个人喜好去定链式查询的风格。
<?php
namespace Extend;
class Database
{
/**
* 指定查询条件
* @param $where
*/
function where($where)
{
return $this;
}
/**
* 指定排序条件
*/
function order($order)
{
return $this;
}
/**
* 指定查询的限制条数
* @param $limit
*/
function limit($limit)
{
return $this;
}
}
其实就是对传过来的条件进行重新的底层封装,然后再把当前对象返回,使得可以不断的链式查询。
三、PHP魔术方法的使用
在php设计模式中,会涉及到很多魔术方法的使用,这里也对经常会用到的魔术方法进行简单总结。
1、框架入口文件 index.php
<?php
/**
* 框架入口文件
*/
define('BASEDIR',__DIR__);//项目根目录
include BASEDIR.'/Extend/Loader.php';//引入项目自动加载类文件
spl_autoload_register('\\Extend\\Loader::autoload');//执行自动加载函数,完成类的自动加载
/**
* 魔术方法的使用
*/
# 实例化Object类
$obj = new \Extend\Object();//当前文件不存在这个类,就会自动执行自动加载函数去包含相应的类文件(即 Extend/Object.php)
# __set 和 __get 对不存在的属性进行接管
$obj->title = 'xiaobudiu'; //当对一个不存在的类属性赋值时,会自动调用类中定义的__set()
echo $obj->title; //当调用一个不存在的类属性时,会自动调用类中定义的__get()
# __call 和 __callStatic 对不存在或者权限不够的类方法进行接管
$obj->getUserInfo('1000068'); //当调用一个不存在的类方法时,会调用__call(),并自动将当前方法名和参数传到__call方法中
\Extend\Object::getOpenId('1000068'); //当调用一个不存在的类静态方法时,会调用__callStatic(),并自动将当前方法名和参数传递到__callStatic方法中
# echo或print对象时,由__toString 接管
echo $obj; //当echo或print一个对象时,会自动调用类中定义的__toString方法
# 在php中,如果我们把一个对象当成函数用,则由__invoke()接管
$obj('xiaobudiu');//当我们将一个对象当成函数用的时候,会自动调用当前类中定义的__invoke()方法
2、 Extend/Object.php
<?php
namespace Extend;
/**
* 要求类名必须和文件名保持一致,即类名是Object,则所在文件名为Object.php
* Class Object
* @package Extend
*/
class Object
{
protected $array = array();
/**
* 在代码要给未定义的属性赋值时调用,或在类外部修改被private修饰的类属性时被调用
*/
function __set($name, $value)
{
echo "this is __set func";
}
/**
* 当在类外部访问被private或proteced修饰的属性或访问一个类中原本不存在的属性时被调用
* @param $name
*/
function __get($name)
{
echo "this is __get func";
}
/**
* 当试图调用不存在的方法或权限不足时会触发__call()
* @param $name 调用不存在的类方法时那个不存在的类方法的方法名
* @param $arguments 调用不存在的类方法时传递的参数
*/
function __call($name, $arguments)
{
var_dump($name,$arguments);
}
/**
* 当试图调用不存在的静态方法或权限不足时会触发__callStatic()
* @param $name 调用不存在的静态方法时那个不存在的方法的方法名
* @param $arguments 调用不存在的静态方法时传递的参数
*/
function __callStatic($name,$arguments)
{
var_dump($name,$arguments);
}
/**
* 当使用echo或print打印对象时会调用__toString()方法将对象转化为字符串
*/
function __toString()
{
echo "this is __toString func";
}
/**
* 对象本身不能直接当函数用,如果被当做函数用,会直接回调__invoke方法
* @param $param
*/
function __invoke($param)
{
echo $param."<br>this is __invoke func";
}
}
四、三种基础设计模式
1、工厂模式
通过传入参数的不同,来实例化不同的类。
index.php
<?php
/**
* 框架入口文件
*/
define('BASEDIR',__DIR__);//项目根目录
include BASEDIR.'/Extend/Loader.php';//引入项目自动加载类文件
spl_autoload_register('\\Extend\\Loader::autoload');//执行自动加载函数,完成类的自动加载
//构造实例化缓存类时传入的参数
$config = array(
'host' => '127.0.0.1',
'pass' => 'myRedis&&&'
);
//工厂模式创建cache对象
$cache = Extend\CacheFactory::getCacheObj('redis',$config);
var_dump($cache);
Extend/CacheFactory.php
<?php
namespace Extend;
class CacheFactory
{
const FILE = 1;
const MEMCACHE = 2;
const REDIS = 3;
static $instance;//定义静态属性,用于存储对象
/**
* 工厂类创建缓存对象
* @param $type 指定缓存类型
* @param array $options 传入缓存参数
* @return FileCache|Memcache|RedisCache
*/
static function getCacheObj($type, array $options)
{
switch ($type) {
case 'file':
case self::FILE:
self::$instance = new FileCache($options);
break;
case 'memcache':
case self::MEMCACHE:
self::$instance = new Memcache($options);
break;
case 'redis':
case self::REDIS:
self::$instance = new RedisCache($options);
break;
default:
self::$instance = new FileCache($options);
break;
}
return self::$instance;
}
}
2、单例模式
保证一个类只实例化一个类对象,进而减少系统开销和资源的浪费
index.php
<?php
/**
* 框架入口文件
*/
define('BASEDIR',__DIR__);//项目根目录
include BASEDIR.'/Extend/Loader.php';//引入项目自动加载类文件
spl_autoload_register('\\Extend\\Loader::autoload');//执行自动加载函数,完成类的自动加载
//单例模式创建对象
$obj = Extend\SingleObject::getInstance();
$obj2 = Extend\SingleObject::getInstance();
var_dump($obj,$obj2);//从结果可以看出,两个实例化的对象其实是一个对象
Extend/SingleObject.php
<?php
namespace Extend;
/**
* 单例模式创建唯一类对象
* Class SingleObject
* @package Extend
*/
class SingleObject
{
//私有的静态属性,用于存储类对象
private static $instance = null;
//私有的构造方法,保证不允许在类外 new
private function __construct(){}
//私有的克隆方法, 确保不允许通过在类外 clone 来创建新对象
private function __clone(){}
//公有的静态方法,用来实例化唯一当前类对象
public static function getInstance()
{
if(is_null(self::$instance)){
self::$instance = new self;
}
return self::$instance;
}
}
3、注册树模式
将我们用到的对象注册到注册树上,然后在之后要用到这个对象的时候,直接从注册树上取下来就好。(就和我们用全局变量一样方便)
Extend/RegisterTree,php
<?php
namespace Extend;
/**
* 注册树模式
* Class RegisterTree
* @package Extend
*/
class RegisterTree
{
static protected $objects;//静态类属性,用于储存注册到注册树上的对象
/**
* 将对象注册到注册树上
* @param $alias 对象的别名
* @param $object 对象
*/
static function setObject($alias,$object)
{
self::$objects[$alias] = $object;
}
/**
* 从注册树上取出给定别名相应的对象
* @param $alias 将对象插入到注册树上时写的别名
* @return mixed 对象
*/
static protected function getObject($alias)
{
return self::$objects[$alias];
}
/**
* 将对象从注册树上删除
* @param $alias 将对象插入到注册树上时写的别名
*/
public function unsetObject($alias)
{
unset(self::$objects[$alias]);
}
}
关于注册树模式,这里推荐一篇文章 ,可以方便理解。 https://www.cnblogs.com/DeanChopper/p/4767181.html
五、其他常见的8种PHP设计模式
1、适配器模式
2、策略模式
3、数据对象映射模式
4、观察者模式
5、原型模式
6、装饰器模式
7、迭代器模式
8、代理模式
#代码待补