ホームページ  >  記事  >  バックエンド開発  >  あなたは今のPHPを本当に理解していますか?

あなたは今のPHPを本当に理解していますか?

PHPz
PHPzオリジナル
2017-04-04 15:59:171143ブラウズ

少し前に、会社のプロジェクトが PHP5.3 から PHP7 にアップグレードされました。現在、プロジェクトは PHP7 のいくつかの新しい構文と機能を使用し始めています。 . PHP バージョン 5.4、5.5、5.6 を振り返ると少し知識が不足しているように感じられるため、その概念を補うために『モダン PHP』を読むことにしました

あなたは今のPHPを本当に理解していますか?

1。特徴

1.

名前空間

名前空間はよく使われるので、いくつかの注目すべき実践と詳細を記録しますこれは行わないでください。人々を混乱させるのは簡単です。

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

use ステートメントを 1 行記述することを提案します。

<?php
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Cookie;
1 つのファイルで複数の名前空間を使用することもできますが、これは 1 つのファイルで 1 つの名前空間を定義するという良い習慣に反します。 class"
<?php
namespace Foo {
  //code
}

namespace Bar {
  //code 
}

グローバル名前空間

。PHPのネイティブExceptionクラスを使用したい場合は、クラス名の前にシンボルを追加する必要があります

<?php
namespace My\App;

class Foo
{
  public function doSomething()
  {
    $exception = new \Exception();
  }
}
Exceptionの前にシンボルを追加しない場合、Exceptionクラス

インターフェースを使用すると、記述されたコードはより柔軟になり、ユーザーはコードの実装ではなくインターフェースのみを考慮するだけで済みます。

3 . TraitsLaravel
フレームワークを学ぶ前は、これはクラスのような新しい概念です。部分的な実装は、Ruby の結合モジュールまたはミックスインと同様に、1 つまたは複数の既存の PHP クラスに混合できます。

特性を使用する理由

たとえば、Car とPhone: これらはすべて GPS 機能を必要とします。この問題を解決するには、最初に親クラスを作成し、それから Car と Phone を継承させます。ただし、この祖先がそれぞれの継承階層に属していないことは明らかです。 を作成し、GPS の機能インターフェイスを定義し、Car クラスと Phone クラスの両方にこのインターフェイスを実装させることができますが、これにより両方のクラスでその機能を実現することができなくなります。繰り返しの GPS 機能を実装する場合、これは DRY (繰り返しを行わない) 原則に準拠しません。

3 番目の反応は、GPS 機能を実装するトレイトを作成し、このトレイトを Car とミックスすることです。機能に影響を与えずに機能を実現するための電話クラス。

特性を作成して使用する

特性を作成する

<?php
trait MyTrait{
  //实现
}

4.PHPジェネレーター(ジェネレーター)は PHP5.5.0 で導入された新機能ですが、多くの PHP 開発者ジェネレーターは理解していません。ジェネレーターは単純なイテレーターですが、ジェネレーターは

Iterator インターフェース

を実装する必要はありません。ジェネレーターは、必要に応じて反復される値を計算して生成します。

query がないと、ジェネレーターは次に反復する値が何であるかを知ることができず、ジェネレーター内で戻ったり早送りしたりする方法はありません。具体的には、次の 2 つの例を見てください:
単純なジェネレーター

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

特定のシナリオ: ジェネレーターを使用して CSV ファイルを処理する

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

foreach (makeRange(1000000) as $i) {
  echo $i, PHP_EOL;
}

このシナリオを処理するには、通常の方法では、まず ファイルをすべて読み取ります。 コンテンツは
array

に入れられ、その後処理などが行われます。この種の処理の問題点は次のとおりです。

ファイルが非常に大きい場合、一度に読み取るのに多くのメモリ リソースが必要になります。ジェネレーターはシステム メモリをほとんど消費しないため、このシナリオに最適です

5. クロージャ

理論的には、クロージャと

匿名関数は異なる概念です。ただし、PHP ではこれを同じ概念として扱います。 単純なクロージャ

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

注: $closurevariableを呼び出すことができる理由は、この変数の値がクロージャであり、closure

オブジェクト

がinvoke()マジックメソッドを実装しているためです。

変数名

の後に () がある限り、PHP は invoke() メソッドを見つけて呼び出します。

附加状态
使用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服务器
}

       

以上があなたは今のPHPを本当に理解していますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。