Tại sao một số lớp định nghĩa phép tiêm trong cả hàm tạo và di.xml của chúng?


12

Tôi không hiểu tại sao, trong một số lớp, việc tiêm phụ thuộc của chúng được khai báo hai lần - một lần trong di.xmlvà trong hàm tạo của lớp cụ thể.

Chẳng hạn Magento\Backend\Model\Url, nó di.xmlcó tập hợp các kiểu cho DI được xác định:

<type name="Magento\Backend\Model\Url">
    <arguments>
        <argument name="scopeResolver" xsi:type="object">
Magento\Backend\Model\Url\ScopeResolver</argument>
        <argument name="authSession" xsi:type="object">
Magento\Backend\Model\Auth\Session\Proxy</argument>
        <argument name="formKey" xsi:type="object">
Magento\Framework\Data\Form\FormKey\Proxy</argument>
        <argument name="scopeType" xsi:type="const">
Magento\Store\Model\ScopeInterface::SCOPE_STORE </argument>
        <argument name="backendHelper" xsi:type="object">
Magento\Backend\Helper\Data\Proxy</argument>
    </arguments>
</type>

Nhưng đồng thời, trong lớp cụ thể của nó, các lớp được định nghĩa trong di.xml cần cho phép tiêm được khai báo lại một lần nữa trong hàm tạo:

<?php
    public function __construct(
        \Magento\Framework\App\Route\ConfigInterface $routeConfig,
        \Magento\Framework\App\RequestInterface $request,
        \Magento\Framework\Url\SecurityInfoInterface $urlSecurityInfo,
        \Magento\Framework\Url\ScopeResolverInterface $scopeResolver,
        \Magento\Framework\Session\Generic $session,
        \Magento\Framework\Session\SidResolverInterface $sidResolver,
        \Magento\Framework\Url\RouteParamsResolverFactory $routeParamsResolverFactory,
        \Magento\Framework\Url\QueryParamsResolverInterface $queryParamsResolver,
        \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
        $scopeType,
        \Magento\Backend\Helper\Data $backendHelper,
        \Magento\Backend\Model\Menu\Config $menuConfig,
        \Magento\Framework\App\CacheInterface $cache,
        \Magento\Backend\Model\Auth\Session $authSession,
        \Magento\Framework\Encryption\EncryptorInterface $encryptor,
        \Magento\Store\Model\StoreFactory $storeFactory,
        \Magento\Framework\Data\Form\FormKey $formKey,
        array $data = []
) {
    //...
}
?>

Nếu chúng ta nhìn vào hàm tạo của nó ở trên, \Magento\Framework\App\Route\ConfigInterface $routeConfigchẳng hạn, không được định nghĩa trong di.xml. Nó chỉ được định nghĩa trong hàm tạo và Magento vẫn sẽ đưa routeConfigvào lớp để sử dụng, phải không? Tương tự cho \Magento\Framework\Encryption\EncryptorInterface $encryptorvà một vài người khác.

Vậy thì, tại sao cần phải xác định các phép tiêm khác trong cả hai di.xmlvà trong hàm tạo khi có các khai báo đó trong hàm tạo là đủ để Magento đưa các phụ thuộc đó vào lớp để sử dụng?

Câu trả lời:


15

Như đã nêu trong tài liệu , trong Magento 2, di.xmlcó thể được sử dụng để làm như sau:

Bạn có thể cấu hình các đối số hàm tạo lớp di.xmltrong nút đối số của bạn . Trình quản lý đối tượng đưa các đối số này vào lớp trong quá trình tạo. Tên của đối số được cấu hình trong tệp XML phải tương ứng với tên của tham số trong hàm tạo trong lớp được cấu hình.

