PHP的新面Kong

PHP是作为一个开放源代码项目进行维护和开发的,有成百上千(可能成千上万)的贡献者积极致力于发展该语言,以满足现代Web开发的需求。 PHP继续合并新的编程思想,并从其他编程语言中借鉴了思想,但仍保持了较高的向后兼容性。 这些特性使PHP成为当前的佼佼者:该语言有助于运行82%的Web,并为某些最大的网站(如Facebook)提供动力。 PHP是诸如WordPress,Drupal,Magento和Joomla之类的内容管理系统(CMS)框架背后的核心技术! (它们共同为大约30%的网络供电)。

如果您很长一段时间(甚至是最近几年)都没有看过PHP,那么您可能不会意识到它已经成为的语言。 本文是由四个部分组成的系列文章的第一篇,向您介绍最新版本中添加的最新功能,例如PHP 5.3、5.4和5.5。

当然,PHP并不是凭空改变的,而新的语言功能只是PHP整体发展的一部分。 PHP程序员组装其开发服务器,管理其第三方库以及解决Web安全性的方式也在发生变化。 本系列的后续文章将探讨不断发展PHP生态系统的那些方面。

我认为没有人会偷东西; 我们所有人都借钱。

BB王

命名空间

命名空间是一种编程功能,旨在允许不同库中的类(和函数)具有完全相同的名称。 随着PHP作为一种语言的发展以及代码库的重用变得越来越普遍,名称冲突开始成为一个主要问题。 通过将每个库分割成自己的名称空间,您可以(没有不好的后果)安装和使用第三方库,该库包含名称与您自己的名称相匹配的任何类。

