Drupal 8 模块开发 11.5 : PhpStorm 策略

原文地址: https://docs.acquia.com/articles/drupal-8-phpstorm-strategies   PhpStorm 提供了帮助使用依赖注入的工具。   扩展结构视图 Drupal 8 里,组件功能经常跨多个文件。一个类经常扩展另一个类,或实现一些接口。结构视图可以浏览类的方法和属性,但默认情况下,看不到从其他类继承的方法。有一个按钮可以激活这个功能。   使用 CMD + 7 (Mac) 或者 View > Tool Windows > Structure 打开这个视图。   灰色方法是继承来的,黑色是当前类中的方法。使用 CMD + 1 可以显示文件列表。   使用服务名找到一个服务类 你经常会看到服务名,但找到这个服务比较有挑战性。我们可以使用 PhpStorm 的文件搜索找到它。 例如,你有参数 arguments: [‘@current_user’],代码这样: $current_user = \Drupal::service(‘current_user’); 这种情况我们知道服务叫做 current_user,但不清楚它定义在那个 service.yml 文件内。 使用 CMD + Shift + F 打开文件搜索。 使用带冒号的服务名 service-name: ,只在 […]

Continue Reading

Drupal 8 模块开发 11.4 : 依赖注入和插件

原文地址: https://docs.acquia.com/articles/drupal-8-dependency-injection-and-plugins   插件 插件是添加依赖注入最复杂的组件。很多插件不需要依赖注入,有时找例子来拷贝都具有挑战性。多数插件继承了使用接口的类。例如 Blocks,继承了 BlockBase,BlockBase 实现了 BlockPluginInterface 。   依赖注入应该添加在个别插件级,而不是基类级别。这意味着我们能够向任何插件添加依赖注入,创建新插件时,也不总是需要使用依赖注入。   实现 ContainerFactoryPluginInterface 插件使用依赖注入的关键是实现 ContainerFactoryPluginInterface 。当插件被创建时,代码首先检查插件是否实现了这个接口。如果实现,使用 create() 和 __construct() 模式,如果未实现,则只使用 __construct() 模式。 下载文件 <?php /**  * @file  * Contains \Drupal\Core\Plugin\Factory\ContainerFactory.  */ namespace Drupal\Core\Plugin\Factory; use Drupal\Component\Plugin\Factory\DefaultFactory; /**  * Plugin factory which passes a container to a create method.  */ class ContainerFactory extends DefaultFactory { […]

Continue Reading

Drupal 8 模块开发 11.3 : 依赖注入和控制器

原文地址: https://docs.acquia.com/articles/drupal-8-dependency-injection-and-controllers   控制器 控制器使用依赖注入比较容易,因为他们提供返回服务容器的 create() 方法。我们已经创建了路由,现在创建下控制器文件: src/Controller/DIController.php 下载文件 <?php   /**  * @file  * Contains \Drupal\di_example\Controller\DIController.  */   namespace Drupal\di_example\Controller;   use Drupal\Core\Controller\ControllerBase; use Symfony\Component\DependencyInjection\ContainerInterface; use Drupal\di_example\DITalk;   class DIController extends ControllerBase {     /**    * @var \Drupal\di_example\DITalk    */   protected $dITalk;     /**    * @param \Drupal\di_example\DITalk $DITalk    […]

Continue Reading

Drupal 8 模块开发 11.2 : 依赖注入和服务

原文地址: https://docs.acquia.com/articles/drupal-8-dependency-injection-and-services   注入服务 上文定义服务时映射了服务名和服务类,这个服务也是完全独立的。如果我们想创建一个使用其他服务的服务,那么必须注入这些依赖(在 services.yml 文件里定义这些依赖)。我们更新下之前定义的 di_example.services.yml 文件,创建一个使用 current_user 和 di_example.mood_ring 服务 的 di_example.talk 服务。 services:   # A service that will let us get a mood.   di_example.mood_ring:     class: Drupal\di_example\DIMoodRing   # A service that will let us talk to users.   di_example.talk:     class: Drupal\di_example\DITalk     # We can inject the current […]

