Điểm:1

Trả lại một Đóng cửa từ một Nhà máy

lá cờ cn

Tôi có các dịch vụ phụ thuộc vào thông tin yêu cầu. Tôi đang cố gắng tạo một nhà máy nhà máy sẽ có bộ chứa Dependency Injection trả về một nhà máy (một chức năng ẩn danh) sẽ tạo ra các dịch vụ mà tôi muốn. Vì vậy, về cơ bản một cái gì đó như thế này:

lớp FooFactoryFactory {
  chức năng tĩnh công khai tạo (ContainerInterface $ container): có thể gọi được {
     trả về hàm tĩnh (Yêu cầu $request) sử dụng ($container) {
       $raz = request->get('param_raz');
       trả lại Thanh mới (
           $container->get(LoggerInterface::class),
           $raz,
       );
     };
  }

}

Vấn đề tôi có là Khép kín được tạo đúng cách, nhưng lớp Bộ chứa tiêm phụ thuộc của de Drupal cố gắng đặt thuộc tính cho Khép kín. Điều này không thể hoạt động và kết thúc bằng một lỗi nghiêm trọng:

Đối tượng đóng cửa không thể có thuộc tính

Đây là nơi nó xảy ra:

// Drupal\Component\DependencyInjection\Container::createService() - Dòng 283-293
if (isset($definition['properties'])) {
  if ($definition['properties'] instanceof \stdClass) {
    $definition['properties'] = $this->resolveServicesAndParameters($definition['properties']);
  }
  foreach ($definition['properties'] as $key => $value) {
     $service->{$key} = $value; // <- Sẽ không hoạt động khi Đóng
  }
}
...

Vì vậy, những câu hỏi tôi có:

  • Đây có phải là do thiết kế? Có nghĩa là nó là thứ gì đó không được mong muốn trong thực hành mã hóa?
  • Có thể tránh được lỗi nếu tôi quản lý để đảm bảo rằng dịch vụ tôi muốn tạo không có tính chất nó là định nghĩa. Tôi chỉ không biết làm thế nào để đạt được điều này.

Cảm ơn sự giúp đỡ về vấn đề này.

CHỈNH SỬA: Về cơ bản, đây là những gì tôi đang cố gắng đạt được:


  đóng cửa.factory.service:
    lớp: Drupal\some_module\ClosureFactoryService
  đóng cửa.dịch vụ:
    lớp: Đóng cửa
    nhà máy: [ '@closure.factory.service', getCallable ]
lớp ClosureFactoryService {
  hàm công khai getCallable (): Đóng {
    trả về hàm tĩnh (int $arg): string {
      quay lại sprintf('val %d', $arg);
    };
  }
}

