简体   繁体   English

Symfony2 + Propel Collection未定义偏移量:2

[英]Symfony2 + Propel Collection undefined offset: 2

We have created a collection using propel and Symfony2 forms. 我们使用propel和Symfony2表单创建了一个集合。 We can save the form without any problems and we can add a second option using the collection. 我们可以毫无问题地保存表单,并且可以使用集合添加第二个选项。 If we then save and then try to add a 3rd collection in we get the following error: 如果然后保存然后尝试添加第三个集合,则会出现以下错误:

Notice: Undefined offset: 2 

Stack Trace 堆栈跟踪

in src/app/MyBundle/Model/om/BaseLabelsLabelsLinesMapsQuery.php at line 241  

$cton0 = $this->getNewCriterion(LabelsLabelsLinesMapsPeer::ID, $key[0], Criteria::EQUAL);
            $cton1 = $this->getNewCriterion(LabelsLabelsLinesMapsPeer::LABEL_ID, $key[1], Criteria::EQUAL);
            $cton0->addAnd($cton1);
            $cton2 = $this->getNewCriterion(LabelsLabelsLinesMapsPeer::LABEL_LINES_ID, $key[2], Criteria::EQUAL);
            $cton0->addAnd($cton2);
            $this->addOr($cton0);
        }

I have posted the relevant code below, however as there is quiet a substantial amount of code. 我已经在下面发布了相关的代码,但是由于有大量的代码安静了下来。 We were wondering if anybody had experienced this same issue. 我们想知道是否有人遇到过同样的问题。

I have sent a bug report over with a different bit of code which created the same error however I received no reply. 我已经用不同的代码发送了一个错误报告,该错误创建了相同的错误,但是我没有收到任何回复。 The bug report is here . 错误报告在这里

This is a snippet of the relevant schema: 这是相关架构的片段:

<table name="labels_labels_lines_maps" isCrossRef="true">
    <column name="id"
            type="integer"
            required="true"
            autoIncrement="true"
            primaryKey="true"/>
    <column name="label_id"
            type="integer"
            primaryKey="true"/>
    <column name="label_lines_id"
            type="integer"
            primaryKey="true"/>
    <foreign-key foreignTable="labels" onDelete="cascade">
        <reference local="label_id" foreign="id"/>
    </foreign-key>
    <foreign-key foreignTable="labels_lines" onDelete="cascade">
        <reference local="label_lines_id" foreign="id"/>
    </foreign-key>
    <vendor type="mysql">
        <parameter name="Engine" value="InnoDB" />
        <parameter name="Charset" value="utf8" />
    </vendor>
</table>

<table name="labels_lines">
    <column name="id"
            type="integer"
            required="true"
            autoIncrement="true"
            primaryKey="true"/>
    <column name="placeholder_text"
            type="varchar"
            size="150"/>
    <column name="font_id"
            type="integer"/>
    <column name="font_size"
            type="integer"/> 
    <column name="x_axis"
            type="integer"/>  
    <column name="y_axis"
            type="integer"/>
    <column name="width"
            type="integer"/>      
    <column name="height"
            type="integer"/>       
    <column name="colour"
            type="varchar"
            size="20"/>        
    <column name="angle"
            type="integer"/> 
    <column name="is_volume"
            type="boolean"/>
    <column name="is_percentage"
            type="boolean"/>
    <column name="is_productof"
            type="boolean"/>
    <column name="is_type"
            type="boolean"/>
    <column name="is_occasion"
            type="boolean"/>        
    <foreign-key foreignTable="font" onDelete="cascade">
        <reference local="font_id" foreign="id"/>
    </foreign-key>
    <vendor type="mysql">
        <parameter name="Engine" value="InnoDB" />
        <parameter name="Charset" value="utf8" />
    </vendor>
</table>

<table name="occasion">
    <column name="id"
            type="integer"
            required="true"
            autoIncrement="true"
            primaryKey="true"/>
    <column name="occasion"
            type="varchar"
            size="200"/>

    <vendor type="mysql">
        <parameter name="Engine" value="InnoDB" />
        <parameter name="Charset" value="utf8" />
    </vendor>
</table>

<table name="font">
    <column name="id"
            type="integer"
            required="true"
            autoIncrement="true"
            primaryKey="true"/>
    <column name="name"
            type="varchar"
            size="100"/>
    <column name="location"
            size="300"/>
    <vendor type="mysql">
        <parameter name="Engine" value="InnoDB" />
        <parameter name="Charset" value="utf8" />
    </vendor>
</table>

Below is the view (without any styling): 下面是视图(没有任何样式):

{{ form_start(form) }}
{{ form_row(form._token) }}
<ul class="labelsliness list-group" data-prototype="{{ form_widget(form.labelsliness.vars.prototype)|e }}">
                    {% for lines in form.labelsliness %}
                        <li>{{ form(lines) }}</li>
                    {% endfor %}
                </ul>

                {{ form_row(form.save) }}

{{ form_end(form) }}

