目录
前言
组件化开发
命名空间
命名冲突
解决办法
PSR 规范
namespace 操作符与__NAMESPACE__ 魔术常量
三种命名空间的导入
全局命名空间
多重导入与多个命名空间
导入常量、函数
文件包含
手动加载
自动加载
反射
后期静态绑定
trait
基本使用
重要性质
优先级
trait 函数冲突
重命名与访问控制
其他
总结
首页 php框架 Laravel 总结Laravel中常用的PHP语法有哪些

总结Laravel中常用的PHP语法有哪些

Sep 09, 2021 am 11:28 AM
laravel php

前言

Laravel框架因为其组件化的设计并恰当使用设计模式,使得框架本身简洁易扩展。区别于 ThinkPHP 那种整合式功能的框架(功能要么全用要么全不用),Laravel 使用 composer 工具进行 package 的管理,想加功能直接添加组件即可。比如你写爬虫使用页面采集组件: composer require jaeger/querylist

本文简要介绍 Laravel 中频繁用到的 PHP 特性与新语法,具体可参考。

组件化开发

Laravel 进行组件化开发,得益于遵循 PSR-4 规范的 composer 工具,其利用命名空间和自动加载来组织项目文件。更多参考:composer 自动加载机制

命名空间

命名冲突

在团队协作、引入第三方依赖代码时,往往可能会出现类、函数和接口重名的情况。比如:

<?php    
# google.php
class User 
{
    private $name;
}
登录后复制
<?php    
# mine.php
// 引入第三方依赖
include &#39;google.php&#39;;

class User
{
    private $name;
}

$user = new User();    // 命名冲突
登录后复制

因为同时定义了类 User 导致命名冲突:

97300cdd2f7ce4a84e54b9583b1738c.png

解决办法

从 PHP 5.3 开始引入,参考 PHP 手册 能知道命名空间有 2 个作用:避免命名冲突、保持命名简短。比如使用命名空间后:

<?php
# google.php
namespace Google;

// 模拟第三方依赖
class User {
    private $name = &#39;google&#39;;

    public function getName() {
        echo $this->name . PHP_EOL;
    }
}
登录后复制
<?php
# mine.php
namespace Mine;

// 导入并命名别名
use Google as G;

// 导入文件使得 google.php 命名空间变为 mine.php 的子命名空间
include &#39;google.php&#39;;

/* 避免了命名冲突 */
class User
{
    private $name = &#39;mine&#39;;

    public function getName() {
        echo $this->name . PHP_EOL;
    }
}

/* 保持了命名简短 */
// 如果没有命名空间,为了类名也不冲突,可能会出现这种函数名
// $user = new Google_User();
// Zend 风格并不提倡
$user = new G\User();

// 为了函数名也不冲突,可能会出现这种函数名
// $user->google_get_name()
$user->getName();

$user = new User();
$user->getName();
登录后复制

运行:

$ php demo.php
google
mine
登录后复制

PSR 规范

其实 namespace 与文件名无关,但按 PSR 标准要求:命名空间与文件路径一致 & 文件名与类名一致。比如 Laravel 默认生成的 laravel-demo/app/Http/Controllers/Auth/LoginController.php,其命名空间为 App\Http\Controllers\Auth & 类名为 LoginController

遵循规范,上边的 mine.phpgoogle.php 都应叫 User.php

namespace 操作符与__NAMESPACE__ 魔术常量

...
// $user = new User();
$user = new namespace\User();    // 值为当前命名空间
$user->getName();

echo __NAMESPACE__ . PHP_EOL;    // 直接获取当前命名空间字符串    // 输出 Mine
登录后复制

三种命名空间的导入

<?php
namespace CurrentNameSpace;

// 不包含前缀
$user = new User();        # CurrentNameSpace\User();

// 指定前缀
$user = new Google\User();    # CurrentNameSpace\Google\User();

// 根前缀
$user = new \Google\User();    # \Google\User();
登录后复制

全局命名空间

如果引用的类、函数没有指定命名空间,则会默认在当在 __NAMESPACE__下寻找。若要引用全局类:

<?php
namespace Demo;

// 均不会被使用到
function strlen() {}
const INI_ALL = 3;
class Exception {}

