プログラムでエンティティフォームを生成するにはどうすればよいですか?


7

プログラムでカスタムエンティティのエンティティフォームを生成する必要があります。基本的に、呼び出し時に発生するのと同じ出力を取得します

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

私のエンティティフォームでそれをやろうとすると、エラーが発生します

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

本当に進む方法に本当に困惑しました。


ここに私が使用しているコードの難読化されたバージョンがあります

エンティティの定義:

/**
 * 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 {

フォームの名前空間

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 {

さて、これは私がこれまでに見つけたものです。ユーザーoknateの回答は部分的に機能します。また、次のようなコールバックエラーを回避するために、ダミーの関数をコンテナーフォームクラスに追加する必要がありました。

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

これはおそらくこれを行う正しい方法ではありませんが、別のフォームでレンダリングされるフォームオブジェクトが作成されます。


1
ドキュメントによると、引数はフォームIDまたはフォームを実装するクラスでなければなりません。そのフォームはFormInterfaceを実装する必要があります。api.drupal.org/api/drupal/...
ケビン・

1
例 \ Drupal :: formBuilder()-> getForm(Drupal \ mymodule \ Form \ FormName)
Kevin


1
はい、私が言ったように私はそれを試しました。
elstevenson 2016

1
私のフォームは、あなたが言ったように、FormEntityFormを拡張するBaseFromInterfaceを拡張するEntityFormInterfaceを拡張するContentEntityFormInterfaceを実装するContentEntityFormクラスから拡張します。
elstevenson 2016

回答:


12

エンティティフォームビルダーサービスを使用できます。この方法でユーザーフォームを読み込むことができました($ entityが現在のユーザーです)。

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

ユーザー登録フォーム(基本的にはエンティティが保存されていないエンティティフォーム)を取得する場合は、エンティティクラスでcreateメソッドを使用してから、フォームに渡すことができます。

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

1
さて、この答えは私に最も近くなった。実行しようとすると、ページが読み込まれますが、エンティティフォームを挿入しようとしているフォームクラスに「processForm」メソッドがないという警告が表示されます。
elstevenson 2016

1
'processForm'関数は\ Drupal \ Core \ Entity \ EntityFormクラスにあるようです。
elstevenson 2016

1
関数が受け取る引数の1つ($ element)を返すだけなので、コンテナーフォームクラスにその関数のダミーバージョンを作成しました。その後、エンティティフォームはレンダリングされます。私はその呼び出しをバイパスすることの結果が何であるかはわかりません。
elstevenson 2016

1
@oknate、コードに感謝します。完璧に機能しますが、ajax操作用に#after_buildメソッドをアタッチしたいと思います。#after_buildメソッドが起動/呼び出ししていない、この状況に遭遇しましたか?または誰かが#after_buildメソッドをアタッチするソリューションを持っています
allabakash.g

1
フォームを保持するためにビルド配列を使用していて、フォームを適切にレンダリングするテンプレートを使用している場合は、正しく機能するはずです。ajaxが読み込まれないという問題がある場合は、フォームを事前にレンダリングしていて、テンプレートにキャッシュされているため、後続のページの読み込み時にJavaScriptを追加するように適切に通知されていません。
oknate 2017年

5

エンティティフォームはエンティティなしでは機能しません。空のフォームが必要な場合は、新しく作成されたエンティティインスタンスを使用します。この例はノードエンティティから使用できます。

/**
   * 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;
  }

エンティティフォームビルダーは、コントローラーの基本クラスに挿入されます。したがって、通常はコントローラを使用してエンティティフォームを作成します。

ノードを作成するとき、エンティティフォームが構築されるバンドル(コンテンツタイプ)を定義する必要があります。エンティティにバンドルがない場合は、空の配列を使用できます。


コメント

コメントはエンティティフィールドに添付されるため、さらに作業が必要です。

ノードのコメントフィールドのフォームを作成する方法の例:

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

または、注入されたサービスのないコントローラの外の同じ:

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

フォームを変更して#after_buildを追加した場合は、共有していただきありがとうございます。#after_buildメソッドが機能していません。何か解決策はありますか?
allabakash.g 2017年

3

明確にするために、以下のコードはDrupal 8.2.xで機能します。

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

1
コードを試したところ、最初は機能しませんでしたが、 'Drupal \ user \ Form \ UserLoginForm :: class'の前に\を追加すると機能しました。私のカスタムクラスでそれをやろうとしたとき、私は同じエラーを得ましたが。私の質問をエンティティ定義で更新しようとしました-私の推測では、コードを機能させるために実装する必要があるものを実装していません。
elstevenson 2016

1
さて、最後に、使用したサンプルフォームがエンティティフォームではなく、FormBaseから拡張されていることに気付きました。エンティティフォーム(具体的にはContentEntityFormから拡張されたコンテンツエンティティ)をレンダリングする必要があります
elstevenson

1
はい、私のユースケースではこれは間違っています。
elstevenson 2016
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.