PHP自定义注解:增强代码灵活性和可扩展性
本文探讨如何在Symfony 3应用中创建和使用自定义注解。注解是我们在类、方法和属性上方看到的文档块元数据/配置,常用于声明控制器路由(@Route()
)、Doctrine ORM映射(@ORM()
)或控制对Rauth等包中各种类和方法的访问。本文将介绍如何自定义注解,并在不加载类的情况下读取类或方法信息。
关键要点:
- PHP自定义注解可用于向代码添加元数据,影响代码行为,使其更灵活、更易于适应。它们可用于定义路由信息、指定验证规则或配置依赖注入。
- 创建PHP自定义注解需要定义一个新的类来表示该注解。此类应具有与您希望在注解中设置的值相对应的属性。
- Doctrine支持自定义注解。您可以定义自己的注解并将其用于Doctrine实体中。Doctrine的注解读取器将解析这些注解,然后可以使用它们来影响实体的行为。
- 使用PHP自定义注解的一个限制是它们不受语言本身的原生支持。这意味着您需要使用提供注解支持的库或工具,例如Doctrine或PHP-DI。
- PHP自定义注解的用途多种多样,包括在Web应用程序中定义路由信息、为表单输入指定验证规则或配置依赖注入。它们还可用于向代码添加文档。
免责声明: 注解与Symfony无关,它是作为Doctrine项目的一部分开发的概念,用于解决将ORM信息映射到类方法的问题。
本文将构建一个名为WorkerBundle的小型可重用捆绑包(仅用于演示目的,并非真正可打包的)。我们将开发一个小型概念,允许定义各种以不同速度“运行”的Worker类型,然后应用程序中的任何人都可以使用它们。实际的worker操作不在本文的讨论范围之内,因为我们关注的是设置管理它们的系统(并通过注解发现它们)。
您可以查看这个仓库并按照其中介绍的说明在本地Symfony应用程序中设置捆绑包。
Worker
Worker将实现一个接口,该接口需要一个方法:::work()
。在新的WorkerBundle中,让我们创建一个Workers/
目录来保持整洁,并在其中添加接口:
<?php namespace WorkerBundle\Workers; interface WorkerInterface { /** * 执行工作 * * @return NULL */ public function work(); }
注解
每个worker都必须实现上述接口。很清楚。但除此之外,我们还需要它们在类上方有一个注解,以便找到它们并读取有关它们的某些元数据。
Doctrine将文档块注解映射到一个类,该类的属性表示注解本身内部的键。让我们创建我们自己的注解并实际操作一下。
每个WorkerInterface实例在其文档块中都将具有以下注解:
<?php namespace WorkerBundle\Workers; interface WorkerInterface { /** * 执行工作 * * @return NULL */ public function work(); }
我们将保持简单,只有两个属性:唯一名称(字符串)和worker速度(整数)。为了使Doctrine的注解库能够识别此注解,我们必须创建一个匹配的类,不出所料,它自己也有一些注解。
我们将此类放在捆绑包命名空间的Annotation文件夹中,并将其简单地命名为Worker:
/** * @Worker( * name = "唯一的Worker名称", * speed = 10 * ) */
如您所见,我们有两个属性和一些简单的getter方法。更重要的是,我们在顶部有两个注解:@Annotation
(告诉Doctrine此类表示一个注解)和@Target("CLASS")
(告诉它应该在整个类而不是方法或属性上方使用)。就是这样,WorkerInterface类现在可以通过确保在文件顶部使用use
语句导入相应的类来使用此注解:
<?php namespace WorkerBundle\Annotation; use Doctrine\Common\Annotations\Annotation; /** * @Annotation * @Target("CLASS") */ class Worker { /** * @Required * * @var string */ public $name; /** * @Required * * @var int */ public $speed; /** * @return string */ public function getName() { return $this->name; } /** * @return int */ public function getSpeed() { return $this->speed; } }
管理器
接下来,我们需要一个管理器,我们的应用程序可以使用它来获取所有可用worker的列表并创建它们。在与WorkerInterface相同的命名空间中,我们可以使用这个简单的管理器类:
use WorkerBundle\Annotation\Worker;
发现器
我们注解演示的关键部分实际上是发现过程的一部分。为什么?因为我们使用Worker注解来确定是否应将相应的类视为Worker。在此过程中,我们在实际实例化对象之前使用了元数据。让我们看看我们的WorkerDiscovery类:
<?php namespace WorkerBundle\Workers; class WorkerManager { // ... (代码与原文相同) ... }
连接起来
现在我们有了主要组件,是时候将所有内容连接起来了。首先,我们需要服务定义,因此在捆绑包的Resource/config文件夹中,我们可以有这个services.yml文件:
<?php namespace WorkerBundle\Workers; // ... (代码与原文相同) ... }
为了使我们的服务定义能够被容器集中拾取,我们需要编写一个小的扩展类。因此,在捆绑包的DependencyInjection文件夹中,创建一个名为WorkerExtension的类。位置和名称对于Symfony自动拾取它都很重要。
services: worker_manager: class: WorkerBundle\Workers\WorkerManager arguments: ["@worker_discovery"] worker_discovery: class: WorkerBundle\Workers\WorkerDiscovery arguments: ["%worker_namespace%", "%worker_directory%", "%kernel.root_dir%", "@annotation_reader"]
最后,我们需要注册我们的捆绑包。在我们的AppKernel中:
<?php namespace WorkerBundle\DependencyInjection; // ... (代码与原文相同) ... }
就是这样。
让我们工作!
现在我们准备工作了。让我们在中央parameters.yml文件中配置我们的worker将在哪里找到:
public function registerBundles() { return array( // ... new WorkerBundle\WorkerBundle(), // ... ); }
这些参数从容器传递到WorkerDiscovery类,如上所述。
位置由您决定,但现在让我们将我们的worker放在应用程序的主要AppBundle捆绑包中。我们的第一个worker可能如下所示:
<?php namespace WorkerBundle\Workers; interface WorkerInterface { /** * 执行工作 * * @return NULL */ public function work(); }
我们的注解在那里,use
语句到位,因此没有任何东西可以阻止某些业务逻辑找到它并实例化它。让我们假设在一个Controller方法内部:
/** * @Worker( * name = "唯一的Worker名称", * speed = 10 * ) */
或者
<?php namespace WorkerBundle\Annotation; use Doctrine\Common\Annotations\Annotation; /** * @Annotation * @Target("CLASS") */ class Worker { /** * @Required * * @var string */ public $name; /** * @Required * * @var int */ public $speed; /** * @return string */ public function getName() { return $this->name; } /** * @return int */ public function getSpeed() { return $this->speed; } }
结论
我们现在可以使用注解来表达有关类(或方法和属性)的元数据。在本教程中,我们构建了一个小型包,它使应用程序(或其他外部捆绑包)能够通过定义有关它们的某些元数据来声明能够执行某些工作的worker。此元数据不仅使它们易于发现,而且还提供有关是否应该实际使用它们的信息。
您在自己的项目中使用自定义注解吗?如果是这样,您是如何实现它们的?也许还有第三种方法?让我们知道!
(感兴趣了解更多关于Symfony、Doctrine、注解以及各种企业级PHP内容的信息?加入我们,参加为期三天的动手研讨会,WebSummerCamp——唯一一个完全手动的会议,并且还会照顾您想带去的任何人!)
(原文的FAQ部分已省略,因为其内容与已翻译和改写的内容高度重复。)
以上是您自己的自定义注释 - 不仅仅是评论!的详细内容。更多信息请关注PHP中文网其他相关文章!

DependencyInjection(DI)inPHPenhancescodeflexibilityandtestabilitybydecouplingdependencycreationfromusage.ToimplementDIeffectively:1)UseDIcontainersjudiciouslytoavoidover-engineering.2)Avoidconstructoroverloadbylimitingdependenciestothreeorfour.3)Adhe