Continue Reading

Drupal 8 模块开发 11.1 : 依赖注入回顾

原文地址: https://docs.acquia.com/articles/drupal-8-review-dependency-injection   在之前的课程里,我们介绍了 服务(services),控制器(controllers)和插件(plugins)机种模式。在这些模式里我们演示了怎样使用依赖注入。在本回顾里,我们提供一些简单的例子,讨论下怎样使用 PhpStorm 帮助我们使用这些模式。   安装基础例子模块 我们将创建包含两个服务,一个控制器和一个区块插件的 di_example 模块。我们首先创建不涉及依赖注入的基础部分: .info.yml 和 .routing.yml 文件,以及一个服务。这个服务不依赖其他的服务。   di_example.info.yml name: Dependency Injection Example type: module description: Examples on how to use dependency injection core: 8.x package: Examples   di_example.routing.yml 这个文件里,我们会有一个生成页面的控制器,它提供一个输出信息,我们叫它交谈(conversation)。交谈关于用户的情绪(mood )。 di_example.conversation_mood:   path: ‘/examples/conversation/mood’   defaults:     _controller: ‘\Drupal\di_example\Controller\DIController::conversationAboutMood’   requirements:     _access: ‘TRUE’   […]

Continue Reading

Drupal 8 模块开发 10.4 : PHPUnit Doubles / Mocks / Stubs

原文地址:https://docs.acquia.com/articles/drupal-8-phpunit-doubles-mocks-stubs   我们写单体测试的目的是要测试个别组件,例如一个服务。通常,服务需要系统其他部分的功能。这种情况下,需要制造依赖的一个模拟(Mock)版本,以便于我们把焦点放在测试服务本身。   创建一个模拟 当你创建一个模拟时,其实你正在创建那个类的一个副本,只是它的所有方法被替换返回 NULL。 例如,如果我们需要一个查询对象,可以使用 getMockBuilder() 和  getMock() 方法取得一个。 $query = $this->getMockBuilder(‘\Drupal\Core\Entity\Query\QueryInterface’) ->getMock(); 你能看到我们在本例中传递了类名,之后调用了 getMock()。   禁用原始构造器 这种模式适用于大多数类。一些类有一个 __construct() 函数,需要被移除。我们知道的最简点方式是用基本模式运行你的测试,如果收到一个错误,就添加 disableOriginalConstructor() 方法移除它。 $query_factory = $this->getMockBuilder(‘\Drupal\Core\Entity\Query\QueryFactory’) ->disableOriginalConstructor() ->getMock();   抽象类 某些情况下,你将使用一个抽象类。再试下常规模式,如果出错,可以使用下面的方法: $filter_plugin = $this->getMockBuilder(‘\Drupal\filter\Plugin\FilterBase’)                                 ->getMockForAbstractClass();   模拟方法 […]

Continue Reading

Drupal 8 模块开发 10.3 : 功能测试

原文地址:https://docs.acquia.com/articles/drupal-8-functional-tests   Drupal 8 中的功能测试需要你有一个正在运行的站点,并且安装了 SimpleTest(核心内) 模块。该测试中我们会向用户(user)实体追加一个字段,之后检查用户是否存在这个字段。我们需要使用功能测试,因为我们需要引导 Drupal 获得用户对象。当然通过单体测试检查这个也可以,但我们最终处理的是很复杂的一个系统。   PHPUnit 和 SimpleTest 功能测试(BrowserTestBase / WebTestBase) 标准和未来的默认功能测试系统是使用 PHPUnit 和基类 BrowserTestBase 。很多核心使用老的功能测试系统 SimpleTest 以及 WebTestBase 。基于 PHPUnit 的测试能从 IDE 运行。SimpleTest 测试运行稍复杂一些,我们将在后边覆盖到。   当前 BrowserTestBase  的主要限制是不能使用 JavaScript 和 AJAX 。如果你的测试需要它们,那么在 JavaScript 被添加到 BrowserTestBase 之前还得使用老的 WebTestBase 。   追加用户字段 第一个测试,我们向用户实体追加一个字段,之后测试这个字段是否有效。 test_example.info.yml name: Test Example type: module description: Example showing how […]