<script>
                    var $collectionHolder;

                    var $addLinesLink = $('<button class="add_line_link btn btn-primary">Add a line</button>');
                    var $newLinkLi = $('<li></li>').append($addLinesLink);

                    $(document).ready(function(){
                       $collectionHolder = $('ul.labelsliness');

                       $collectionHolder.append($newLinkLi);

                       $collectionHolder.data('index', $collectionHolder.find(':input').length);

                       $addLinesLink.on('click', function(e) {
                          e.preventDefault();

                          addLineForm($collectionHolder, $newLinkLi);
                       });
                    });

                    function addLineForm($collectionHolder, $newLinkLi) {
                        var prototype = $collectionHolder.data('prototype');

                        var index = $collectionHolder.data('index');

                        var newForm = prototype.replace('/__name__/g', index);

                        $collectionHolder.data('index', index + 1);

                        var $newFormLi = $('<li></li>').append(newForm);

                        $newFormLi.append('<button class="remove-line btn btn-danger">Remove</button>');

                        $newLinkLi.before($newFormLi);

                        $('.remove-line').click(function(e){
                           e.preventDefault();

                           $(this).parent().remove();

                           return false;
                        });
                    }
                </script>

The Form handling this: 表单处理此:

public function buildForm(FormBuilderInterface $builder, array $options)
    {
       $builder
               ->add("labelsliness", "collection", array(
                   "type" => new LabelsLinesType(),
                   "allow_add" => true,
                   "allow_delete" => true,
                   "by_reference" => false
               ))
               ->add("save", "submit");
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AJSharp\EPCBundle\Model\Labels',
        ));
    }

    public function getName()
    {
        return "label_form";
    }

Finally, below is the controller. 最后,下面是控制器。

public function editAction(Request $request, $id = null)
    {

        $labels = LabelsQuery::create()->findPk($id);

        $form = $this->createForm(new EditLabelType(), $labels);

        $form->handleRequest($request);

        if ($form->isValid()) {

            $labels->save();
            return $this->redirect($this->generateUrl("_admin_labels"));
        }

        return $this->render("AppLabelBundle:Admin:edit.html.twig", array("form" => $form->createView()));
    }

Your schema is a little confusing to me. 您的架构对我有些困惑。 This bit below includes three primary keys with two of them as a foreign key and one of them as a unique identifier for the row: 下面的这一位包括三个主键,其中两个作为外键,其中一个作为该行的唯一标识符:

<table name="labels_labels_lines_maps" isCrossRef="true">
    <column name="id"
            type="integer"
            required="true"
            autoIncrement="true"
            primaryKey="true"/>
    <column name="label_id"
            type="integer"
            primaryKey="true"/>
    <column name="label_lines_id"
            type="integer"
            primaryKey="true"/>
    <foreign-key foreignTable="labels" onDelete="cascade">
        <reference local="label_id" foreign="id"/>
    </foreign-key>
    <foreign-key foreignTable="labels_lines" onDelete="cascade">
        <reference local="label_lines_id" foreign="id"/>
    </foreign-key>
    <vendor type="mysql">
        <parameter name="Engine" value="InnoDB" />
        <parameter name="Charset" value="utf8" />
    </vendor>
</table>

I suspect a lot of your trouble may go away if you pick one thing and stick with it. 我怀疑如果您选择一件东西并坚持下去,那么您的很多麻烦都会消失。 Either remove id and have your primary composite key represent two foreign tables, which is perfectly valid, or change your PRIMARY KEY s to UNIQUE constraints on each of your foreign keys, leaving your primary key as id . 要么删除id并让您的主组合键代表两个完全有效的PRIMARY KEY ,要么将您的PRIMARY KEY更改为每个外键上的UNIQUE约束,而将主键保留为id This is also perfectly valid. 这也是完全有效的。 Ultimately your decision will be based on your design requirements. 最终,您的决定将基于您的设计要求。

Another note: You may or may not want to do a heavyIndexing , particularly if you're referencing individual columns in the primary key. 另一个注意事项:您可能会或可能不想执行heavyIndexing ,尤其是在引用主键中的各个列时。 A composite primary key creates an index against all three columns, not each individually. 复合主键针对所有三列创建索引,而不是分别针对每个列。 That may or may not be important in your project but I thought it would be worth pointing out. 这在您的项目中可能重要,也可能不重要,但我认为值得指出。

I'm not 100% sure on this, but I'm fairly certain it is because this line: 我不太确定这一点,但我可以肯定是因为这条线:

$labels = LabelsQuery::create()->findPk($id);

You'll notice in the method findPkSimple in your BaseQuery class it is expecting that the variable key be an array with 3 values (indices 0, 1, 2) 您会在BaseQuery类的findPkSimple方法中注意到,期望变量键是一个具有3个值(索引0、1、2)的数组。

The reason why I'm unsure is I don't know if $id is just one value or an array as the function definition you have doesn't restrict on type. 我不确定的原因是我不知道$ id是一个值还是一个数组,因为您拥有的函数定义不受类型的限制。 (your editAction function) (您的editAction函数)

I think, because you have three primary keys, the class that gets generated expects you to have three individual values when searching by primary key. 我认为,因为您有三个主键,所以生成的类期望在通过主键进行搜索时具有三个单独的值。

It might be more effective if you only have one primary key, and then an unique index on those three columns to ensure uniqueness (if that's what you're going for) 如果您只有一个主键,然后在这三列上具有唯一索引以确保唯一性,则可能会更有效(如果您要这样做)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM