symfonyはちょうど正しくPATCH-ペイロードを準備し、箱から出して、これを処理します:)
symfonyのCheckboxTypeは、少なくとも現在のバージョン3.3(2.3以降、以下の更新を参照のように思える)で、入力を受け付けますnull
の値で、「チェックされていない」と解釈されます(スニペットの3〜5行目のRoubi's really helpful answerにあります)。
クライアントサイドのAJAX-PATCH-controllerでは、application/merge-patch+json
ペイロードのチェックされていないチェックボックスフィールドの値をnull
に設定していますが、すべて問題ありません。 CheckboxTypeの動作を上書きするフォーム拡張はまったく必要ありません。
問題:HTTP-POSTペイロードの値をnull
に設定できないため、リクエスト本体内のJSON(またはその他の互換性のある)ペイロードでのみ動作します。Content-Type: application/merge-patch+json
またはこの場合にも、有効なJSONペイロード、下記の意志とPATCH-要求の場合
/**
* @Route("/test/patch.json", name="test_patch")
* @Method({"PATCH"})
*/
public function patchAction(\Symfony\Component\HttpFoundation\Request $request)
{
$form = $this->createFormBuilder(['checkbox' => true, 'dummyfield' => 'presetvalue'], ['csrf_protection' => false])
->setAction($this->generateUrl($request->get('_route')))
->setMethod('PATCH')
->add('checkbox', \Symfony\Component\Form\Extension\Core\Type\CheckboxType::class)
->add('dummyfield', \Symfony\Component\Form\Extension\Core\Type\TextType::class)
->getForm()
;
$form->submit(json_decode($request->getContent(), true), false);
return new \Symfony\Component\HttpFoundation\JsonResponse($form->getData());
}
:
これを実証するために簡単なデモ
、あなたはこの単純化されたテストコントローラを使用することができます起こる:
がnull
値でチェックボックスを提出
{"checkbox": null}
falseにあるチェックボックスを上書きします:
{"checkbox": false, "dummyfield": "presetvalue"}
と(前もそうでした)trueにするチェックボックスを設定します
{"checkbox": "1"}
元の値であるチェックボックスを提出
{"checkbox": true, "dummyfield": "presetvalue"}
を
と提出されたチェックボックスの値なし
{"dummyfield": "requestvalue"}
は、その初期の真の状態のチェックボックスを残すのみdummyfieldを上書きします:
{"checkbox": true, "dummyfield": "requestvalue"}
これは、PATCH要求は余分な隠し入力が必要で、動作してはならない方法です。クライアントサイドでJSONペイロードを適切に準備するだけで、うまくいきます。
OKですが、拡張ChoiceType/EntityTypeはどうですか?
チェックボックスやラジオボタンをレンダリングし、送信されたペイロード内のチェックされたチェックボックス/ラジオボタンの値の単純なリストを期待する、拡張されたChoiceType(EntityTypeのような子タイプ)の場合、この単純な解決法は機能しません。フォーム拡張を実装し、PRE_SUBMITのイベントリスナをこれらのフィールドに追加し、送信されなかったチェックボックス/ラジオボタンをnullに設定しました。このイベントリスナーはCheckboxTypeのクロージャーリスナーの後に呼び出さなければならず、単純リスト["1", "3"]
をチェックボックスの値をキーと値として持つハッシュに転送します。私には-1
の優先度があります。だから、閉鎖から出てくる["1" => "1", "3" => "3"]
は私のリスナーの後に["1" => "1", "2" => null, "3" => "3"]
になる。
$builder->addEventListener(
\Symfony\Component\Form\FormEvents::PRE_SUBMIT,
function (\Symfony\Component\Form\FormEvent $event) {
if ('PATCH' === $event->getForm()->getRoot()->getConfig()->getMethod()
&& $event->getForm()->getConfig()->getOption('expanded', false)
) {
$data = $event->getData();
foreach ($event->getForm()->all() as $type) {
if (!array_key_exists($type->getName(), $data)) {
$data[$type->getName()] = null;
}
}
ksort($data);
$event->setData($data);
}
}, -1
);
更新:/Symfony/Component/Form/Form.phpで提出し、メソッド内でこのコメントを見ている(それはsymfonyの2.3以降があります):私のPatchableChoiceTypeExtension
のリスナーは、基本的にはこのようになります
// Treat false as NULL to support binding false to checkboxes.
// Don't convert NULL to a string here in order to determine later
// whether an empty value has been submitted or whether no value has
// been submitted at all. This is important for processing checkboxes
// and radio buttons with empty values.
アップデート2017-09-12:ラジオグループは、チェックボックスグループと同じ方法で処理する必要があります。そのため、リスナーは両方を処理します。選択して複数選択すると、すぐに使用できるようになります。
$ builder-> resetViewTransformers()でデータトランスフォーマをリセットできます。次に、独自のDataTransformerを追加します。 – Falc
@Falc Excellent!それはまさに私が必要なものです! – Roubi
良い解決策!私はこの動作を 'accept_null_on_patch'フォームフィールドオプションで簡単に設定できるように' CheckboxType'を拡張した 'PatchableCheckboxTypeExtension'の中でこれを実装しました。 trueに設定すると、すべてのViewTransformerが削除され、代わりに 'PatchableCheckboxBooleanToStringTransformer'が追加されます。 – spackmat