Continue Reading

Drupal 8 模块开发 10.2 : 单体测试

原文地址:https://docs.acquia.com/articles/drupal-8-unit-testing   Drupal 附带了一个 PHPUnit 版本,但你需要确保它配置正确。我们假设你正使用 PhoStorm,但你也可以从命令行运行这些测试。   何时你应该创建单体测试? 服务最有意义做单体测试,因为它们被设计为独立存在。围绕测什么有很多争论。首先测试你的所有服务方法,之后根据需要添加测试,这样进行测试可能比较有用。   在 PhpStorm 内配置 PHPUnit 配置项目: 导航到 PhpStorm > Preferences > Languages & Frameworks > PHP > PHPUnit > Local Window 操作系统是:File > Settings … 选择 PHPUnit Library > Use custom autoloader 导航到 /vendor/autoload.php 选择 Test Runner > Default configuration file 导航到 /core/phpunit.xml.dist 点击 Save […]

Continue Reading

Drupal 8 模块开发 10.1 : 单体和功能测试

原文地址:https://docs.acquia.com/articles/drupal-8-unit-and-functional-testing   Drupal 8 中的测试主要分为两种类型:单体测试和功能测试。测试被用于多种途径,有些测试在开发开始之前书写,帮助开发者构建所需要的功能。另一些测试帮助进行回归测试。本课目的是介绍这两种类型的测试,但不解释何时写这些测试。   单体测试和功能测试的主要区别是测试的范围,单体测试旨在测试少量的功能。Drupal 8 中,自定义服务比较适合使用单体测试,这是因为服务被设计为与使用这个服务的功能解耦,这些服务不依赖于正在运行的 Drupal 站点或者现场运行的配置和数据。   功能测试是测试整合了很多组件的功能。例如,我们可能希望在系统中执行一个变更,然后确保另一个系统响应这种变化。要完成这个你需要一个实际的 Drupal 站点。你可以做更大范围的功能测试,但它们通常较慢。   本课… 书写单体测试 执行单体测试 书写功能测试 执行功能测试   初期安装 我们创建个新模块 test_example。 test_example.info.yml name: Test Example type: module description: Example showing how to create tests core: 8.x package: Examples dependencies:   – user   – options   创建一个简单服务 服务(Services)是能够进行测试的好例子。 test_example.services.yml services:   […]

Continue Reading

Drupal 8 模块开发 9.6 : 实验室

原文地址: https://docs.acquia.com/articles/drupal-8-theme-lab   总结 Drupal 这些年改变了很多,很多情况下,它支持新旧系统。Drupal 8 中主题改进很多,但它没有像其他系统那样大修的很彻底。所以关注新的和一贯的方式很重要,而不是只关注所有的新老替代方案。   完整步骤 创建新模块 theme_example 拷贝代码到 theme_example.info.yml 拷贝代码到 theme_example.routing.yml 拷贝代码到 src/Controller/ThemeExampleController.php 创建插件 src/Element/MyElement.php 拷贝代码到 theme_example.module 创建 Twig 模板 templates/my-element.html.twig 创建 theme_example.libraries.yml 和追加 sample_library 拷贝代码到 theme_example/css/example.css 更新控制器 src/Controller/ThemeExampleController.php 拷贝代码到 theme_example/js/example.js 查看例子页面 /examples/theme-example/simple 激活 Twig debugging 激活 Devel 和 Kint 模块 研究产生页面中的调试信息 在 Twig 模板中增加 kint() 调试函数   额外练习 在 […]

Continue Reading