Trong trường hợp của bạn, nó hơi phức tạp Tôi sẽ giải thích từng đối số một:

  • \Magento\Framework\App\Route\ConfigInterface $routeConfig: đây là giao diện nên không thể sử dụng trực tiếp . Các ưu tiên cho lớp này được định nghĩa trongapp/etc/di.xml và nó là Magento\Framework\App\Route\Configlớp
  • \Magento\Framework\App\RequestInterface $request : cùng đi với lớp này, ưu tiên là Magento\Framework\App\Request\Http
  • \Magento\Framework\Url\SecurityInfoInterface $urlSecurityInfo: trường hợp tương tự ở đây một lần nữa với Magento\Framework\Url\SecurityInfo\Proxytùy chọn
  • \Magento\Framework\Url\ScopeResolverInterface $scopeResolver: ở đây chúng tôi bắt đầu với một chút thú vị. Trong app/etc/di.xmlmột ưu tiên được xác định cho giao diện này và đó là Magento\Framework\Url\ScopeResolverlớp. Tuy nhiên, đối với Magento\Backend\Model\UrlMagento 2 cần sử dụng một lớp khác và do đó, nó xác định lớp nào trong di.xmlbạn đã đăng Magento\Backend\Model\Url\ScopeResolversẽ được sử dụng.
  • \Magento\Framework\Session\Generic $session đây là một lớp bình thường và do đó có thể được sử dụng như nó.
  • \Magento\Framework\Session\SidResolverInterface $sidResolver: quay lại giao diện, tùy chọn vẫn được xác định app/etc/di.xmlvà đó làMagento\Framework\Session\SidResolver\Proxy
  • \Magento\Framework\Url\RouteParamsResolverFactory $routeParamsResolverFactory : đây là một lớp nhà máy để nó có thể được sử dụng như nó.
  • \Magento\Framework\Url\QueryParamsResolverInterface $queryParamsResolver: trở lại app/etc/di.xmlsở thích của chúng tôi vàMagento\Framework\Url\QueryParamsResolver
  • \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig: một trường hợp khác ở đây trong đó ** một ưu tiên được xác định app/etc/di.xmlvà đó là Magento\Framework\App\Config.
  • $scopeType: ở đây chúng ta chỉ có một biến mà không có lớp nào ở trước nó. Mô-đun của bạn di.xmlchỉ định rằng Magento\Store\Model\ScopeInterface::SCOPE_STOREnên được sử dụng làm giá trị của biến này. **
  • \Magento\Backend\Helper\Data $backendHelper: ở đây chúng ta có thể sử dụng lớp đó. Tuy nhiên, ở đây một proxy được sử dụng vì lớp này không nhất thiết phải được sử dụng (xem bài đăng này để biết chi tiết về các lớp proxy: Magento 2: giải thích thực tế về lớp proxy là gì? )
  • \Magento\Backend\Model\Menu\Config $menuConfig : chúng ta có thể sử dụng lớp này như nó.
  • \Magento\Framework\App\CacheInterface $cache: một ưu tiên khác được xác định trong app/etc/di.xmlgiao diện này làMagento\Framework\App\Cache\Proxy
  • \Magento\Backend\Model\Auth\Session $authSession: cùng một lần nữa ở đây chúng ta có thể đã sử dụng lớp như nó nhưng chúng ta sử dụng một lớp proxy thay vì lười tải.
  • \Magento\Framework\Encryption\EncryptorInterface $encryptor: nhảy sang app/etc/di.xmlmột lần nữa và chúng tôi tìm thấy Magento\Framework\Encryption\Encryptornhư một sở thích
  • \Magento\Store\Model\StoreFactory $storeFactory : một nhà máy để chúng tôi có thể sử dụng nó như nó.
  • \Magento\Framework\Data\Form\FormKey $formKey: ở đây chúng tôi sử dụng một Magento\Framework\Data\Form\FormKey\Proxylớp proxy một lần nữa để lười tải.
  • array $data = []: cái này luôn luôn xuất hiện cuối cùng và được tự động mặc định thành một mảng trống, bạn có thể tìm thêm thông tin ở đây: Magento 2: tham số hàm tạo mảng dữ liệu $ là gì?

Tóm tắt

Trên toàn cầu, các tham số hàm tạo của lớp là các giao diện hoặc các lớp không thể thực hiện được. Do đó di.xmlcho phép bạn điều chỉnh các phụ thuộc mà bạn muốn sử dụng cho mỗi hàm tạo của lớp. Nó cũng hợp lệ cho các lớp khả thi. Ví dụ, một hàm tạo của lớp lấy một lớp sản phẩm làm đối số của hàm tạo. Nó có thể được tùy chỉnh trong mô-đun sản phẩm có thể định cấu hình để nó lấy một lớp sản phẩm có thể định cấu hình thay vì làm đối số.