Tôi có: Đối tượng đóng cửa không thể có các thuộc tính trong Drupal\Component\DependencyInjection\Container->createService() (dòng 288...

4uk4 avatar
lá cờ cn
Nếu dịch vụ của bạn phụ thuộc vào thông tin yêu cầu thì hãy thêm `@request_stack` Để hiểu thiết kế của bạn, bạn có thể cung cấp toàn bộ mã, cụ thể là lớp Bar và định nghĩa dịch vụ gây ra lỗi không. Tại sao bạn sử dụng phương pháp nhà máy cụ thể này? Bạn có thể cung cấp thêm ngữ cảnh không?
lá cờ cn
Tôi vừa chỉnh sửa câu hỏi thành Có mã gốc như trong `Drupal\Component\DependencyInjection\Container.php`. @4k4: đó là khá nhiều trong ví dụ. Các dịch vụ tôi muốn cần phải có các phụ thuộc được kéo từ vùng chứa và phụ thuộc vào vùng chứa. Đó có phải là một cái gì đó không được phép thực hiện theo cách đó?
apaderno avatar
lá cờ us
Trong Drupal, các dịch vụ được xác định trong tệp .services.yml, đây là thứ mà @4k4 yêu cầu xem. Ngoài ra, một dịch vụ được xác định trong tệp đó không triển khai bất kỳ phương thức `create()` nào. Phương thức tiêm phụ thuộc được sử dụng bởi Drupal, đó là phương thức tiêm phụ thuộc Symfony, mong muốn `create()` trả về một thể hiện của lớp đó, không phải là một bao đóng.
lá cờ cn
Xin chào @apaderno, cảm ơn vì đã trả lời. Tôi đã không đề cập đến phần khai báo dịch vụ trong các tệp `*.yml` bởi vì đó không phải là nơi tôi gặp sự cố. Thách thức mà tôi gặp phải là trả về một hàm (nhà máy) ẩn danh từ lớp sau của Drupal `Drupal\Component\DependencyInjection\Container.php`.Tôi đã đăng đoạn mã trong lớp đó khiến nó không thành công. `Closure` được tạo đúng cách trong lớp Drupal đã đề cập nhưng các dòng tiếp theo làm cho `Container.php` gây ra lỗi. Tôi sẽ kiểm tra việc triển khai vùng chứa của Symfony.
apaderno avatar
lá cờ us
Thông tin đó là cần thiết; ít nhất, cần phải hiểu liệu lớp đó có dành cho dịch vụ được xác định trong tệp .services.yml của mô-đun hay không. Bằng cách này, câu trả lời có thể hữu ích hơn.
Điểm:4
lá cờ us

Trong Drupal, lớp cho một dịch vụ được xác định trong tệp .services.yml của mô-đun không cần triển khai tạo (ContainerInterface $container). Nó thậm chí không được yêu cầu triển khai một giao diện PHP cụ thể.

Xem một trong các dịch vụ mà Drupal triển khai, ví dụ: path_alias.manager dịch vụ.

path_alias.manager:
  lớp: Drupal\path_alias\AliasManager
  tranh luận:
   - '@path_alias.repository'
   - '@path_alias.whitelist'
   - '@language_manager'
   - '@cache.data'

Các Trình quản lý bí danh lớp thực hiện dịch vụ đó không thực hiện bất kỳ tạo ra() phương pháp; nó chỉ thực hiện người xây dựng, với các tham số được xác định theo thứ tự giống như các đối số dịch vụ được liệt kê.

chức năng công khai __construct($alias_repository, AliasWhitelistInterface $whitelist, LanguageManagerInterface $language_manager, CacheBackendInterface $cache) {
  $this->pathAliasRepository = $alias_repository;
  $this->languageManager = $language_manager;
  $this->whitelist = $whitelist;
  $this->cache = $cache;
}

Các lớp thực hiện tạo (ContainerInterface $container) và cái nào thực hiện ChứaTiêmGiao Diện, ví dụ như CronForm lớp, không trả lại một đóng cửa từ tạo (ContainerInterface $container); họ thực sự chỉ trả lại một phiên bản của chính họ. Nhìn thấy CronForm::tạo().

tạo hàm tĩnh công khai (ContainerInterface $container) {
  trả lại tĩnh mới ($ container-> get ('config.factory'),
    $container->get('trạng thái'),
    $container->get('cron'),
    $container->get('date.formatter'),
    $container->get('module_handler')
  );
}

Nếu bạn muốn triển khai dịch vụ nhà máy trong Drupal, bạn nên thực hiện cache_factory service làm ví dụ để viết mã của bạn.

cache_factory:
  lớp: Drupal\Core\Cache\CacheFactory
  tranh luận:
    - '@cài đặt'
    - '%cache_default_bin_backends%'
  cuộc gọi:
    - [setContainer, ['@service_container']]

Ví dụ, một dịch vụ sử dụng dịch vụ đó làm nhà máy là cache.render dịch vụ.

bộ nhớ cache.render:
  lớp: Drupal\Core\Cache\CacheBackendInterface
  thẻ:
    - {tên: cache.bin}
  nhà máy:
    - '@cache_factory'
    - được
  tranh luận:
    - kết xuất

Các nhà máy khóa xác định dịch vụ nào là dịch vụ của nhà máy và phương thức nào được gọi cho dịch vụ của nhà máy đó; các tranh luận key xác định các đối số được truyền cho phương thức đó. Trong trường hợp này, nó yêu cầu Drupal khởi tạo cache.render dịch vụ bằng cách khởi tạo cache_factory dịch vụ và gọi nhận ('kết xuất') trên đối tượng đó.

lá cờ cn
Cảm ơn các câu trả lời chi tiết. Tôi đã chỉnh sửa câu hỏi của mình để hình dung những gì tôi đang cố gắng đạt được. Tôi nghĩ điều đó là không thể với Drupal Container hiện tại. Hoặc tôi đang ồ ạt làm điều gì đó sai trái.
Jaypan avatar
lá cờ de
Bạn chưa cung cấp trường hợp sử dụng của những gì bạn đang cố gắng thực hiện (hoặc vấn đề bạn đang cố gắng khắc phục/tránh), chỉ những vấn đề bạn đang gặp phải khi cố gắng thực hiện nó. Tôi nghi ngờ rằng bạn đang sử dụng trải nghiệm PHP trước đây của mình và cố gắng áp dụng nó để thực hiện điều gì đó được xử lý theo cách khác bằng cách sử dụng khung công tác Drupal. Có lẽ bạn có thể giải thích thêm về trường hợp sử dụng của mình, thay vì cách triển khai của bạn. Mặt khác, thật khó để nói nếu bạn đang làm "sai" (hay còn gọi là - theo cách không phải Drupally) hay không.
apaderno avatar
lá cờ us
@Jaypan Tôi cho rằng dickwan chỉ đơn giản là quen với cách DI hoạt động với các thư viện/khung công tác khác nhau.Ví dụ: trong PHP-DI hoàn toàn ổn khi triển khai một nhà máy dịch vụ với đối tượng `Closure` (hoặc bất kỳ đối tượng có thể gọi nào), nhưng điều tương tự không hợp lệ trong Drupal.
apaderno avatar
lá cờ us
@dickwan Như bạn đã biết, Drupal hy vọng nó có thể thêm các thuộc tính vào đối tượng được trả về cho một dịch vụ. Vì các đối tượng `Close` không thể có các thuộc tính nên chúng không thể được sử dụng. Những gì tôi đã mô tả trong câu trả lời là cách Drupal triển khai dịch vụ và nhà máy dịch vụ. Hãy nhớ rằng các phiên bản của một lớp triển khai [`__invoke()`](https://www.php.net/manual/en/lingu.oop5.magic.php#object.invoke) là các đối tượng có thể gọi được, đối với PHP và chúng có thể có các thuộc tính, đó là điều mà Drupal mong đợi. Nếu `$callable` là một trong những đối tượng đó, thì `$result = $callable();` là mã hoàn toàn hợp lệ.
lá cờ cn
@apaderno: Cảm ơn. Tôi thực sự hơi ngạc nhiên khi cách tiếp cận mà tôi muốn thực hiện lại không hiệu quả. Tôi nghĩ rằng tôi đang tìm kiếm lý do cho hành vi cụ thể của công việc khung này. Vì vậy, tôi cho rằng Framework đang hoạt động như mong đợi và có thể không thể tạo dịch vụ mà không có thuộc tính
apaderno avatar
lá cờ us
@dickwan Drupal sử dụng các thành phần Symfony, nhưng nó không hoạt động giống như Symfony trong mọi trường hợp.Biết rằng Drupal sử dụng Symfony có thể giúp hiểu cách thức hoạt động của Drupal, nhưng vẫn cần phải xem mã Drupal để hiểu Drupal hoàn toàn.

Đăng câu trả lời

Hầu hết mọi người không hiểu rằng việc đặt nhiều câu hỏi sẽ mở ra cơ hội học hỏi và cải thiện mối quan hệ giữa các cá nhân. Ví dụ, trong các nghiên cứu của Alison, mặc dù mọi người có thể nhớ chính xác có bao nhiêu câu hỏi đã được đặt ra trong các cuộc trò chuyện của họ, nhưng họ không trực giác nhận ra mối liên hệ giữa câu hỏi và sự yêu thích. Qua bốn nghiên cứu, trong đó những người tham gia tự tham gia vào các cuộc trò chuyện hoặc đọc bản ghi lại các cuộc trò chuyện của người khác, mọi người có xu hướng không nhận ra rằng việc đặt câu hỏi sẽ ảnh hưởng—hoặc đã ảnh hưởng—mức độ thân thiện giữa những người đối thoại.