I am running a Symfony2 application for a client that tracks AEDs (defibrillators), their maintenance records, and persons responsible for their maintenance. I'm in a beta launch and have run into an issue with a one-to-many bidirectional relationship achieved with Doctrine.
The project was a conversion from a previous schema on a custom-developed framework. This means I used
The relationship structure is a "top-down approach" where the AEDs are organized by the following:
Municipalities
one-to-many-> Organizations
one-to-many-> Locations
one-to-many-> AEDs
one-to-many-> Monthly Check Logs
one-to-many-> Maintenance Records
one-to-many-> Persons
one-to-many-> Contact Entries
(This is simplified but should give you enough context for the problem I'm having.)
I am showing a "User Profile" where all of their associated contact entries are listed in a table. The problem is when a new entry is added, only (the newest) one shows up in the table. The others are still stored in the database but hidden for some reason.
The desired
I cloned the production database into my staging environment and replicated the problem.
I tried forcing the fetch mode to EAGER
and still had the same problem.
I checked the length of person.contacts
and it outputted a value of 1.
I tried taking the runnable eager query directly into the database (as follows) and had a result of multiple entries (greater than 1):
SELECT
t0.table_id AS table_id1,
t0.ref_id AS ref_id2,
t0.person_id AS person_id3,
t0.contact_type AS contact_type4,
t0.contact_place AS contact_place5,
t0.contact AS contact6,
t0.contact_id AS contact_id7,
t0.person_id AS person_id8
FROM
supContact t0
WHERE
t0.person_id = 1490
I'm not sure how to proceed with debugging from here. The desired functionality is to have multiple entries show up of course.
public function showAction($personId = 0, $organizationId = 0)
{
$person = $this->getDoctrine()
->getRepository('AEDTracker:Genperson')
->find($personId);
return $this->render('AEDTracker:Personnel:show.html.twig', array(
'person' => $person,
'organizationId' => $organizationId,
));
}
{% if person.contacts is empty %}
<tr><td colspan="100">No entries</td></tr>
{% else %}
{% for item in person.contacts %}
<tr class="contact_edit" module="contact" name="{{ item.contactId }}">
<td></td>
<td>{{ item.contactType }}</td>
<td>{{ item.contactPlace }}</td>
<td>{{ item.contact }}</td>
<td><a href="{{ path('personnelEditContact', { 'contactId': item.contactId, 'organizationId': organizationId }) }}">Edit</a></td>
</tr>
{% endfor %}
{% endif %}
<?xml version="1.0" encoding="utf-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="AED\Tracker\Entity\Genperson" table="genPerson">
<id name="personId" type="integer" column="person_id">
<generator strategy="IDENTITY"/>
</id>
<!-- Skipped unimportant fields -->
<one-to-many field="contacts" target-entity="Supcontact" mapped-by="person" fetch="EAGER" />
</entity>
</doctrine-mapping>
<?xml version="1.0" encoding="utf-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="AED\Tracker\Entity\Supcontact" table="supContact">
<id name="contactId" type="integer" column="contact_id">
<generator strategy="IDENTITY"/>
</id>
<field name="personId" type="integer" column="person_id" nullable="true" />
<!-- Removed unimportant fields -->
<many-to-one field="person" target-entity="Genperson" inversed-by="contacts">
<join-column name="person_id" referenced-column-name="person_id" />
<cascade>
<cascade-persist />
<cascade-merge />
</cascade>
</many-to-one>
</entity>
</doctrine-mapping>
Any help would be greatly appreciated.
Like a silly person, I didn't try something obvious for this fix.
There must be a bug between Symfony 2.3 and 2.4, because updating fixed this issue entirely.
For those that may ever stumble on this, to update you must download the new composer.json
file located here into the root folder of the project, then run
php composer.phar update
All dependencies will be updated, including the Symfony core and Doctrine library. Make sure you test before pushing this to your production environment.
However, oddly enough I had to keep the fetch="EAGER"
parameter in my ORM XML files to keep the functionality working. This may not be a complete solution and someone else may have some further insight. Ideally I'd like the application to continue using lazy loading.