Làm thế nào để tôi lập trình tạo một biểu mẫu thực thể?


7

Tôi cần lập trình tạo biểu mẫu thực thể cho thực thể tùy chỉnh của mình - về cơ bản nhận được cùng một đầu ra xảy ra khi bạn gọi

\Drupal::formBuilder()->getForm('form namespace')

Khi tôi cố gắng làm điều đó với biểu mẫu thực thể của mình, tôi gặp lỗi :

Call to a member function getEntityTypeId() on null in Drupal\Core\Entity\EntityForm->getBaseFormId() (line 77 of core/lib/Drupal/Core/Entity/EntityForm.php).

Thực sự bối rối về cách tiến hành.


Đây là phiên bản mã bị xáo trộn mà tôi đang sử dụng

Định nghĩa thực thể:

/**
 * Defines the My Entity entity.
 *
 * @ingroup my_module
 *
 * @ContentEntityType(
 *   id = "my_entity",
 *   label = @Translation("My Entity"),
 *   handlers = {
 *     "view_builder" = "Drupal\Core\Entity\EntityViewBuilder",
 *     "list_builder" = "Drupal\my_module\MyEntityListBuilder",
 *     "views_data" = "Drupal\my_module\Entity\MyEntityViewsData",
 *     "translation" = "Drupal\my_module\MyEntityTranslationHandler",
 *
 *     "form" = {
 *       "default" = "Drupal\my_module\Form\MyEntityForm",
 *       "add" = "Drupal\my_module\Form\MyEntityForm",
 *       "edit" = "Drupal\my_module\Form\MyEntityForm",
 *       "delete" = "Drupal\my_module\Form\MyEntityDeleteForm",
 *     },
 *     "access" = "Drupal\my_module\MyEntityAccessControlHandler",
 *     "route_provider" = {
 *       "html" = "Drupal\my_module\MyEntityHtmlRouteProvider",
 *     },
 *   },
 *   base_table = "my_entity",
 *   data_table = "my_entity_field_data",
 *   translatable = TRUE,
 *   admin_permission = "administer as my_entity entities",
 *   entity_keys = {
 *     "id" = "id",
 *     "label" = "name",
 *     "uuid" = "uuid",
 *     "uid" = "user_id",
 *     "langcode" = "langcode",
 *     "status" = "status",
 *   },
 *   links = {
 *     "canonical" = "/admin/structure/my_entity/{my_entity}",
 *     "add-form" = "/admin/structure/my_entity/add",
 *     "edit-form" = "/admin/structure/my_entity/{my_entity}/edit",
 *     "delete-form" = "/admin/structure/my_entity/{my_entity}/delete",
 *     "collection" = "/admin/structure/my_entity",
 *   },
 *   field_ui_base_route = "my_entity.settings",
 *   constraints = {
 *     "CustomContraint" = {}
 *   }
 * )
 */
class MyEntity extends ContentEntityBase implements MyEntityInterface {

Không gian tên biểu mẫu

namespace Drupal\my_module\Form;

use Drupal\Core\Entity\ContentEntityForm;
use Drupal\Core\Form\FormStateInterface;

/**
 * Form controller for My Entity edit forms.
 *
 * @ingroup my_module
 */
class MyEntityForm extends ContentEntityForm {

Được rồi, đây là những gì tôi đã tìm thấy cho đến nay. Câu trả lời của người dùng oknate một phần hoạt động; Tôi cũng đã phải thêm một hàm giả vào lớp biểu mẫu container của mình để khắc phục lỗi gọi lại, trông giống như sau:

 public function processForm($element, FormStateInterface $form_state, $form)
  {
    return $element;
  }

Đây có lẽ không phải là cách đúng đắn để làm điều này, nhưng nó dẫn đến một đối tượng biểu mẫu sẽ kết xuất ở dạng khác.


1
Theo các tài liệu, đối số phải là ID biểu mẫu hoặc lớp thực hiện biểu mẫu. Hình thức đó phải thực hiện FormInterface. api.drupal.org/api/drupal/ cường
Kevin

1
Ví dụ. \ Drupal :: formBuilder () -> getForm (Drupal \ mymodule \ Form \ FormName)
Kevin


1
Vâng, như tôi đã nói tôi đã thử nó.
elstevenson

1
Biểu mẫu của tôi mở rộng từ lớp ContentEntityForm, thực hiện ContentEntityFormInterface, mở rộng EntityFormInterface, mở rộng BaseFromInterface, mở rộng FormInterface, như bạn đã nói.
elstevenson

Câu trả lời:


12

Bạn có thể sử dụng dịch vụ xây dựng biểu mẫu thực thể. Tôi đã có thể tải biểu mẫu người dùng theo cách này (với $ entity là người dùng hiện tại):

$entity = User::load($uid);
$user_form = \Drupal::service('entity.form_builder')->getForm($entity, 'default');

Nếu bạn muốn lấy biểu mẫu đăng ký người dùng (về cơ bản là biểu mẫu thực thể không có thực thể đã lưu), bạn chỉ có thể sử dụng phương thức tạo trên lớp thực thể của mình trước khi chuyển nó vào biểu mẫu:

$entity = User::create();
$user_form = \Drupal::service('entity.form_builder')->getForm($entity, 'default');

1
Được rồi, câu trả lời này đã đưa tôi gần nhất. Khi tôi thử thực hiện, trang sẽ tải, nhưng tất cả những gì hiển thị là một cảnh báo rằng lớp biểu mẫu tôi đang cố gắng đưa biểu mẫu thực thể vào không có phương thức 'processForm'.
elstevenson

1
Hàm 'processForm' dường như sống trong lớp \ Drupal \ Core \ Entity \ EntityForm.
elstevenson

1
Vì hàm chỉ trả về một trong các đối số mà nó nhận được (phần tử $), nên tôi đã tạo một phiên bản giả của hàm đó trong lớp biểu mẫu container của mình. Sau khi làm điều đó, biểu mẫu thực thể DOES kết xuất. Tôi không biết hậu quả của việc bỏ qua cuộc gọi đó là gì.
elstevenson

1
@oknate, Cảm ơn mã của bạn, nó hoạt động hoàn hảo, Nhưng, tôi muốn đính kèm phương thức #after_build cho các hoạt động ajax. Phương thức #after_build không kích hoạt / gọi điện, Bạn có gặp phải tình huống này không? hoặc bất cứ ai có giải pháp để đính kèm phương thức
#after_build

1
Nếu bạn đang sử dụng một mảng xây dựng để giữ biểu mẫu và bạn đang sử dụng một mẫu biểu hiện đúng biểu mẫu, thì nó sẽ hoạt động tốt. Nếu bạn gặp sự cố với ajax không tải, bạn có thể hiển thị trước biểu mẫu và sau đó nó sẽ được lưu trong bộ nhớ cache, nơi nó không có tín hiệu chính xác để thêm javascript vào các lần tải trang tiếp theo.
oknate

5

Các hình thức thực thể không hoạt động mà không có thực thể. Nếu bạn muốn một biểu mẫu trống thì hãy sử dụng một thực thể mới được tạo. Bạn có thể sử dụng ví dụ này từ thực thể nút:

/**
   * Provides the node submission form.
   *
   * @param \Drupal\node\NodeTypeInterface $node_type
   *   The node type entity for the node.
   *
   * @return array
   *   A node submission form.
   */
  public function add(NodeTypeInterface $node_type) {
    $node = $this->entityManager()->getStorage('node')->create(array(
      'type' => $node_type->id(),
    ));

    $form = $this->entityFormBuilder()->getForm($node);

    return $form;
  }

Trình xây dựng biểu mẫu thực thể được chèn vào lớp cơ sở của bộ điều khiển. Vì vậy, thông thường bạn sử dụng một bộ điều khiển để xây dựng các hình thức thực thể.

Khi tạo một nút, bạn cần xác định một gói (loại nội dung), theo đó mẫu thực thể sẽ được xây dựng. Nếu thực thể của bạn không có gói nào, bạn có thể sử dụng một mảng trống.


Bình luận

Nhận xét cần nhiều công việc hơn, bởi vì chúng được gắn vào một trường thực thể.

Ví dụ cách xây dựng biểu mẫu cho trường nhận xét của nút:

$comment = $this->entityTypeManager()->getStorage('comment')->create([
  'entity_type' => 'node',
  'entity_id' => $node->id(),
  'field_name' => 'comment',
]);
$build = $this->entityFormBuilder()->getForm($comment);

Hoặc tương tự bên ngoài bộ điều khiển mà không cần dịch vụ tiêm:

$comment = \Drupal::entityTypeManager()->getStorage('comment')->create([
  'entity_type' => 'node',
  'entity_id' => $node->id(),
  'field_name' => 'comment',
]);
$build = \Drupal::service('entity.form_builder')->getForm($comment);

Cảm ơn đã chia sẻ, nếu chúng tôi thay đổi biểu mẫu và thêm #after_build. Phương thức #after_build không hoạt động. Bạn có giải pháp nào không?
allabakash.g

3

Chỉ cần làm rõ, đoạn mã dưới đây hoạt động với tôi trong Drupal 8.2.x:

$form = \Drupal::formBuilder()->getForm(Drupal\user\Form\UserLoginForm::class);

1
Khi tôi thử mã của bạn, ban đầu nó không hoạt động, nhưng việc thêm \ ở phía trước 'Drupal \ user \ Form \ UserLoginForm :: class' đã khiến nó hoạt động. Khi tôi thử làm điều đó với lớp tùy chỉnh của mình, tôi cũng gặp lỗi tương tự. Tôi đã thử cập nhật câu hỏi của mình với định nghĩa thực thể của mình - tôi đoán là tôi đã không triển khai thứ gì đó mà tôi cần triển khai để mã của bạn hoạt động.
elstevenson

1
Được rồi, cuối cùng tôi nhận thấy rằng mẫu ví dụ bạn sử dụng không phải là một hình thức thực thể, nó chỉ mở rộng từ FormBase. Tôi cần hiển thị biểu mẫu thực thể (Cụ thể là thực thể nội dung, nội dung mở rộng từ ContentEntityForm)
elstevenson

1
Vâng, đối với trường hợp sử dụng của tôi, điều này là sai.
elstevenson
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.