0

EDIT: Breakdown

Two or more time is recorded to one day.
There are Date Entity and Time Entity.
Date Entity oneToMany: Time Entity.
Time Entity manyToOne: Date Entity.

step1

The field of form is added by javascript.

step2

So far, so good. It does work all right.

The problem is that a category is registered with time.

step3

$form  = $this->createForm(new DateType(), new Date());

Structure now looks like this.

DateFormType collection with TimeFormType  
    TimeFormType collection with CategoryFormType  
    TimeFormType collection with SubCategoryFormType

Category Entity    oneToMany: Time Entity.  
SubCategory Entity oneToMany: Time Entity.  
Time Entity        manyToOne: Category Entity.  
Time Entity        manyToOne: SubCategory Entity.  

The bind of form is occurred error at controller, if this condition.

$form->bind($request); // => Error: Category, array given 
Catchable Fatal Error: Argument 1 passed to ...\Entity\Time::setCategory() must be an instance of ...\Entity\Category, array given

Can "Category" by which relation was carried out be collected by "manyToOne"?
Is how to use "collection of forms" wrong?

The details are as follows.


I want to achieve what is recording time day by day.
Two or more time is recorded to one day.
The field of form is added by javascript.
An outline is the following although it is difficult to explain that it does not become long.

Entities:

Date, Category, SubCategory, Time

Date.orm

Date:
    oneToMany:
        times:
            targetEntity: Time
            mappedBy: date
            cascade: ["persist", "remove"]

Time.orm

Time:
    // ...
    manyToOne:
        date:
            targetEntity: Date
            inversedBy: times
            joinColumn:
                name: date_id
                referencedColumnName: id
        category:
            targetEntity: Category
            inversedBy: times
            joinColumn:
                name: category_id
                referencedColumnName: id
        sub_category:
            targetEntity: SubCategory
            inversedBy: times
            joinColumn:
                name: sub_id
                referencedColumnName: id

Category.orm

Category:
    // ...
    oneToMany:
        times:
            targetEntity: Time
            mappedBy: categoy
            cascade: ["persist", "remove"]

    manyToMany:
        subs:
          targetEntity: SubCategory
          inversedBy: main
          joinTable:
            name: main_and_sub
            joinColumns:
                joinColum:
                    name: main_id
                    referencedColumnName: id
                    onDelete: CASCADE
            inverseJoinColumns:
                joinColum:
                    name: sub_id
                    referencedColumnName: id
                    onDelete: CASCADE

SubCategory.orm

SubCategory:
    // ...
    oneToMany:
        times:
            targetEntity: Time
            mappedBy: sub_category
            cascade: ["persist", "remove"]

    manyToMany:
        main:
            targetEntity: Category
            mappedBy: subs

TimeType

// ...
$builder->add('category', 'collection', array(
    'type' => new CategoryType(),
    'options' => array(
        'required'  => true,
    ),
    'allow_add'      => true,
    'by_reference'   => false,
    'allow_delete'   => true,
    'prototype'      => true,
    'prototype_name' => '__cat_prot__'
));
$builder->add('subcategory', 'collection', array(
    'type' => new SubCategoryType(),
    'options' => array(
        'required'  => false,
    ),
    'allow_add'      => true,
    'by_reference'   => false,
    'allow_delete'   => true,
    'prototype'      => true,
    'prototype_name' => '__cat_prot__'
));
$builder->add('time', 'time', array(
    'input'  => 'datetime',
    'widget' => 'choice',
));

DateType

// ...
$builder->add('date', 'date', array(
    'input'  => 'datetime',
    'widget' => 'choice',
));
$builder->add('times', 'collection', array(
    'type' => new TimeType(),
    'options' => array(
        'required'  => true,
    ),
    'allow_add'      => true,
    'by_reference'   => false,
    'allow_delete'   => true,
    'prototype'      => true,
    'prototype_name' => '__times_prot__'
));

View:

{{ form_widget(form.date) }}

<ul id="TIMES" data-prototype="
    <div>
        {{ form_widget(form.times.vars.prototype.children['category'].vars.prototype.name) | e }}
        <label>Category 1</label>
    </div>
    <div>
        {{ form_widget(form.times.vars.prototype.children['subcategory'].vars.prototype.name) | e }}
        <label>Category 2</label>
    </div>
    <div>
        {{ form_widget(form.times.vars.prototype.time) | e }}
    </div>
    <input type='button' value='Remove' class='remove' />">
</ul>
<input type="button" value="add times" class="add-form-field" />

javascript

var nums = 0;

$(document).on('click', '.add-form-field', function(e){
    var field  = $("#TIMES"),
        data   = field.attr("data-prototype"),
        widget = data.replace(/__cat_prot__/g, 0).replace(/__times_prot__/g, nums),
        newLi  = $('<li></li>').html(widget);
        newLi.appendTo("#TIMES");

    nums += 1;

    return false;
});

$(document).on('click', '#TIMES .remove', function(){
    $(this).parent().remove();
});

Controller:

$_date = new Date();
$form  = $this->createForm(new DateType(), $_date);

if ($request->getMethod() == 'POST') {
    $form->bind($request);  // => Error: Category, array given

$form->bind($request); // => Error: Category, array given

Catchable Fatal Error: Argument 1 passed to ...\Entity\Time::setCategory() must be an instance of ...\Entity\Category, array given

If in this condition, "$form->bind($request)" has a error "Category, array given".

Isn't it well-designed?
Is it better not to use form builder?

The date has times.
A time has a category and a sub category.
A time has to have a category.
A time has not to have a sub category. (not must, nullable)

form data

date[date][day]

date[times][0][category][0][name]
date[times][0][subcategory][0][name]
date[times][0][time][hour]
date[times][0][time][minute]

date[times][1][category][0][name]
date[times][1][subcategory][0][name]
date[times][1][time][hour]
date[times][1][time][minute]

I think "date[times][0][category][0][name]" is have to be as "date[times][0][category][name]".
I think the way of consolidation of the form is wrong.

4

0 回答 0