2015-10-13 3 views
8

Мы создали коллекцию с использованием форм Propel и Symfony2. Мы можем сохранить форму без каких-либо проблем, и мы можем добавить второй вариант с помощью коллекции. Если мы затем сохранить, а затем попытаться добавить 3-ю коллекцию мы получим следующее сообщение об ошибке:Symfony2 + Propel Collection undefined offset: 2

Notice: Undefined offset: 2 

трассировки стека

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); 
     } 

Я отправил соответствующий код ниже, однако, поскольку есть тихий существенный количество кода. Нам было интересно, если кто-то испытал эту же проблему.

Я отправил отчет об ошибке с другим кодом, который создал ту же ошибку, однако я не получил ответа. Отчет об ошибке - here.

Это фрагмент соответствующей схеме:

<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> 

Ниже вид (без укладки):

{{ 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> 

Форма, обрабатывающая это:

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"; 
    } 

Наконец, ниже находится контроллер.

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())); 
    } 
+0

и ваш код 'BaseLabelsLabelsLinesMapsQuery.php'? – Alex

+0

@Alex, поскольку в скрипте есть несколько строк, которые я скопировал в pastebin. http://pastebin.com/WXgfN7yf. Обратите внимание, что этот код полностью генерируется Propel. –

ответ

1

Ваша схема немного запутанным меня. Этот бит ниже включает в себя три основных ключа с двумя из них в качестве внешнего ключа, и один из них в качестве уникального идентификатора для строки:

<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> 

Я подозреваю вас много неприятностей может уйти, если вы выбираете одну вещь и придерживаться. Либо удалите id, и ваш основной составной ключ отобразит две внешние таблицы, что совершенно верно, или измените ваши PRIMARY KEY s на UNIQUE ограничения на каждый из ваших внешних ключей, оставив ваш первичный ключ как id. Это также отлично.В конечном итоге ваше решение будет основываться на ваших требованиях к дизайну.

Другое примечание. Вы можете или не хотите делать heavyIndexing, особенно если вы ссылаетесь на отдельные столбцы в первичном ключе. Комбинированный первичный ключ создает индекс для всех трех столбцов, не каждый отдельно. Это может быть или не быть важным в вашем проекте, но я подумал, что стоит отметить.

+0

Привет, спасибо за упоминание heavyIndexing. Я на самом деле никогда не использовал его, поэтому я посмотрю на это. Сначала я собирался по следующей схеме (propelorm.org/documentation/cookbook/symfony2/mastering-symfony2-forms-with-propel.html#many-to-many-relations) Однако, как вы уже указали. Идентификатор на самом деле не во многих схемах. Я полагаю, что это может быть основной причиной проблемы. Я посмотрю и вернусь к вам. –

0

Я не 100% уверен в этом, но я абсолютно уверен, что это потому, что этой линии:

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

Вы замечаете в методе findPkSimple в классе BaseQuery это ожидая, что переменным ключом будет массив с 3 значениями (индексы 0, 1, 2)

Причина, по которой я не уверен, я не знаю, является ли $ id только одним значением или массивом в качестве определения функции у вас нет ограничений по типу. (ваша функция editAction)

Думаю, потому что у вас есть три первичных ключа, класс, который генерируется, ожидает, что вы будете иметь три отдельных значения при поиске по первичному ключу.

Это могло бы быть более эффективным, если у вас есть только один первичный ключ, а затем уникальный индекс на этих трех столбцов, чтобы обеспечить уникальность (если это то, что вы собираетесь)

+0

Просто пояснить, что $ id - это один идентификатор, а не массив. Что касается наличия одного первичного ключа. Я взял здесь следующее (propelorm.org/documentation/cookbook/symfony2/mastering-symfony2-forms-with-propel.html#many-to-many-relations), который показывает несколько первичных ключей. Однако id на самом деле не на этой карте в этом примере. –

+0

Я думаю, что этот пример может быть либо устаревшим, либо просто совершенно неправильным. В их примере у них есть первичный ключ, который также является внешним ключом. – William