来总结一下新的知识点,这是第一篇
php新语言特性
1. namespace 命名空间,使用命名空间use
<?php
//定义命名空间
namespace Oreilly\senyzy
<?php
//使用命名空间
use Oreilly\senyzy as sen
//as加别名,对于过长的地址可以用别名
$test = new sen();
2.interface接口,接口就是两个对象的契约,目的不是让一个对象依赖另一个对象,而是依赖另一个对象的能力,我们不管第三方代码是如何实现接口,只关心第三方代码是否实现了指定的接口。可以参考以下代码
<?php
//定义接口
interface Documenttabel
{
public function getId();
public function getContent();
}
/**
* 接口继承 Html文档
*/
class HtmlDocument implements Documenttabel
{
protected $url;
public function __construct($url)
{
$this->url = $url;
}
public function getId()
{
return $this->url;
}
public function getContent()
{
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$this->url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,3);
curl_setopt($ch,CURLOPT_FOLLOWLOCATION,1);
curl_setopt($ch,CURLOPT_MAXREDIRS,3);
curl_exec($ch);
return $html;
}
}
/**
* 接口继承 文件流
*/
class StreamDocument implements Documenttabel
{
protected $resource;
protected $buffer;
public function __construct($resource,$buffer = 4096)
{
$this->resource = $resource;
$this->buffer = $buffer;
}
public function getId()
{
return 'resource-'.(int)$this->resource;
}
public function getContent()
{
$streamContent = '';
rewind($this->resource);
while(feof($this->resource) === false){
$streamContent .= fread($this->resource,$this->buffer);
}
return $streamContent;
}
}
/**
* 接口继承 命令行
*/
class CommandOutputDocument implements Documenttabel
{
protected $command;
public function __construct($command)
{
$this->command = $command;
}
public function getId()
{
return $this->command;
}
public function getContent()
{
return shell_exec($this->command);
}
}
/**
* 使用
*/
class DocumentStore
{
protected $data = [];
public function addDocument(Documenttabel,$document)
{
$key = $document->getId();
$value = $document->getContent();
$this->data[$key] = $value;
}
public function getDocuments()
{
return $this->data;
}
}
//实例化接口
$documentStore = new DocumentStore();
//添加Html文档
$htmlDoc = new HtmlDocument('https://php.net');
$documentStore->addDocument($htmlDoc);
//添加文档流
$streamDoc = new StreamDocument(fopen('strem.txt','rb'));
$documentStore->addDocument($streamDoc);
//添加终端命令行
$cmdDoc = new CommandOutputDocument('cat /etc/hosts');
$documnetStore->addDocument($cmdDoc);
//返回操作数据
print_r($documentStore->getDocuments);
?>
3.trait性状(PHP5.4引入),即像类又像接口,不过都不是,为什么使用性状?可以通过性状让两个不同的类(class)使用相同的功能(常量、属性、方法)见下代码
<?php
/**
* 性状 定义
*/
trait Geocodable{
/**
* @var string
*/
protected $address;
/**
* @var \Geocoder\Geocoder
*/
protected $geocoder;
/**
* @var \Geocoder\Result\Geocoded
*/
protected $geocoderResult;
public function setGeocoder(\Geocoder\GeocoderInterface $geocoder)
{
$this->geocoder = $geocoder;
}
public function setAddress($address)
{
$this->address = $address;
}
public function getLatitude()
{
if(isset($this->geocoderResult) === false)
{
$this->geocodeAddress();
}
return $this->geocoderResult->getLatitude();
}
public function getLongitude()
{
if(isset($this->geocoderResult) === false)
{
$this->geocodeAddress();
}
return $this->geocoderResult->getLatitude();
}
protected function geocodeAddress()
{
$this->geocoderResult = $this->geocoder->geocode($this->address);
return true;
}
}
//使用性状
class RetailStore
{
use Geocodable;
}
$geocoderAdapter = new \Geocoder\HttpAdapter\CurlHttpAdapter();
$geocoderProvider = new \Geocoder\Provider\GoogleMapsProvider($geocoderAdapter);
$geocoder = new \Geocoder\Geocoder($geocoderProvider);
$store = new RetailStore();
$store->setAddress('420 9th Avenue,New York, NY 10001 USA');
$latitude = $store->getLatitude();
$longitude = $store->getLongitude();
echo $latitude, ':' ,$longitude;
4.yield生成器(PHP5.5引入),生成器就是简单的迭代器,为什么使用生成器?减轻内存压力,试想一下一个数据需要循环1百万次,这一百万次的数据通常会存在一个变量里,需要先计算集合在展示,会让内存有非常多的开销,生产器就解决了类似的问题
<?php
/**
* 生成器 php>=5.5
*/
function myGenerator(){
yield 'value1';
yield 'value2';
yield 'value3';
}
//使用生成器生成数列,节省内存开销
function makeRange($length)
{
for($i = 0;$i < $length;$i++)
{
yield $i;
}
}
foreach(makeRange(1000000) as $i)
{
echo $i , PHP_EOL;
}
//使用生成器处理CVS文件(大型文件)节省内存开销
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.cvs') as $row) {
print_r($row);
}
?>
5.PHP 闭包(PHP5.3引入) 闭包是指在创建时封装周围的函数,用过js闭包的应该都不陌生,使用闭包会调用__invoke()魔术方法
<?php
/**
* php 闭包 匿名函数 php>=5.3
*/
$closure = function ($name){
return sprintf('Hello %s',$name);
};
echo $closure('Josh');
$numbersPlusOne = array_map(function($number){
return $number+1;
},[1,2,3]);
print_r($numbersPlusOne);
//附加状态(跟js有区别,use关键字)
function enclosePerson($name)
{
return function ($doCommand) use ($name) {
return sprintf('%s ,%s',$name,$doCommand);
};
};
//封装字符串Clay
$Clay = enclosePerson('Clay');
//传入参数调用闭包
echo $Clay('get me sweet tea!');
//bindTo关键字的应用
class App
{
protected $routes = array();
protected $responseStatus = '200 OK';
protected $responseContentType = 'text/html';
protected $responseBody = 'Hello world';
public function addRoute($routePath,$routeCallback)
{
$this->routes[$routePath] = $routeCallback->bindTo($this,__CLASS__);
}
public function dispatch($currentPath)
{
foreach ($this->routes as $routePath => $Callback) {
if($routePath == $currentPath)
{
$callback();
}
}
header('HTTP/1.1'.$this->responseStatus);
header('Content-type:'.$this->responseContentType);
header('Content-length:'.mb_strlen($this->responseBody));
echo $this->responseBody;
}
}
$app = new App();
$app->addRoute('/users/josh',function()
{
$this->responseContentType = 'application/json;charset=utf-8';
$this->responseBody = '{"name":"josh"}';
});
$app->dispatch('/users/josh');
?>
6.Zend Opcache(PHP5.5引入),php内置字码缓存功能,php是解释型语言,php会执行脚本将其变成一系列的zend(zend engine)操作码,如果每次都去解析会消耗很多的资源,若开启zend opcache会大大提升性能
/zend opcache Linux系统下,编译PHP时别忘加下面代码
./configure --enable-opcache
//编译好在php.ini中指定位置
zend_extension = /path/to/opcache.so
//在php.ini中配置Zend Opcache
opcache.validate_timestamps = 1 //生产环境中设置为0
opcache.revalidate = 0
opcache.memory_consumption = 64
opcache.interned_strings_buffer = 16
opcache.fast_shutdown = 1
7.PHP内置服务器(了解) 性能虽然比不上Apache,NGINX等服务器,线上也不能使用但还是需要了解一下
//启动服务器 进入项目根目录输入如下命令
php -S localhost:4000 //4000端口启动