$a = \strlen(&#39;hi&#39;);         // 调用全局函数 strlen
$b = \CREDITS_GROUP;          // 访问全局常量 CREDITS_GROUP
$c = new \Exception(&#39;error&#39;);   // 实例化全局类 Exception
登录后复制

多重导入与多个命名空间

// use 可一次导入多个命名空间
use Google,
    Microsoft;

// 良好实践:每行一个 use
use Google;
use Microsoft;
登录后复制
<?php
// 一个文件可定义多个命名空间
namespace Google {
    class User {}
}    
    
namespace Microsoft {
    class User {}
}   

// 良好实践:“一个文件一个类”
登录后复制

导入常量、函数

从 PHP 5.6 开始,可使用 use functionuse const 分别导入函数和常量使用:

# google.php
const CEO = &#39;Sundar Pichai&#39;;
function getMarketValue() {
    echo &#39;770 billion dollars&#39; . PHP_EOL;
}
登录后复制
# mine.php
use function Google\getMarketValue as thirdMarketValue;
use const Google\CEO as third_CEO;

thirdMarketValue();
echo third_CEO;
登录后复制

运行:

$ php mine.php
google
770 billion dollars
Sundar Pichaimine
Mine
登录后复制

文件包含

手动加载

使用 includerequire 引入指定的文件,(字面理解)需注意 require 出错会报编译错误中断脚本运行,而 include 出错只会报 warning 脚本继续运行。

include 文件时,会先去 php.ini 中配置项 include_path 指定的目录找,找不到才在当前目录下找:

3af5146340b6b2f68c8b4a9b6c5bc82.png

<?php
    
// 引入的是 /usr/share/php/System.php
include &#39;System.php&#39;;
登录后复制

自动加载

void __autoload(string $class ) 能进行类的自动加载,但一般都使用 spl_autoload_register 手动进行注册:

<?php

// 自动加载子目录 classes 下 *.class.php 的类定义
function __autoload($class) {
    include &#39;classes/&#39; . $class . &#39;.class.php&#39;;
}

// PHP 5.3 后直接使用匿名函数注册
$throw = true;        // 注册出错时是否抛出异常
$prepend = false;    // 是否将当前注册函数添加到队列头

spl_autoload_register(function ($class) {
    include &#39;classes/&#39; . $class . &#39;.class.php&#39;;
}, $throw, $prepend);
登录后复制

在 composer 生成的自动加载文件 laravel-demo/vendor/composer/autoload_real.php 中可看到:

class ComposerAutoloaderInit8b41a
{
    private static $loader;

    public static function loadClassLoader($class)
    {
        if (&#39;Composer\Autoload\ClassLoader&#39; === $class) {
            // 加载当前目录下文件
            require __DIR__ . &#39;/ClassLoader.php&#39;;
        }
    }
    
     public static function getLoader()
    {
        if (null !== self::$loader) {
            return self::$loader;
        }
    
        // 注册自己的加载器
        spl_autoload_register(array(&#39;ComposerAutoloaderInit8b41a6&#39;, &#39;loadClassLoader&#39;), true, true);
        self::$loader = $loader = new \Composer\Autoload\ClassLoader();
        spl_autoload_unregister(array(&#39;ComposerAutoloaderInit8b41a6a&#39;, &#39;loadClassLoader&#39;));

        ...
     }
 
    ...
}
登录后复制

这里只提一下,具体 Laravel 整体是怎么做自动加载的,后边的文章会细说。

反射

参考 PHP 手册,可简单的理解为在运行时获取对象的完整信息。反射有 5 个类:

ReflectionClass     // 解析类名
ReflectionProperty     // 获取和设置类属性的信息(属性名和值、注释、访问权限)
ReflectionMethod     // 获取和设置类函数的信息(函数名、注释、访问权限)、执行函数等
ReflectionParameter    // 获取函数的参数信息
ReflectionFunction    // 获取函数信息
登录后复制

比如 ReflectionClass 的使用:

<?php

class User
{
    public $name;
    public $age;

    public function __construct($name = &#39;Laruence&#39;, $age = 35) {
        $this->name = $name;
        $this->age  = $age;
    }

    public function intro() {
        echo '[name]: ' . $this->name . PHP_EOL;
        echo '[age]: '  . $this->age  . PHP_EOL;
    }
}

reflect('User');

// ReflectionClass 反射类使用示例
function reflect($class) {
    try {
        $ref = new ReflectionClass($class);
        // 检查是否可实例化
        // interface、abstract class、 __construct() 为 private 的类均不可实例化
        if (!$ref->isInstantiable()) {
            echo "[can't instantiable]: ${class}\n";
        }

        // 输出属性列表
        // 还能获取方法列表、静态常量等信息,具体参考手册
        foreach ($ref->getProperties() as $attr) {
            echo $attr->getName() . PHP_EOL;
        }

        // 直接调用类中的方法,个人认为这是反射最好用的地方
        $obj = $ref->newInstanceArgs();
        $obj->intro();
    } catch (ReflectionException $e) {
            // try catch 机制真的不优雅
            // 相比之下 Golang 的错误处理虽然繁琐,但很简洁
        echo '[reflection exception: ]' . $e->getMessage();
    }
}
登录后复制

运行:

$ php reflect.php
name
age
[name]: Laruence
[age]: 35
登录后复制

其余 4 个反射类参考手册 demo 即可。

后期静态绑定

参考 PHP 手册,先看一个例子:

<?php

class Base
{
        // 后期绑定不局限于 static 方法
    public static function call() {
        echo &#39;[called]: &#39; . __CLASS__ . PHP_EOL;
    }

    public static function test() {
        self::call();        // self   取值为 Base  直接调用本类中的函数
        static::call();        // static 取值为 Child 调用者
    }
}

class Child extends Base
{
    public static function call() {
        echo &#39;[called]: &#39; . __CLASS__ . PHP_EOL;
    }
}


Child::test();
登录后复制

输出:

$ php late_static_bind.php
[called]: Base
[called]: Child
登录后复制

在对象实例化时,self:: 会实例化根据定义所在的类,static:: 会实例化调用它的类。

trait

基本使用

参考 PHP 手册,PHP 虽然是单继承的,但从 5.4 后可通过 trait 水平组合“类”,来实现“类”的多重继承,其实就是把重复的函数拆分成 triat 放到不同的文件中,通过 use 关键字按需引入、组合。可类比 Golang 的 struct 填鸭式组合来实现继承。比如:

<?php

class DemoLogger
{
    public function log($message, $level) {
        echo "[message]: $message", PHP_EOL;
        echo "[level]: $level", PHP_EOL;
    }
}

trait Loggable
{
    protected $logger;

    public function setLogger($logger) {
        $this->logger = $logger;
    }

    public function log($message, $level) {
        $this->logger->log($message, $level);
    }
}

class Foo
{
        // 直接引入 Loggable 的代码片段
    use Loggable;
}

$foo = new Foo;
$foo->setLogger(new DemoLogger);
$foo->log('trait works', 1);
登录后复制

运行:

$ php trait.php
[message]: trait works
[level]: 1
登录后复制

更多参考:我所理解的 PHP Trait

重要性质

优先级

当前类的函数会覆盖 trait 的同名函数,trait 会覆盖父类的同名函数( use trait 相当于当前类直接覆写了父类的同名函数)

trait 函数冲突

同时引入多个 trait 可用 , 隔开,即多重继承。

多个 trait 有同名函数时,引入将发生命名冲突,使用 insteadof 来指明使用哪个 trait 的函数。

重命名与访问控制

使用 as 关键字可以重命名的 trait 中引入的函数,还可以修改其访问权限。

其他

trait 类似于类,可以定义属性、方法、抽象方法、静态方法和静态属性。

下边的苹果、微软和 Linux 的小栗子来说明:

<?php

trait Apple
{
    public function getCEO() {
        echo &#39;[Apple CEO]: Tim Cook&#39;, PHP_EOL;
    }

    public function getMarketValue() {
        echo &#39;[Apple Market Value]: 953 billion&#39;, PHP_EOL;
    }
}


trait MicroSoft
{
    public function getCEO() {
        echo &#39;[MicroSoft CEO]: Satya Nadella&#39;, PHP_EOL;
    }

    public function getMarketValue() {
        echo &#39;[MicroSoft Market Value]: 780 billion&#39;, PHP_EOL;
    }

    abstract public function MadeGreatOS();

    static public function staticFunc() {
        echo &#39;[MicroSoft Static Function]&#39;, PHP_EOL;
    }

    public function staticValue() {
        static $v;
        $v++;
        echo &#39;[MicroSoft Static Value]: &#39; . $v, PHP_EOL;
    }
}


// Apple 最终登顶,成为第一家市值超万亿美元的企业
trait Top
{
    // 处理引入的 trait 之间的冲突
    use Apple, MicroSoft {
        Apple::getCEO insteadof MicroSoft;
        Apple::getMarketValue insteadof MicroSoft;
    }
}


class Linux
{
    use Top {
            // as 关键字可以重命名函数、修改权限控制
        getCEO as private noCEO;
    }

    // 引入后必须实现抽象方法
    public function MadeGreatOS() {
        echo &#39;[Linux Already Made]&#39;, PHP_EOL;
    }

    public function getMarketValue() {
        echo &#39;[Linux Market Value]: Infinity&#39;, PHP_EOL;
    }
}

$linux = new Linux();
// 和 extends 继承一样
// 当前类中的同名函数也会覆盖 trait 中的函数
$linux->getMarketValue();

// trait 中可以定义静态方法
$linux::staticFunc();

// 在 trait Top 中已解决过冲突,输出库克
$linux->getCEO();
// $linux->noCEO();        // Uncaught Error: Call to private method Linux::noCEO() 

// trait 中可以定义静态变量
$linux->staticValue();
$linux->staticValue();
登录后复制

运行:

$ php trait.php
[Linux Market Value]: Infinity
[MicroSoft Static Function]
[Apple CEO]: Tim Cook
[MicroSoft Static Value]: 1
[MicroSoft Static Value]: 2
登录后复制

总结

本节简要提及了命名空间、文件自动加载、反射机制与 trait 等,Laravel 正是恰如其分的利用了这些新特性,才实现了组件化开发、服务加载等优雅的特性。

以上是总结Laravel中常用的PHP语法有哪些的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

适用于 Ubuntu 和 Debian 的 PHP 8.4 安装和升级指南 适用于 Ubuntu 和 Debian 的 PHP 8.4 安装和升级指南 Dec 24, 2024 pm 04:42 PM

PHP 8.4 带来了多项新功能、安全性改进和性能改进,同时弃用和删除了大量功能。 本指南介绍了如何在 Ubuntu、Debian 或其衍生版本上安装 PHP 8.4 或升级到 PHP 8.4

如何设置 Visual Studio Code (VS Code) 进行 PHP 开发 如何设置 Visual Studio Code (VS Code) 进行 PHP 开发 Dec 20, 2024 am 11:31 AM

Visual Studio Code,也称为 VS Code,是一个免费的源代码编辑器 - 或集成开发环境 (IDE) - 可用于所有主要操作系统。 VS Code 拥有针对多种编程语言的大量扩展,可以轻松编写

您如何在PHP中解析和处理HTML/XML? 您如何在PHP中解析和处理HTML/XML? Feb 07, 2025 am 11:57 AM

本教程演示了如何使用PHP有效地处理XML文档。 XML(可扩展的标记语言)是一种用于人类可读性和机器解析的多功能文本标记语言。它通常用于数据存储

在PHP API中说明JSON Web令牌(JWT)及其用例。 在PHP API中说明JSON Web令牌(JWT)及其用例。 Apr 05, 2025 am 12:04 AM

JWT是一种基于JSON的开放标准,用于在各方之间安全地传输信息,主要用于身份验证和信息交换。1.JWT由Header、Payload和Signature三部分组成。2.JWT的工作原理包括生成JWT、验证JWT和解析Payload三个步骤。3.在PHP中使用JWT进行身份验证时,可以生成和验证JWT,并在高级用法中包含用户角色和权限信息。4.常见错误包括签名验证失败、令牌过期和Payload过大,调试技巧包括使用调试工具和日志记录。5.性能优化和最佳实践包括使用合适的签名算法、合理设置有效期、

php程序在字符串中计数元音 php程序在字符串中计数元音 Feb 07, 2025 pm 12:12 PM

字符串是由字符组成的序列,包括字母、数字和符号。本教程将学习如何使用不同的方法在PHP中计算给定字符串中元音的数量。英语中的元音是a、e、i、o、u,它们可以是大写或小写。 什么是元音? 元音是代表特定语音的字母字符。英语中共有五个元音,包括大写和小写: a, e, i, o, u 示例 1 输入:字符串 = "Tutorialspoint" 输出:6 解释 字符串 "Tutorialspoint" 中的元音是 u、o、i、a、o、i。总共有 6 个元

解释PHP中的晚期静态绑定(静态::)。 解释PHP中的晚期静态绑定(静态::)。 Apr 03, 2025 am 12:04 AM

静态绑定(static::)在PHP中实现晚期静态绑定(LSB),允许在静态上下文中引用调用类而非定义类。1)解析过程在运行时进行,2)在继承关系中向上查找调用类,3)可能带来性能开销。

什么是PHP魔术方法(__ -construct,__destruct,__call,__get,__ set等)并提供用例? 什么是PHP魔术方法(__ -construct,__destruct,__call,__get,__ set等)并提供用例? Apr 03, 2025 am 12:03 AM

PHP的魔法方法有哪些?PHP的魔法方法包括:1.\_\_construct,用于初始化对象;2.\_\_destruct,用于清理资源;3.\_\_call,处理不存在的方法调用;4.\_\_get,实现动态属性访问;5.\_\_set,实现动态属性设置。这些方法在特定情况下自动调用,提升代码的灵活性和效率。

在Laravel中如何获取邮件发送失败时的退信代码? 在Laravel中如何获取邮件发送失败时的退信代码? Apr 01, 2025 pm 02:45 PM

Laravel邮件发送失败时的退信代码获取方法在使用Laravel开发应用时,经常会遇到需要发送验证码的情况。而在实�...

See all articles