到Improveyourphpwebsite的实力,UsEthestertate:1)emplastOpCodeCachingWithOpcachetCachetOspeedUpScriptInterpretation.2)优化的atabasequesquesquesquelies berselectingOnlynlynnellynnessaryfields.3)usecachingsystemssslikeremememememcachedisemcachedtoredtoredtoredsatabaseloadch.4)

是的,itispossibletosendMassemailswithp.1)uselibrarieslikeLikePhpMailerorSwiftMailerForeffitedEmailSending.2)enasledeLaysBetemailStoavoidSpamflagssspamflags.3)sylectynamicContentToimpovereveragement.4)

DependencyInjection(DI)inPHPisadesignpatternthatachievesInversionofControl(IoC)byallowingdependenciestobeinjectedintoclasses,enhancingmodularity,testability,andflexibility.DIdecouplesclassesfromspecificimplementations,makingcodemoremanageableandadapt

使用PHP发送电子邮件的最佳方法包括:1.使用PHP的mail()函数进行基本发送;2.使用PHPMailer库发送更复杂的HTML邮件;3.使用SendGrid等事务性邮件服务提高可靠性和分析能力。通过这些方法,可以确保邮件不仅到达收件箱,还能吸引收件人。

计算PHP多维数组的元素总数可以使用递归或迭代方法。1.递归方法通过遍历数组并递归处理嵌套数组来计数。2.迭代方法使用栈来模拟递归,避免深度问题。3.array_walk_recursive函数也能实现,但需手动计数。

在PHP中,do-while循环的特点是保证循环体至少执行一次,然后再根据条件决定是否继续循环。1)它在条件检查之前执行循环体,适合需要确保操作至少执行一次的场景,如用户输入验证和菜单系统。2)然而,do-while循环的语法可能导致新手困惑,且可能增加不必要的性能开销。

在PHP中高效地哈希字符串可以使用以下方法:1.使用md5函数进行快速哈希,但不适合密码存储。2.使用sha256函数提高安全性。3.使用password_hash函数处理密码,提供最高安全性和便捷性。


热AI工具

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

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

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

PhpStorm Mac 版本
最新(2018.2.1 )专业的PHP集成开发工具

SecLists
SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

SublimeText3 英文版
推荐:为Win版本,支持代码提示!

SublimeText3汉化版
中文版,非常好用

安全考试浏览器
Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。