私は現在、SonataAdminBundle、1 対多の関係、およびファイルのアップロードで課題に直面しています。と呼ばれるエンティティとClient
と呼ばれるエンティティがありExchangeFile
ます。1 つClient
は複数ExchangeFile
の を持つことができるため、ここでは 1 対多の関係があります。ファイルのアップロードにはVichUploaderBundleを使用しています。
これはClient
クラスです:
/**
* @ORM\Table(name="client")
* @ORM\Entity()
* @ORM\HasLifecycleCallbacks
*/
class Client extends BaseUser
{
// SNIP
/**
* @ORM\OneToMany(targetEntity="ExchangeFile", mappedBy="client", orphanRemoval=true, cascade={"persist", "remove"})
*/
protected $exchangeFiles;
// SNIP
}
これはExchangeFile
クラスです:
/**
* @ORM\Table(name="exchange_file")
* @ORM\Entity
* @Vich\Uploadable
*/
class ExchangeFile
{
// SNIP
/**
* @Assert\File(
* maxSize="20M"
* )
* @Vich\UploadableField(mapping="exchange_file", fileNameProperty="fileName")
*/
protected $file;
/**
* @ORM\Column(name="file_name", type="string", nullable=true)
*/
protected $fileName;
/**
* @ORM\ManyToOne(targetEntity="Client", inversedBy="exchangeFiles")
* @ORM\JoinColumn(name="client_id", referencedColumnName="id")
*/
protected $client;
// SNIP
}
私のClientAdmin
クラスではexchangeFiles
、次の方法でフィールドを追加しました。
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
// SNIP
->with('Files')
->add('exchangeFiles', 'sonata_type_collection', array('by_reference' => false), array(
'edit' => 'inline',
'inline' => 'table',
))
// SNIP
}
これにより、クライアント編集フォームでさまざまな交換ファイルをインライン編集できます。そして、これまでのところうまくいきます: .
問題
しかし、注意点が 1 つあります。緑の「+」記号を 1 回押して (新しい交換ファイル フォーム行を追加)、ファイルシステム内のファイルを選択してから、もう一度「+」記号を押します(新しいフォーム行が Ajax 経由で追加されます)。 )、別のファイルを選択し、[更新] (現在のクライアントを保存) をクリックすると、最初のファイルは保持されません。2 番目のファイルのみがデータベースとファイル システムで見つかります。
私が知る限り、これには次の理由があります: 緑色の「+」記号が 2 回目にクリックされると、現在フォームにあるデータ (クライアントとすべての交換ファイル) を含む現在のフォームが Web サーバーにポストされます。 )。新しいフォームが作成され、リクエストがフォームにバインドされます (これは にあるAdminHelper
クラスで行われますSonata\AdminBundle\Admin
)。
public function appendFormFieldElement(AdminInterface $admin, $subject, $elementId)
{
// retrieve the subject
$formBuilder = $admin->getFormBuilder();
$form = $formBuilder->getForm();
$form->setData($subject);
$form->bind($admin->getRequest()); // <-- here
// SNIP
}
したがって、フォーム全体がバインドされ、フォーム行が追加され、フォームがブラウザーに送り返され、フォーム全体が新しいフォームで上書きされます。ただし、<input type="file" />
セキュリティ上の理由からファイル入力 ( ) を事前設定できないため、最初のファイルは失われます。VichUploaderBundle
ファイルは、エンティティが永続化されている場合にのみファイルシステムに保存されます (これには Doctrine を使用していると思いますprePersist
) が、フォーム フィールド行が追加された場合はまだ発生しません。
私の最初の質問は次のとおりです。この問題をどのように解決できますか、またはどの方向に進むべきですか? 次の使用例を機能させたいと思います: 新しいクライアントを作成したいのですが、3 つのファイルをアップロードすることがわかっています。「新しいクライアント」をクリックし、クライアント データを入力し、緑色の「+」ボタンを 1 回押して、最初のファイルを選択します。次に、「+」記号をもう一度押して、2 番目のファイルを選択します。3 番目のファイルについても同様です。3 つのファイルはすべて永続化する必要があります。
2 番目の質問: 1 対多の関係で 1 つのフォーム行のみを追加したいのに、Sonata Admin がフォーム全体を投稿するのはなぜですか? これは本当に必要ですか?これは、ファイル入力がある場合、新しいフォーム行が追加されるたびに、フォームに存在するすべてのファイルがアップロードされることを意味します。
よろしくお願いします。詳細が必要な場合は、お知らせください。