Home  >  Article  >  Backend Development  >  Do you really understand current PHP?

Do you really understand current PHP?

PHPz
PHPzOriginal
2017-04-04 15:59:171109browse

Some time ago, the company's project was upgraded from PHP5.3 to PHP7. Now the project starts to use some of PHP7 New syntax and features. Looking back at PHP versions 5.4, 5.5, and 5.6, there is a sense of lack of knowledge. Therefore, I decided to read "Modern PHP" to supplement some concepts.

Reading this bookDo you really understand current PHP?
1. Features

1.

Namespace

Namespaces are used more often, not Written in detail, recording several noteworthy practices and details Don’t do this, it is easy to make people confused

<?php
use Symfony\Component\HttpFoundation\Request,
    Symfony\Component\HttpFoundation\Response,
    Symfony\Component\HttpFoundation\Cookie;

It is recommended to write one per line. use statement:

<?php
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Cookie;
Use multiple namespaces in one file

You can do this, but this violates

"One file defines a class"

Good practice.

<?php
namespace Foo {
  //code
}

namespace Bar {
  //code 
}
Global namespace
If you want to use PHP’s native Exception

class, you need to add the \ symbol in front of the class name

<?php
namespace My\App;

class Foo
{
  public function doSomething()
  {
    $exception = new \Exception();
  }
}
#. ##If there is no \ symbol before Exception, the Exception class will be found in the My\App namespace 2. Use
interface

Code written using interface is updated. It is flexible and can be delegated to others to implement the details. Users only need to care about the interface, not the implementation. It can decouple the code well and facilitate expansion.

3 . Traits

I didn’t understand traits before learning laravelframework

. This is a new concept introduced in PHP5.4.0, which is like both a class and an interface. No.

Traits are partial implementations of classes that can be mixed into one or more existing PHP classes.

Why use traits? For example, there are two classes, Car and Phone, both of which require GPS functionality. In order to solve this problem, the first reaction is to create a parent class and let Car and Phone

inherit it.

It. But because it is obvious that this ancestor does not belong to the respective inheritance hierarchy.

The second reaction is to create a GPS interface, define the GPS functional interface, and then make the two classes Car and Phone. Both implement this interface. This can achieve functionality while maintaining the natural inheritance hierarchy. However, this requires duplicate GPS functions, which does not comply with the DRY (dont repeat yourself) principle ##. #The third reaction is to create a trait that implements the GPS function, and then mix this trait into the Car and Phone classes. It can realize functions, does not affect the inheritance structure, does not repeat implementation, and is perfect.
Creating and using traits

Creating traits

<?php
trait MyTrait{
  //实现
}

Using traits

<?php
class MyClass
{
  use MyTrait;
  // 类的实现
}

4.

Generator
PHP generator (generator) is a new feature introduced in PHP5.5.0, which many PHP developers do not understand. The generator is a simple iterator, but the generator is not required to implement the

Iterator interface

. The generator computes and produces the values ​​to be iterated over as needed. Without

querying

, the generator never knows what the next value to iterate over is, and there is no way to go back or fast forward in the generator. Specifically, look at the following two examples:

Simple generator

<?php
function makeRange($length) {
  for ($i = 0; $i < $length; $i++) {
    yield $i;
  }
}

foreach (makeRange(1000000) as $i) {
  echo $i, PHP_EOL;
}
Specific scenario: Use the generator to process CSV files

<?php
function getRows($file) {
  $handle = fopen($file, &#39;rb&#39;);
  if ($handle === false) {
    throw new Exception();
  }
  while (feof($handle) === false) {
    yield fgetcsv($handle);
  }
}

foreach (getRows(&#39;data.csv&#39;) as $row) {
  print_r($row);
}

To deal with this scenario, the customary method is to first read all the contents of the file and put them into the

array

, and then do processing and so on. The problem with this kind of processing is: When the file is very large, it takes up a lot of memory resources to read it at one time. The generator is most suitable for this scenario because it takes up very little system memory.

5. ClosureTheoretically, closure and anonymous function are different concepts. However, PHP treats it as the same concept. Simple closure

<?php
$closure = function ($name) {
  return sprintf(&#39;Hello %s&#39;, $name);
}

echo $closure("Beck");
// 输出 --> “Hello Beck”
Note: The reason why we can call $closure

variable is because the value of this variable is a closure, and closureObject
implements invoke()magic method. As long as there is () after

variable name

, PHP will find and call the invoke() method.

附加状态
使用use关键字可以把多个参数传入闭包,此时要像PHP函数或方法的参数一样,使用逗号分隔多个参数。

<?php
function enclosePerson($name) {
  return function ($doCommand) use ($name) {
    return sprintf(&#39;%s, %s&#39;, $name, $doCommand);
  };
}

// 把字符串“Clay”封装在闭包中
$clay = enclosePerson(&#39;Clay&#39;);

// 传入参数,调用闭包
echo $clay(&#39;get me sweet tea!&#39;);
// 输出 --> "Clay, get me sweet tea!"

使用bindTo()方法附加闭包的状态
PHP框架经常使用bindTo()方法把路由URL映射到匿名回调函数上,框架会把匿名函数绑定到应用对象上,这么做可以在这个匿名函数中使用$this关键字引用重要的应用对象。例子如下:

<?php
class App
{
  protected $routes = array();
  protected $responseStatus = &#39;200 OK&#39;;
  protected $responseContentType = &#39;text/html&#39;;
  protected $responseBody = &#39;Hello world&#39;;

  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;
  }
}

第11行是重点所在,把路由回调绑定到了当前的App实例上。这么做能在回调函数中处理App实例的状态:

<?php
$app = new App();
$app->addRoute('/users/josh', function () {
  $this->responseContentType = 'application/json;charset=utf8';
  $this->responseBody = '{"name": "Josh"}';
});
$app->dispatch('/users/josh');

6. Zend OPcache

字节码缓存不是PHP的新特性,很多独立的扩展可以实现缓存。从PHP5.5.0开始,PHP内置了字节码缓存功能,名为Zend OPcache。

字节码缓存是什么
PHP是解释性语言,PHP解释器执行PHP脚本时会解析PHP脚本代码,把PHP代码编译成一系列Zend操作码,然后执行字节码。每次请求PHP文件都是这样,会消耗很多资源。字节码缓存能存储预先编译好的PHP字节码。这意味着,请求PHP脚本时,PHP解释器不用每次都读取、解析和编译PHP代码。这样能极大地提升应用的性能。

7. 内置的HTTP服务器

从PHP5.4.0起,PHP内置了Web服务器,这对众多使用Apache或nginx的php开发者来说,可能是个隐藏功能。不过,这个内置的服务器功能并不完善,不应该在生产环境中使用,但对本地开发来说是个便利的工具,可以用于快速预览一些框架和应用。

启动服务器

php -S localhost:4000

配置服务器

php -S localhost:8000 -c app/config/php.ini

路由器脚本
与Apache和nginx不同,它不支持.htaccess文件。因此,这个服务器很难使用多数流行的PHP框架中常见的前端控制器。PHP内置的服务器使用路由器脚本弥补了这个遗漏的功能。处理每个HTTP请求前,会先经过这个路由器脚本,如果结果为false,返回当前HTTP请求中引用的静态资源URI。

php -S localhost:8000 route.php

是否为内置的服务器

<?php
if (php_sapi_name() === 'cli-server') {
  // php 内置的web服务器
}

       

The above is the detailed content of Do you really understand current PHP?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn