Drupal 8から始めたところ、すぐに最初の問題が発生しました。
Drupal 8)の既存のフォームをどのように変更すればよいですか?
他のページにリダイレクトするには、ノードフォームのsaveメソッドを変更する必要があります。ノードフォームを変更して、マルチステップフォームのようなものにしたいと考えています。ユーザーが新しいコンテンツを作成すると、新しいフォーム(私たちが作成したもの)にリダイレクトされ、さらに情報を取得します。
hook_entity_type_alter()
の実装に関する問題を解決しました。
function mymodule_entity_type_alter(&$entity_info) {
$handlers = $entity_info['node']->get('handlers');
$handlers['form']['default'] = 'Drupal\mymodule\Form\MyExtendedNodeForm';
$handlers['form']['edit'] = 'Drupal\mymodule\Form\MyExtendedNodeForm';
$entity_info['node']->set('handlers', $handlers);
}
次に、ノードフォームを拡張し、saveメソッドを変更する新しいフォームクラスを作成しました。
class MyExtendedNodeForm extends NodeForm {
public function save(array $form, FormStateInterface $form_state) {
parent::save($form, $form_state);
$node = $this->entity;
$form_state->setRedirect('entity.regions.add_form', ['nid' => $node->id()]);
}
}
これは完全に機能しますが、それで良いのでしょうか?別のモジュールが同じことを行う場合、コードは実行されなくなります。
私は昨日まったく同じことをしなければならなかった、そして私はまだこれを行うためのより多くのDrupal 8方法を探していますが、それを見つけられませんでした。私はこのようにしてしまいました:
<?php
/**
* @file
* This is my module.
*/
use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\HttpFoundation\Request;
/**
* Implements hook_form_alter().
*/
function MODULE_form_alter(array &$form, FormStateInterface $form_state, $form_id) {
if ($form_id == 'user_form') {
$form['actions']['submit']['#submit'][] = '_MODULE_goto';
}
}
/**
* Make the form go to route.id.
*/
function _MODULE_goto($form, FormStateInterface $form_state) {
$form_state->setRedirect('route.id');
}
私はそれを別の方法で行うことに非常に興味があります。私のモジュールは.moduleファイルなしではとてもきれいに見えました:)。
Drupal 8.1.1を使用しており、ユーザーがアカウントを変更した後、つまり/ user/editページの[保存]ボタンをクリックした後に、ユーザーをリダイレクトしようとしました。最初にこれを試しました:
/**
* Implements hook_form_alter().
*/
function MODULE_form_alter(array &$form, FormStateInterface $form_state, $form_id) {
if ($form_id == 'user_form') {
$form['#submit'][] = '_MODULE_goto';
}
}
user_login_form
、それはuser_form
。ために user_form
使用しなければなりませんでした
$form['actions']['submit']['#submit'][] = '_MODULE_goto';
私が同じ問題に出くわした他の人を助けることを願っています!
さて、いくつかのフィールドを追加するためにsite_information_settings
フォームを変更したいと思いました。
あなたとして、私はどちらかを選択しました
hook_form_alter
(またはhook_form_FORM_ID_alter
)OOPを作成したかったので、system.site_information_settings
ルートの_form
属性を変更するルートサブスクライバーサービスの作成を開始しました。
次に、SiteInformationForm
を拡張する新しいクラスで、フィールドとそのバリデーターが追加され、送信関数が拡張された後、私はあなたとまったく同じように感じました... 別のモジュールが独自のクラスを使用するためのフォームのルート?
最初に戻ると、2つのオプションから選択できました...間違ったオプションを選択したようです。
hook_form_alter
/hook_form_FORM_ID_alter
は、既存のフォームを変更する最良の方法のようです。
KernelEvents :: REQUESTイベントをリッスンする新しいEventSubscriberを作成し、 this のようなノードフォームを送信するときに反応することができます。
とにかく、hook_form_alterの方法は問題なく動作します。
それはあなたがやりたいことのように見えます、それは実際にsaveメソッドを変更するのではなく、ノードが保存されるときにリダイレクトを変更することです。
この状況では、Drupal 7、hook_form_alter
カスタム送信ハンドラ(フォームまたは要件に応じて、フォームまたはボタン上)と一緒に使用することをお勧めします。
質問であなたが説明することも機能しますが、実際にクラスの何かを変更したいのでない限り、基本クラスを上書きしないようにします。
いずれにしても、saveメソッドは送信ハンドラーとして使用されるだけなので、リダイレクトを追加するためだけに上書きしても意味がありません。
私は、form_alterファミリーのフックの1つを使用し、送信ハンドラを接続し、その中にリダイレクトを設定する方が良い方法だと思います。
これを行うために基本クラスを拡張するContribは、私の意見では毛深いです。特に、機能が変更されていないため、リダイレクトするだけです。
これまでに見つけたもの:フォーム変更フックを実装し、フォーム変更フック自体の検証/送信ハンドラーを変更しようとすると、$ form ['#validate]/$ form [#submit']ハンドラーを変更した場合にのみ機能します。 (このためのform_state関数の呼び出しは、フォームの変更フック自体では機能しません)
しかし、これを検証ハンドラ内で試すと、うまくいく傾向があります。
// Load form submit handlers.
$submit_handlers = $form_state->getSubmitHandlers();
// Drop the core entity submitForm function.
$key_core_submit = array_search('::submitForm', $submit_handlers);
if ($key_core_submit !== FALSE) {
unset($submit_handlers[$key_core_submit]);
// Add your own submit handler.
array_unshift($submit_handlers, 'yourmodule_submit_handler');
}
// Update submit handlers.
$form_state->setSubmitHandlers($submit_handlers);
これは、フォームが完全に構築されたためであり、フォームの変更フック自体の場合ではありません。
アイデアは、検証ハンドラーを最後のハンドラーとして追加し、送信用に存在する他のハンドラーを評価して、そこですぐに変更できるというものです。
検証ハンドラーも変更する場合は、他のものよりも先に実行することを確認し、検証ハンドラーで必要なものを変更します。
私自身より良い方法を探していますが、ユーザー登録フォームの検証/送信ハンドラを常に置き換える必要があります。しかし、私のモジュールの実装を壊す他のモジュールが存在する可能性があります。したがって、私のモジュールはこれらをチェックできる必要があり、それはこの方法で可能です。ビルド機能の後にあるエンティティフォームがこれを実現するために存在するのだろうか。 (フォームが完成して配信されようとしているときに実行されるもの)(これは、この単純なケースでは複雑にする方法ではありません)
Save()メソッドのリダイレクトをバイパスすることはできませんが、save()の設定を解除するには、この方法を使用します(独自の方法を実装します)。確かに、クラスの方が優れており、オブジェクトなどに簡単にアクセスできますが、コアクラスをオーバーライドすると、他のモジュールがこれらを使用するときに問題が発生します。このコードを使用する場合はそうではありません。
この問題を確認した後、これがあなたのケースに合うはずです:
/**
* Implements hook_entity_type_alter().
*/
function mymodule_entity_type_alter(&$entity_info) {
$entity_info['node']->setFormClass('edit','Drupal\mymodule\Form\CustomNodeForm');
}