命名空间:
命名空间很重要,因为代码放在沙盒中,可以和其他开发者编写的代码一起使用。这是现代PHP组件生态系统的基础。组件和框架的作者编写了大量的代码,供众多PHP开发者使用,这些作者不可能知道或者控制别人在使用自己的代码时还能使用了什么其他类、接口、函数或者常量。在你自己的私人项目中也会遇到这种问题,在为项目编写PHP组件或类时,要确保这些代码能和项目的第三方依赖在一起使用。如果不使用命名空间,名称会起冲突,导致PHP执行出错。
在命名空间中使用限定的类名:
<?php
namespace My\App;
class Foo
{
public function doSomething()
{
throw new \Exception();
}
}
我们要Exception类的名称前加上'\'前缀。这么做的目的是告诉PHP别在当前命名空间中查找Expection类,要在全局命名空间中查找。
PHP接口:
接口是两个PHP对象之间的契约,其目的不是让一个对象依赖另一个对象的身份,而是依赖另一个对象的能力。接口把我们的代码和依赖解耦了,而且允许我们的代码依赖任何实现了预期接口的第三方代码。
性状(trait):
性状是类的部分实现(即常量,属性和方法),可以混入一个或多个现有的PHP类中。
性状有两个作用:表明类可以做什么(像是接口);提供模块化实现(像是类)。
DRY原则:
Don't Repeat Yourself。不要在多个地方重复编写相同的代码。
生成器(generator):
生成器是简单的迭代器。与标准的PHP迭代器不同,PHP生成器不要求类实现Iterator接口,从而减轻了类的负担。生成器会根据需求计算并产出要迭代的值。这对应用的性能有重大影响。试想一下,加入标准PHP迭代器经常在内存中执行迭代操作,这要预先计算出数据集,性能地下;如果要使用特定的方式计算大量数据,对性能的影响更甚。此时,我们可以使用生成器,即时计算并产出后续值,不占宝贵的内存资源。
注意:PHP生成器不能满足所有迭代操作的需求,因为如果不查询,生成器永远不知道下一个要迭代的值是什么,在生成器中无法后退或快进。生成器还是一次性的,无法多次迭代用一个生成器。不过,如果需要,可以重建或克隆生成器。
<?php
function getRows($file) {
$handle = fopen($file, 'rb');
if ($handle === false) {
throw new Exception();
}
while (feof($handle) === false) {
yield fgetcsv($handle);
}
fclose($handle);
}
foreach (getRows('data.csv') as $row) {
print_r($row);
}
上述示例中一次只会为CSV文件中的一行分配内存,而不会把整个文件(或许有4G)都读取到内存中。而且上述代码还把迭代的实现方式封装到了一个简洁的包中,因此,如果想要快速修改获取数据的方式(例如获取CSV,XML或JSON), 无须改动应用中迭代数据的代码。生成器是功能多样性和简洁性之间的这种方案。生成器是只能向前的迭代器,这意味着不能使用生成器在数据集中执行后退,快进,或查找。只能让生成器计算并产生下一个值。
闭包:
闭包是指在创建时封装周围状态的函数。即便闭包所在的环境不存在了,闭包中封装的状态依然存在。
<?php
function enclosePerson($name) {
return function($doCommand) use ($name) {
return sprintf('%s, %s', $name, $doCommand);
} ;
}
$clay = enclosePerson('clay');
echo $clay('get me sweet tea!');
// 输出 ---> "clay, get me sweet tea!"
上述例子中,enclosePerson()有个$name参数,这个函数返回一个闭包对象,而且这个对象封装了$name参数。使用use关键字可以把多个参数传入闭包,此时要像PHP函数或方法的参数一样,使用逗号分隔多个参数。
bindTo()
bindTo方法为闭包增加了一些有趣的潜力。我们可以使用这个方法把Closure对象的内部状态绑定到其他的对象上。bindTo方法的第二个参数很重要,其作用是指定绑定闭包的那个对象所属的PHP类。因此,闭包可以访问绑定闭包的对象中受保护或者私有的成员变量。
<?php
class App
{
protected $routes = array();
protected $responseBody = 'Hello World';
public function addRoute($routePath, $routeCallback)
{
$this->routes[$routePath] = $routeCallback->bindTo($this, __CLASS__);
}
}
$app = new App();
$app->addRoute('/users/josh', function(){
$this->responseBody = "Okay";
});
上述例子我们把路由回调绑绑定到了routes array里面。之后可以通过foreach来调用存在routes array里面的回调函数
匿名函数:
匿名函数其实就是没有名称的函数,可以赋值给变量,还能像其他的PHP对象那样传递。
Example:
<?php
$numberPlusOne = array_map(function($number){
return $number + 1;
}, [1,2,3])
print_r($numberPlusOne);
?>
上述例子会输出[2,3,4]
网友评论