在内置对名称空间的支持之前,库通过使用一致的短语(例如在Zend Framework中使用Zend_在其所有类前面添加前缀来解决此问题。 您可能会得到诸如Zend_Db_Table类的深奥的类名,并且需要在编码时重复键入此类前缀。 当将(非常需要的) DateTime类添加到5.2版PHP核心中时,问题浮出水面。 突然,许多开源库开始崩溃,因为它们创建了自己的名为DateTime的类来填补空白。

命名空间是通过namespace关键字创建的,并用反斜杠( \ )分隔。 清单1显示了一个简单的示例。

清单1.简单的名称空间用法
<?php
namespace zebra;

class DateTime
{
   public function __construct() {
      echo "Today!";
   }
}

function stripes() {
   echo "-=-=-=-=-=-=-=-";
}

在清单1中,我定义了自己的命名空间zebra ,然后在其中定义了一个类和一个函数。 在这种情况下,重新定义DateTime类不会引起任何问题或错误,因为我在命名空间中创建了自己的DateTime版本。 现在,可以通过使用全名(以\作为分隔符)来引用名称空间,如清单2所示。

清单2.使用自定义名称空间
<?php
include 'listing1.php';

// Use the stripes function I declared in my namespace:
zebra\stripes();

// Use my own DateTime class:
$dt = new zebra\DateTime();

// Now use the 'root' level Datetime class:
$real = new \DateTime('tomorrow noon');
echo $real->format(\DateTime::ATOM);

在清单2的第2行中,我include了以namespace指令开头的文件(listing1.php)。 然后,我可以通过以zebra\名称空间开头来引用我的类和函数。 我还可以通过在反斜杠前面添加前缀来表示全局名称空间,从而仍然使用全局级别的类,例如原始的DateTime

清单2中的技术很方便,但是有一种方法可以使代码看起来更简单:new use关键字。 该关键字表明您希望直接从该名称空间中访问特定的类,如清单3所示。

清单3. use名称空间
<?php
include 'listing1.php';
use zebra\DateTime;

// Use our own DateTime class:
$dt = new DateTime();

您还可以use关键字create aliases,以便您可以将所使用的类的任何类重命名为其他名称。清单4显示了如何创建别名。

清单4.创建一个别名
<?php
include 'listing1.php';
use zebra\DateTime as ZDT;

// Use our own DateTime class:
$dt = new ZDT();

使用名称空间,您可以做的比我在这里涉及的更多,包括创建子名称空间。 在官方文档中进行更深入的研究。

特质

传统上,面向对象的编程深深地基于彼此继承的类和对象的概念。 您从一个抽象的概念开始,并随着对子项的更具体了解而不断地与子类成为子类。 如果您的对象之间需要一致的API,则可以使用接口的概念。 在这里,您可以定义对象需要实现的方法。 但是,如果您不仅要声明必须存在哪些方法,还想同时提供它们的实现,该怎么办? 输入特征 。

PHP 5.4中添加的特性是水平代码重用的一种功能(而继承是垂直代码重用)。 在其他语言中,此功能有时称为mixin 。 无论哪种情况,该概念都很简单。 特征或混合是一次开发任意数量方法的一种方法。 也许您有一些通用的方法来过滤和处理某些对象应该共享的数据或业务逻辑。 您可以将它们保存为特征,然后在所需的任何类中重复使用它们。

清单5显示了一个简化的示例,该示例提供了一种日志记录方法,任何类都可以将其用作记录事件的一致方法。

清单5.声明和使用特征
<?php
trait logging {
   private static $LOG_ERROR = 100;
   private static $LOG_WARNING = 50;
   private static $LOG_NOTICE = 10;

   protected $log_location = 'output.log';

   protected function log($level, $msg) {

      $output = [];
      $output[] = "Class: ".__CLASS__.' | ';
      $output[] = "Level: {$level} | ";
      $output = array_merge($output, (array)$msg, ["\n"]);
      file_put_contents($this->log_location, $output, FILE_APPEND);
   }
}

class User {
   use logging;

   public function __construct() {
      $this->log(self::$LOG_NOTICE, 'New User Created');
   }
}

class DB {
   use logging;

   private $db = 'localhost:8080';

   public function connect() {
      // ... attempt to connect and fail:
      $this->log(self::$LOG_ERROR, ['Connection Failed-', $this->db]);
   }
}

在清单5中, trait logging的声明从第2行开始。请注意,该特征包含一个方法以及许多属性(包括静态属性)。 从表面上看,该声明看起来类似于类的声明,但是它使用trait关键字代替。

在清单5中,将特征带入UserDB类中,我再次使用use关键字。 use logging; 它们的类定义顶部的指令本质上会将所有属性和方法从logging特征中拉到本地这些类中。 现在,每个类都可以直接访问所有日志记录工具,而无需分别实现它们。 特质内部使用的魔术__CLASS__变量在__CLASS__成为使用特质的类的名称,从而使日志消息可以立即针对该类进行定制。

闭包(又名匿名函数)

使用旧版本PHP,您可以通过create_function编程地创建函数,并且它们允许传递函数的解决方法:以字符串形式发送函数名称,然后通过call_user_funccall_user_func_array调用该函数。 该选项缺乏真正的匿名函数的优雅,后者可以在方法和类之间传递或保存在具有适当作用域的变量中。

匿名函数在JavaScript中占统治地位,并且还不知道JavaScriptPHP程序员很少见。 因此,PHP逐渐发展为包含匿名函数是很自然的。 从PHP 5.3开始,您可以在任何可以使用变量(存储或传递)的地方使用常规的函数声明语法。

作为示例,清单6显示了使用内置排序功能来指定您自己的自定义排序功能的旧方法。

清单6.传递函数的旧方法
<?php
$insurees = [
   'u4937' => ['name' => 'Thomas Smythe', 'age' => 33],
   'u1282' => ['name' => 'Gayle Runecor', 'age' => 25],
   'u9275' => ['name' => 'Sara Pinnicle', 'age' => 57],
   'u2078' => ['name' => 'Delilah Shock', 'age' => 41],
];

function insuree_age_sort($a, $b) {
   if ($a['age'] == $b['age']) { return 0; }
   return ($a['age'] > $b['age']) ? -1 : 1;
}

uasort($insurees, 'insuree_age_sort');

清单6有点笨拙,因为需要在相同范围内定义一个函数然后再使用它-即使您永远不会再使用它。 使用闭包,您现在可以一步一步直接创建和使用该函数。 清单7显示了这种更为优雅的解决方案的示例。

清单7.使用匿名函数进行排序
<?php
uasort($insurees, function ($a, $b) {
   if ($a['age'] == $b['age']) { return 0; }
   return ($a['age'] > $b['age']) ? -1 : 1;
});

尽管如此,任何人都很难说这个次要用例是此功能的唯一理由。 但是要意识到这里发生了什么。 我即时创建的传递给uasort()函数是一类可变公民。 您可以将函数存储在变量中,并将它们传递给不同的函数和类。 当您查看随闭包一起添加到PHP的作用域功能时,闭包的真正力量显而易见。

使用重载的use关键字,您可以在当前作用域中指定该函数应有权访问的某些变量。 这样,您可以处理相当复杂的细节,而不必每次从其可变形式访问函数时都将其不断地传递给函数。 清单8和清单9中的(有些人为设计的)示例演示了这种功能。

清单8在回调中使用继承的变量作用域。

清单8.在回调中使用继承的变量范围
<?php
// Find only people over a certain age
$minage = 40;

$over = array_filter($insurees, function($a) use ($minage) {
   return ($a['age'] >= $minage);
});

清单9使用带有多个变量和直接调用的闭包。

清单9.具有多个变量和直接调用的闭包
<?php
$urls = [
   'training' => '/training',
   'magazine' => '/magazine',
   't-shirt' => '/swag/tshirts',
];

$current = $_SERVER['REQUEST_URI']; // May come from somewhere else

// Helper for links, ignoring links if we are on that page:
$link = function($name) use ($urls, $current) {
   if ($current == $urls[$name]) {
      return $name;
   } else {
      return "<a href=\"{$urls[$name]}\">{$name}</a>";
   }
};
?>
<p>Welcome to our website!  Make sure to check out
   our <?= $link('training') ?> offerings, see the
   latest issue of our <?= $link('magazine'); ?>,
   and don't forget to check out our latest
   <?= $link('t-shirt') ?> designs as well.</p>

如果您习惯使用JavaScript使用闭包,那么您已经熟悉它们的功能,灵活性以及有时很危险的性质。

发电机

当PHP 5.0发布时,它伴随着标准PHP库(SPL)的诞生。 SPL旨在作为解决某些计算机科学问题的标准化方法的集合,例如创建队列和链接列表(并提供诸如类文件自动加载器之类的可扩展功能)。

SPL中包含的一项功能称为迭代器 。 Iterator是一个接口(带有一组预建的类),您可以使用它通过foreach关键字使任何类都能够像数组一样循环foreach 。 这项惊人的发明使所有“事物清单”以统一的方式遍历成为可能。 但是Iterator是一个相当复杂的系统,需要您创建一个类并定义四个方法。 有时,您需要标准的foreach循环功能,但不需要类结构的开销来实现它。

使用较新的生成器功能,您可以(通过yield关键字)创建一个函数,该函数生成值列表并一次提供给它们。 本质上,不需要返回一个值,而是产生所需数量的值。 然后,您可以在函数上使用foreach循环来检索该函数要返回的所有值。

清单10显示了一个简单的函数示例,该函数将值范围划分为相等的部分并返回它们。

清单10.分为几部分的生成器
<?php
function parts($start, $end, $parts) {
   // Find what our actual length is:
   $length = $end - $start;
   do {
      $start += $length / $parts;
      yield $start;
   } while ($start < $end);
}

// Break 5 feet into 3 parts:
foreach (parts(0, 5, 3) as $l) {
   echo $l, " ";
}
echo "\n";

// Break the range 10-90 into 2 parts:

foreach (parts(10, 90, 12) as $l) {
   echo $l, " ";
}
echo "\n";

魔术发生在第7行,其中使用了yield关键字。 此时,基本上,该函数停止执行,并返回产生的值。 在每次后续调用该函数时,都会从中断处开始执行,直到发生下一次屈服或该函数结束为止。

这个示例显然是人为设计的,但是您可以想象在数据库查询的结果上或在解析XML文件返回的结果上使用此技术。 您甚至可以产生键和值,以使用语法yield $key => $value来直接模拟数组,如清单11中基于XML的示例所示。

清单11.使用生成器来处理XML
<?php
$xml = <<<EOXML
<?xml version="1.0" encoding="UTF-8" ?>
<products>
  <books>
    <book isbn="978-1940111001">Mastering the SPL Library</book>
    <book isbn="978-1940111056">Functional Programming in PHP</book>
    <book isbn="978-0981034508">Guide to Date and Time Programming</book>
    <book isbn="0973589825">Guide to PHP Design Patterns</book>
  </books>
</products>
EOXML;

$books = function () use ($xml) {
   $products = simplexml_load_string($xml);
   foreach ($products->books->book as $book) {
      yield $book['isbn'] => (string)$book;
   }
};

foreach ($books() as $isbn => $title) {
   echo "{$isbn}: {$title}\n";
}

还有更多...

PHP中的所有新功能太多了,无法在此处详细介绍。 表1是过去几年中其他一些值得注意的补充的快速列表。

表1.其他新PHP语言功能
特征 描述
后期静态绑定 5.3 父类调用由其子代/继承者之一定义的静态方法或属性的能力(与通常的操作相反)。 例如,允许泛型功能存在于从其扩展子级获取配置的父类中。
Nowdoc语法 5.3 将字符串指定为文本块的能力,其中没有解释变量。
捷径三元(?:) 5.3 可以省略标准三元运算符的中间值,从而使true条件默认返回到原始比较值的能力。 示例: $result = $value ?: 0;
跳转标签( goto 5.3 尽管有些人认为不随语言而发展,但添加了goto运算符,以便可以在PHP内部更轻松地完成某些编码练习,例如创建状态机。
魔术方法
__callStatic
__invoke
__debugInfo

5.3
5.3
5.6
从PHP 5.0开始,这三种新的魔术方法已添加到其他可用的魔术方法中,以完善您在设计类时可以使用的选项的强大功能。 现在,您可以拥有重载和未定义的静态方法,可以像调用对象一样调用对象,并可以在调试对象时控制输出内容。
始终在线的短码回显( <?= 5.4 以前,如果您在PHP中禁用了简码,则所有版本均已关闭。 从PHP 5.4开始,模板中常用的<?=短代码始终可用。
短数组语法 5.4 您现在可以使用方括号,而不是将数组声明为array(1,2,3) ,例如: [1,2,3]
内置网络服务器 5.4 PHP运行时现在带有一个内置的Web服务器,无需配置Apache或IIS,就可以更轻松地进行简单的代码测试和开发。

结论

现代PHP开发看起来不像过去的旧程序代码。 而且PHP继续保持较高的发展速度。 PHP 7已经面世,计划于2015年下半年发布。

本系列的下一部分将探讨不断变化的密码保护需求领域,以及PHP为帮助Web开发人员处理这一复杂要求所做的工作。


翻译自: https://www.ibm.com/developerworks/web/library/wa-php-renewed_1/index.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值