as far as I understand I need to add a "cascade" parameter to the mapping. But my mapping is in XML.
I found quite a bit of information about it but there was no result.
Pleace help!
Мy error is:
Multiple non-persisted new entities were found through the given association graph:\n\n * A new entity was found through the relationship 'Domain\Maintenance\Maintenance#affectedRegions' that was not configured to cascade persist operations for entity: Domain\AffectedRegion\AffectedRegion#0000000075384ba200000000535ab7f1. To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist this association in the mapping for example #ManyToOne(..,cascade={"persist"}). If you cannot find out which entity causes the problem implement 'Domain\AffectedRegion\AffectedRegion#__toString()' to get a clue.\n *
XML fails:
<entity name="Domain\Maintenance\Maintenance" table="maintenances" repository-class="Infrastructure\Repositories\MaintenanceRepository">
<id name="id" type="integer" column="id">
<generator strategy="AUTO"/>
</id>
<field name="name" type="string"/>
<one-to-many field="affectedRegions" target-entity="Domain\AffectedRegion\AffectedRegion" mapped-by="Domain\Maintenance\Maintenance" />
<cascade>
<cascade-merge/>
</cascade>
</entity>
<entity name="Domain\AffectedRegion\AffectedRegion" table="affected_regions" repository-class="Infrastructure\Repositories\AffectedRegionRepository">
<id name="id" type="integer" column="id">
<generator strategy="AUTO"/>
</id>
<many-to-one field="region" target-entity="Domain\Region\Region" inversed-by="Domain\AffectedRegion\AffectedRegion">
<join-column name="region_id" referenced-column-name="id" />
<cascade>
<cascade-persist/>
</cascade>
</many-to-one>
<many-to-one field="maintenance" target-entity="Domain\Maintenance\Maintenance" inversed-by="Domain\AffectedRegion\AffectedRegion">
<join-column name="maintenance_id" referenced-column-name="id" />
<cascade>
<cascade-persist/>
</cascade>
</many-to-one>
<field name="vlans" type="string"/>
<field name="olts" type="string"/>
</entity>
<entity name="Domain\Region\Region" table="regions" repository-class="Infrastructure\Repositories\RegionRepository">
<id name="id" type="integer" column="id">
<generator strategy="AUTO"/>
</id>
<field name="name" type="string"/>
<field name="code" type="string"/>
<one-to-many field="affectedRegions" target-entity="Domain\AffectedRegion\AffectedRegion" mapped-by="Domain\Maintenance\Maintenance" />
</entity>
this is my FK:
$affectedRegionTable->addForeignKeyConstraint(
$regionTable,
['region_id'],
['id'],
['onUpdate' => 'CASCADE'],
'fk_affectedRegions_region_id'
);
$affectedRegionTable->addForeignKeyConstraint(
$regionTable,
['maintenance_id'],
['id'],
['onUpdate' => 'CASCADE'],
'fk_affectedRegions_maintenance_id'
);
the relation I want to make is:
Maintenance ← one-to-many → AffectedRegions ← many-to-one → Region
Here is the answer.
Another way to add a cascade argument:
<one-to-many field="affectedRegions" target-entity="Domain\AffectedRegion\AffectedRegion" mapped-by="maintenance">
<cascade>
<cascade-persist/>
<cascade-remove/>
</cascade>
</one-to-many>
Related
I start to model the db/entities in symfony2.
I have two entities. First is a User and second is a Groups.
I want to connect both. I think I should use many to many relations(?).
But my major problem is how can I get list of all groups with information if user joined this group.
Group Entity:
<?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="GroupBundle\Entity\Group">
<id name="id" type="integer" column="id">
<generator strategy="AUTO"/>
</id>
<field name="name" type="string" column="name" length="50"/>
<field name="description" type="string" column="description"/>
<many-to-many field="users" mapped-by="groups" target-entity="AccountBundle\Entity\User"/>
</entity>
</doctrine-mapping>
and User Entity:
<?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="AccountBundle\Entity\User">
<id name="id" type="integer" column="id">
<generator strategy="AUTO"/>
</id>
<field name="username" type="string" column="username" length="255"/>
<field name="password" type="string" column="password" length="255"/>
<field name="salt" type="string" column="salt" length="255"/>
<field name="email" type="string" column="email" length="255"/>
<field name="active" type="boolean" column="active"></field>
<field name="token" type="string" column="token" length="255"/>
<field name="lastLoginTime" type="datetime" column="lastLoginTime" nullable="true"/>
<field name="registerTime" type="datetime" column="registerTime"/>
<one-to-many field="events" target-entity="CoreBundle\Entity\Event" mapped-by="user" />
<many-to-many field="groups" inversed-by="users" target-entity="GroupBundle\Entity\Group">
<join-table name="UserGroups">
<join-columns>
<join-column name="userId" referenced-column-name="id" />
</join-columns>
<inverse-join-columns>
<join-column name="groupId" referenced-column-name="id" />
</inverse-join-columns>
</join-table>
</many-to-many>
</entity>
</doctrine-mapping>
There is no relation between there yet because I don't know what is best.
Maybe I must create additional Entity between like UserGroup?
D4V1D you have a right. Assumption is: User can join to many group and group can have a many user.
Okey I add the many-to-many relations. I hope I did it right.
And now. This is fragment of my controller:
$em = $this->getDoctrine()->getManager();
$repo = $em->getRepository("GroupBundle\Entity\Group");
$groups = $repo->findAll();
$user = $this->getUser();
$user_groups = $user->getGroups();
foreach($user_groups as $user_group){
/* #var $group Group */
foreach($groups as $group){
if($group->getId() == $user_group->getId()){
$group->setUserInGroup(true); // of course i extend my entity file about extra set and get method.
}
}
}
return $this->render('GroupBundle:showAll.html.twig', array('groups' => $groups));
and view:
{% for group in groups %}
<div>
{{ group.name }}
{% if(group.getUserInGroup()) %}
join
{% endif %}
</div>
{% endfor %}
I try find the best and right method to do this.
Without relation OneToMany with user and group, how do you join the group with user? which field have this information? you need a relation yes.
Group entity :
<many-to-many field="users" target-entity="AccountBundle\Entity\User" mapped-by="groups" />
User entity :
<many-to-many field="groups" target-entity="GroupBundle\Entity\Group" inversed-by="users"/>
i have Banner and Group entities with xml configs
Banner.xml
<mapped-superclass name="Banner" table="luc_banners"
repository-class="BannerRepository">
<id name="id" column="id" type="integer">
<generator strategy="AUTO" />
</id>
<field name="path" column="path" type="string" nullable="true" />
<field name="link" column="link" type="string" nullable="true" />
<field name="position" column="position" type="string" nullable="true" />
<field name="groupId" column="group_id" type="integer" />
<many-to-one field="group" target-entity="Group" inversed-by="banners">
<join-column name="group_id" referenced-column-name="id" nullable="false" on-delete="CASCADE" />
</many-to-one>
</mapped-superclass>
Group.xml
<mapped-superclass name="Group" table="luc_banners_groups" repository-class="GroupRepository">
<id name="id" column="id" type="integer">
<generator strategy="AUTO" />
</id>
<field name="name" column="group_name" type="string" nullable="true" />
<field name="type" column="group_type" type="string" nullable="true" />
<field name="status" column="group_status" type="string" nullable="true" />
<field name="order" column="group_order" type="integer" nullable="true" />
<one-to-many field="banners" target-entity="Banners" mapped-by="group">
<cascade>
<cascade-all />
</cascade>
</one-to-many>
</mapped-superclass>
when trying to get banners form group object i get empty array, and Profiler shows this sql SELECT l0_.group_name AS group_name0, l0_.id AS id4 FROM luc_banners_groups l0_ WHERE l0_.group_status = ? and show not valid entity with this error Banner - The association Banner#group refers to the inverse side field Group#banners which does not exist.
Can you help me with this thing ?
remove <field name="groupId" column="group_id" type="integer" /> from Banner.xml, I think it's overriding the second one..
I work with symfony2 and there i use doctrine. As Example i have a simple repository-class in my doctrine xml-file:
<?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="AllgemeinBundle\Entity\ObjektPosition" table="objekt_position" repository-class="AllgemeinBundle\Repository\ObjektPositionRepository">
<indexes>
<index name="id_objekt_subunternehmer_position_fk2_idx" columns="id_subunternehmer"/>
<index name="id_objekt_objektposition_idx" columns="id_objekt"/>
</indexes>
<id name="id" type="integer" column="id">
<generator strategy="IDENTITY"/>
</id>
<field name="artikelnummer" type="integer" column="artikelnummer" nullable="false"/>
<field name="preisProEinheit" type="float" column="preis_pro_einheit" precision="10" scale="2" nullable="false"/>
<field name="p1Einheit" type="float" column="p1_einheit" precision="10" scale="2" nullable="false"/>
<field name="p2Einheit" type="float" column="p2_einheit" precision="10" scale="2" nullable="true"/>
<field name="p3Einheit" type="float" column="p3_einheit" precision="10" scale="2" nullable="true"/>
<field name="zusatztext" type="text" column="zusatztext" nullable="true"/>
<field name="position" type="integer" column="position" nullable="false"/>
<many-to-one field="idSubunternehmer" target-entity="Subunternehmer">
<join-columns>
<join-column name="id_subunternehmer" referenced-column-name="subunternehmernummer"/>
</join-columns>
</many-to-one>
<many-to-one field="idObjekt" target-entity="Objekt">
<join-columns>
<join-column name="id_objekt" referenced-column-name="id"/>
</join-columns>
</many-to-one>
when i am generating my entities from the database, then the repository-class would be deleted. Also some other thinks i added to the xml-file.
Is it able to save the customized data in a sperated folder or file, so that i can generate the entities as often as i like and the customized data wouldn't be lost?
If you are using console commands, when generating entities don't mention '--no-backup' at the end of the command. So, you will be able to preserve your entity class. However you entity class will be renamed with adding '~' sign at the start of the file name. Your entity generation code will be like this, (without trailing --no-backup)
php app/console doctrine:generate:entities
Hope this helps,
Cheers!
I have a Service (product), which has many Inventories. When user logs in, let's say he is assigned to only one Location. That is why I have to filter array collection, so the user can not edit inventories from other locations. Number of inventories is usually small. I have a ServiceType form which has a collection type, where inventories can be edited, added and removed.
The problem is.. I have set up an entity listener for only the Service entity, and after loading it from the database, the postLoad method is executed, which saves the filtered inventories to the array collection. On the form type, I see only the filtered ones, as expected, also editing works, and when I add a new item to the collection, it also works. When I hit the delete button on collection item, and submit the form, the removeInventory() method is called and item is removed from collection. But then when I persist Service, doctrine does not generate DELETE query and 'deleted' inventories are not deleted from the database. When I visit the form again, the items are still on the list. However, everything (also delete) works, if I do not use postLoad method.
Commenting this line
$service->setInventory($inventory->matching($criteria));
fixes the not deleting problem, but ofcourse I get all items, not only filtered ones.
Inventory 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="Service\Bundle\RepairBundle\Entity\Inventory" table="inventory">
<indexes>
<index name="fk_inventory_location1_idx" columns="location_id"/>
<index name="fk_inventory_service1_idx" columns="service_id"/>
</indexes>
<entity-listeners>
<entity-listener class="Service\Bundle\RepairBundle\Entity\Listener\InventoryListener">
<lifecycle-callback type="prePersist" method="prePersistHandler"/>
</entity-listener>
</entity-listeners>
<id name="id" type="integer" column="id">
<generator strategy="IDENTITY"/>
</id>
<field name="quantity" type="integer" column="quantity" nullable="false"/>
<field name="stock" type="integer" column="stock" nullable="false"/>
<many-to-one field="service" target-entity="Service\Bundle\RepairBundle\Entity\Service" inversed-by="inventory">
<join-columns>
<join-column name="service_id" referenced-column-name="id" nullable="false"/>
</join-columns>
</many-to-one>
<many-to-one field="location" target-entity="Service\Bundle\UserBundle\Entity\Location" inversed-by="inventory">
<join-columns>
<join-column name="location_id" referenced-column-name="id" nullable="false"/>
</join-columns>
</many-to-one>
</entity>
</doctrine-mapping>
And Service 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="Service\Bundle\RepairBundle\Entity\Service" table="service">
<indexes>
<index name="fk_service_account1_idx" columns="account_id"/>
</indexes>
<entity-listeners>
<entity-listener class="Service\Bundle\RepairBundle\Entity\Listener\ServiceListener">
<lifecycle-callback type="postLoad" method="postLoadHandler"/>
</entity-listener>
</entity-listeners>
<id name="id" type="integer" column="id">
<generator strategy="IDENTITY"/>
</id>
<field name="name" type="string" column="name" length="255" nullable="false"/>
<field name="description" type="text" column="description" nullable="true"/>
<field name="stockable" type="boolean" column="stockable" nullable="false"/>
<field name="value" type="decimal" column="value" precision="15" scale="4" nullable="false"/>
<field name="tax" type="decimal" column="tax" precision="5" scale="2" nullable="false"/>
<field name="unit" type="string" column="unit" length="63" nullable="false"/>
<one-to-many target-entity="Service\Bundle\RepairBundle\Entity\Inventory" mapped-by="service" field="inventory" fetch="LAZY" orphan-removal="true">
<cascade>
<cascade-persist/>
<cascade-remove/>
</cascade>
</one-to-many>
<one-to-many target-entity="Service\Bundle\RepairBundle\Entity\Price" mapped-by="service" field="priceList" fetch="LAZY" orphan-removal="true">
<cascade>
<cascade-persist/>
<cascade-remove/>
</cascade>
</one-to-many>
<many-to-one field="account" target-entity="Service\Bundle\UserBundle\Entity\Account">
<join-columns>
<join-column name="account_id" referenced-column-name="id" nullable="false"/>
</join-columns>
</many-to-one>
</entity>
</doctrine-mapping>
Service entity listener:
<?php
/**
* Created by PhpStorm.
* User: tomaz
* Date: 06/05/14
* Time: 15:33
*/
namespace Service\Bundle\RepairBundle\Entity\Listener;
use Doctrine\Common\Collections\Criteria;
use Doctrine\Common\Persistence\Event\LifecycleEventArgs;
use Service\Bundle\RepairBundle\Entity\Service;
use Service\Bundle\UserBundle\Entity\User;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Security\Core\SecurityContext;
class ServiceListener
{
protected $container;
/** Doctrine entity listeners should have container injection, because of lazy loading other services, to avoid circular references
* #param ContainerInterface $container
*/
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
public function postLoadHandler(Service $service, LifecycleEventArgs $event)
{
if($service instanceof Service) # Should always be true
{
$inventory = $service->getInventory();
if($this->getUser() instanceof User)
{
$criteria = Criteria::create()
->where(Criteria::expr()->eq('location', $this->getUser()->getPrimaryLocation()))
->orderBy(array('timeInsert' => Criteria::ASC));
$service->setInventory($inventory->matching($criteria));
}
}
}
/**
* #return User|null
*/
private function getUser()
{
return $this->container->get('security.context')->getToken()->getUser();
}
}
I'm trying to update my doctrine schema with the command:
php app/console doctrine:schema:update --force
I'm getting this error:
[Doctrine\DBAL\DBALException]
Unknown column type requested.
I'm getting this error since I've updated the xml mapping of the user entity in the Sonata UserBundle like this:
<?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="Application\Sonata\UserBundle\Entity\User" table="fos_user_user" repository-class="Application\Sonata\UserBundle\Repository\UserRepository">
<id name="id" column="id" type="integer">
<generator strategy="AUTO" />
</id>
<field name="name" type="string" length="50" />
<field name="birthdate" type="date" />
<field name="natRanking" type="string" length="10" />
<field name="interNatRanking" type="string" length="10" nullable="true" />
<field name="natDoublesRanking" type="string" length="10" />
<field name="interNatDoublesRanking" type="string" length="10" nullable="true" />
<field name="doublesPartner" type="string" length="50" nullable="true" />
<field name="nationality" type="string" length="50" />
<field name="fileName" type="string" length="255" nullable="true" />
<field name="path" type="string" length="255" nullable="true" />
<field name="file" />
<many-to-many field="teams" target-entity="Tennisconnect\DashboardBundle\Entity\Team" mapped-by="players">
<join-table name="team_user">
<join-columns>
<join-column name="team_id" referenced-column-name="id"/>
</join-columns>
<inverse-join-columns>
<join-column name="user_id" referenced-column-name="id"/>
</inverse-join-columns>
</join-table>
</many-to-many>
<one-to-many field="my_friends" target-entity="Friend" mapped-by="friends_of_mine" />
<one-to-many field="friended_me" target-entity="Friend" mapped-by="friends_with_me" />
</entity>
Is the type of the field "file" missing?