Là một ưu tiên luôn luôn cần thiết cho một tham số giao diện? Nó có thể được coi là một dự phòng? Liệu nó có ý nghĩa khi chỉ xác định một đối số cụ thể trong cấu hình mà không có một ưu tiên ở bất cứ đâu? Hay là không thể?
robsch

6

Điều quan trọng là phải hiểu sự khác biệt giữa định nghĩa của phụ thuộc và cấu hình của phụ thuộc.

Sự phụ thuộc không được định nghĩa bên trong di.xml. Các phụ thuộc được định nghĩa bên trong hàm tạo của lớp tương ứng bằng cách chỉ định một giao diện, một bản tóm tắt hoặc một nhà máy là loại phụ thuộc cụ thể đó, ví dụ như $routeConfiglà một phụ thuộc của loại \Magento\Framework\App\Route\ConfigInterface.

Mặt khác, di.xmllà nơi để cấu hình các phụ thuộc bằng cách sử dụng <preference/>các nút và / hoặc xpath:type/arguments/argumentnút (đôi khi được kết hợp với các nút cấu hình nâng cao hơn như <virtualType/>hoặc <proxy/>). Cấu hình một phụ thuộc đơn giản có nghĩa là ánh xạ đối số hàm tạo của đối tượng thành một triển khai / đối tượng / cụ thể .

Bạn muốn các phụ thuộc có thể được cấu hình thông qua di.xml để bạn có thể trao đổi chúng và sử dụng một triển khai khác cho một giao diện hoặc đối số nhất định trong các điều kiện nhất định (tiếp tục đọc ví dụ để hiểu ý nghĩa của các điều kiện nhất định).

Ví dụ: khi phát triển tiện ích mở rộng của bạn, trước tiên bạn sẽ tạo một lớp mới (chúng tôi gọi lớp mới này là một triển khai ). Lớp mới của bạn thực hiện \Magento\Framework\App\Route\ConfigInterfacegiao diện và bên trong nó có chức năng cụ thể nhằm tôn vinh hợp đồng giao diện. Bây giờ bắt đầu phần cấu hình : để yêu cầu Magento sử dụng triển khai mới được xác định của bạn, bạn phải định cấu hình triển khai này làm phần phụ thuộc cho đối tượng Magento\Backend\Model\Url . Bạn thực hiện cấu hình này bên trong các di.xmltập tin hoặc mô-đun của bạn. Trong trường hợp này, bạn cần sử dụng <preference/>nút để ánh xạ giao diện đến triển khai mới của bạn. Những lần khác, bạn sẽ sử dụng xpath:type/arguments/argument di.xmlnút chi tiết hơn đểchỉ ánh xạ các đối số cụ thể (còn gọi là phụ thuộc, giao diện aka) của một triển khai cụ thể . Bây giờ, việc triển khai của bạn sẽ chỉ hoạt động như một phụ thuộc cho đối tượng \Magento\Backend\Model\Url trong một số điều kiện nhất định , ví dụ: trong luồng thực thi mã của ứng dụng hiện tại yêu cầu một đối tượng loại Magento\Backend\Model\Urlđang được tạo và nó cần một triển khai cho phụ thuộc được xác định bởi hàm$routeConfig tạo thuộc loại \Magento\Framework\App\Route\ConfigInterface.

Nó khá giống như nói:

"Này ông ObjectManager! Bất cứ khi nào một thể hiện đối tượng của loại Magento\Backend\Model\Urlđược yêu cầu, xin vui lòng có một cái nhìn tại các lớp học định nghĩa constructor thứ nhất và phân tích dependecies định nghĩa trong đó. Tôi muốn sau đó bạn để tra cứu trong trận chung kết, sáp nhập di.xmlcủa yêu cầu HTTP hiện các cấu hình cho mỗi và mọi phụ thuộc được cấu hình được xác định trong hàm tạo của lớp Magento \ Backend \ Model \ Url . Bạn cho tôi thực hiện phụ thuộc được cấu hình đó . "

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.