Mapping Nested Tree With Doctrine 2 and YAML - doctrine-orm

We are currently working on implementing a nested tree using the DoctrineExtensions module. We believe we have wired everything up correctly, however when we go to flush using Doctrine, we keep getting an Exception.
SyntaxErrorException in AbstractMySQLDriver.php line 90: An exception
occurred while executing 'INSERT INTO ProductTree (left, right,
rootProductTreeID, level, componentProductComponentID) VALUES (?, ?, ?,
?, ?)':
You have an error in your SQL syntax; check the manual that corresponds
to your MySQL server version for the right syntax to use near 'left,
right, rootProductTreeID, level, componentProductComponentID) VALUES (?,
?' at line 1
The code we are using that is triggering this problem is
$productTree->setRootProductComponentID($productComponent->getID());
$productTree->setComponent($productComponent);
$em->persist($productTree);
$em->flush();
And our YAML mapping looks as so
OS\Domain\Entity\Products\ProductTree:
type: entity
repositoryClass: Gedmo\Tree\Entity\Repository\NestedTreeRepository
table: ProductTree
gedmo:
tree:
type: nested
indexes:
rootProductFK_idx:
columns:
- rootProductComponentID
componentProductFK_idx:
columns:
- componentProductComponentID
id:
id:
type: integer
nullable: false
options:
unsigned: false
id: true
generator:
strategy: IDENTITY
fields:
left:
type: integer
nullable: false
options:
unsigned: false
gedmo:
- treeLeft
right:
type: integer
nullable: false
options:
unsigned: false
gedmo:
- treeRight
rootProductTreeID:
type: integer
nullable: false
options:
unsigned: false
gedmo:
- treeRoot
level:
type: integer
gedmo:
- treeLevel
manyToOne:
# parent:
# targetEntity: OS\Domain\Entity\Products\ProductComponent
# inversedBy: children
# joinColumn:
# name: parentProductComponentID
# referencedColumnName: id
# onDelete: CASCADE
# gedmo:
# - treeParent
root:
targetEntity: OS\Domain\Entity\Products\ProductTree
cascade: { }
fetch: LAZY
mappedBy: null
inversedBy: null
joinColumns:
rootProductTreeID:
referencedColumnName: id
orphanRemoval: false
gedmo:
- treeParent
component:
targetEntity: OS\Domain\Entity\Products\ProductComponent
cascade: { }
fetch: LAZY
mappedBy: null
inversedBy: null
joinColumns:
componentProductComponentID:
referencedColumnName: id
orphanRemoval: false
oneToMany:
children:
targetEntity: OS\Domain\Entity\Products\ProductComponent
mappedBy: parent
orderBy:
left: ASC
lifecycleCallbacks: { }
Our configuration of Doctrine adds in the Tree Driver:
$metadataDriver = new MappingDriverChain();
$configuredDriver = $this->createMetadataDriver($doctrineConfig, $metadataConfig);
$treeDriver = $doctrineConfig->newDefaultAnnotationDriver(
'/vendor/gedmo/doctrine-extensions/lib/Gedmo/Tree/Entity'
);
$metadataDriver->addDriver($configuredDriver,'OS');
$metadataDriver->addDriver($treeDriver,'Gedmo');
DoctrineExtensions::registerAbstractMappingIntoDriverChainORM($metadataDriver);
and we register the tree listener before creating the Doctrine Entity Manager:
$eventManager->addEventSubscriber(new TreeListener());
return EntityManager::create(config('doctrine.connection'), $doctrineConfig, $eventManager);
We've been trying for hours to get this thing wired up, but it always fails on persistence and we can't find why. We've code traced through all the different elements, but we can't see where we are getting this error from. Any help would be much appreciated, or a sample of how we can wire up the Tree using YAML would also be welcome.

We found that in the Tree mapping file, we had to name the left: and right: columns as lft: and rgt:, identically to the examples on the github repository for the yaml mappings.
fields:
lft: <----
type: integer
nullable: false
options:
unsigned: false
gedmo:
- treeLeft
rgt: <-----
type: integer
nullable: false
options:
unsigned: false
gedmo:
- treeRight

Related

AppSync - unable to create a schema with an array when the array property has `#key` directive associated with it

I recently added a #key directive to a schema field so that I could search by that field, although I now get an error implying the previously correct data type is not what is expected. It says it expects a string but got a list, although the field is a list containing an enum.
Is it possible to query by a specific field without using #key? If not, how can I create records when the #key (seemingly) changes the expected type of a list to a string?
Below is my code, I added the #key to the categories list, but now when I try to create a new Journey I get the error shown below.
This is the schema:
type Journey #model
#auth(rules: [{ allow: owner, operations: [create, delete, update] }])
#key(name: "getJourneysByCategories", fields: ["categories"], queryField: "getJourneysByCategories")
#key(name: "getJourneysByName", fields: ["name"], queryField: "getJourneysByName") {
id: ID!
name: String!
description: String
coverImage: String
isPrivate: Boolean!
members: [JourneyUsersBridge] #connection(name: "JourneyUsers")
moderators: [JourneyModeratorsBridge] #connection(name: "ModeratedBy")
creator: User! #connection(name: "JourneyCreator")
goals: [Goal] #connection(name: "JourneyGoals")
posts: [Post] #connection(name: "JourneyPosts")
categories: [JourneyCategory!]!
}
This is an example of the code used to create a Journey:
type CreateJourneyInput = {
name: string;
description?: string | null;
coverImage?: string | null;
isPrivate: boolean;
categories: Array<JourneyCategory | null>;
journeyCreatorId: string;
};
const journey: CreateJourneyInput = {
name: 'My GraphQL Journey',
description: 'This Journey was made using GraphQL minus DataStore!',
isPrivate: false,
categories: [JourneyCategory.EXMAMPLE],
journeyCreatorId: userId
};
const result = await API.graphql(
graphqlOperation(mutations.createJourney, { input: journey })
);
This is the full error:
"One or more parameter values were invalid: Type mismatch for Index Key categories Expected: S Actual: L IndexName: getJourneysByCategories (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ValidationException; Request ID: U4EB7HPO1GU5LHVAOPMGAJJHANVV4KQNSO5AEMVJF66Q9ASUAAJG)"
So I removed the getJourneysByCategories key and the upload worked fine. What's happening here and why?
I just want to be able to query by categories - perhaps #key wasn't the right route to take? Does the key directive not work with lists?

Drupal 8 - How to enable custom field under manage form display programmatically?

I have created a drupal8 module that programmatically created custom user fields. It display in Manage fields section but not enable/view inside Manage form display and Manage display section.
I have tried to override entiry_form_display but not get success.
core.entity_form_display.user.facebook.default.yml
langcode: en
status: true
dependencies:
config:
- field.field.user.user.field_facebook
module:
- field_layout
- layout_discovery
- user
id: user.field_facebook.default
targetEntityType: user
bundle: field_facebook
mode: default
content:
field_facebook:
type: string
weight: 200
label: above
settings:
link_to_entity: false
third_party_settings: { }
hidden: { }
field.field.user.user.field_facebook.yml
langcode: en
status: true
dependencies:
config:
- field.storage.user.field_facebook
module:
- user
id: user.user.field_facebook
field_name: field_facebook
entity_type: user
bundle: user
label: 'Facebook'
description: ''
required: false
translatable: false
default_value: { }
default_value_callback: ''
settings: { }
field_type: string
field.storage.user.field_fullcontact_facebook.yml
langcode: en
status: true
dependencies:
module:
- user
id: user.field_facebook
field_name: field_facebook
entity_type: user
type: string
settings: {
max_length: 255
is_ascii: false
case_sensitive: false
}
module: core
locked: false
cardinality: 1
translatable: true
indexes: { }
persist_with_no_fields: false
custom_storage: false
persist_with_no_fields: true
Give it a try.

Doctrine sortable extension in symfony3 - Error: Not Null

I try to use the doctrine extension sortable via the gedmo extension. I installed the gedmo-package with composer and followed the instructions of the installation in symfony2. I use yaml-files as mapping-information for doctrine.
My yaml-file:
AppBundle\Entity\Picture:
type: entity
table: pictures
id:
id:
type: integer
generator: { strategy: AUTO }
fields:
[...]
type:
type: string
length: 20
position:
type: string
gedmo:
sortable:
groups: [type]
The field position did have the type int, but I also tried string, because that should cause an error by the yaml-driver of the sortable-extension (InvalidMappingException).
But the error I always get is Integrity constraint violation: 19 NOT NULL constraint failed: pictures.position. But in all examples of the sortable extension there is no need to specifically set a value for the position-field or to allow null in the yaml-file. Also I suppose, that the InvalidMappingException should occur before the NOT NULL Exception.
Because of this I think that the extension is not even used.
The config-files I use:
My config.yml file:
imports:
- { resource: parameters.yml }
- { resource: security.yml }
- { resource: services.yml }
- { resource: doctrine_extensions.yml}
[...]
My doctrine_extensions.yml file:
services:
# KernelRequest listener
gedmo.listener.sortable:
class: Gedmo\Sortable\SortableListener
tags:
- { name: doctrine.event_subscriber, connection: default }
calls:
- [ setAnnotationReader, [ "#annotation_reader" ] ]
i know this question has been asked ages ago, but in case it can help: depending on versions you're using, you can try this syntax (this worked for me):
#Resources/config/doctrine/Entity.orm.yml
[...]
fields:
position:
type: integer
gedmo:
- sortablePosition
and if you need to sort by group, you need to add this into your relation (here is full example):
manyToOne:
parent:
targetEntity: Parent
inversedBy: children
joinColumn:
name: parent_id
referencedColumnName: id
onDelete: cascade
gedmo:
- sortableGroup

Lots of Fun with Doctrine ORM and Silex - Doctrine MappingException: Class does not exist

I am using the DflyDevDoctrineORMServicProvider with Silex. I have created a simple model as a proof of concept.
I am able to build the model (PHP classes) from my Yml files- but when I try to generate the schema, and populate the database etc - it all falls apart, and I get the error message:
[Doctrine\Common\Persistence\Mapping\MappingException]
Class 'DistrictType' does not exist
I must admit, I am struggling with PHP Namespaces and how they relate to Doctrine Mappings and file locations - I'm sure the problem is likely to be related to this confusion.
I will briefly describe my directory layout and the configuration files I am using - hopefully, someone maybe able to spot where I am going wrong:
Directory layout
|
|---src
| app.php // app variable cration, autoloading etc ..
| registration.php // service registration etc ..
|---Entity // Generated models go here
|---Resources
| |-- mappings // YamL model definitions here ...
|
|---config
| cli-config.php
| config.yml
|
|---web
index.php // imports app.php
composer.json
.htaccess
Snippet from registration.php
$app->register(new DoctrineOrmServiceProvider, array(
"orm.proxies_dir" => __DIR__.'/../cache/doctrine/proxy',
"orm.em.options" => array(
"mappings" => array(
// Using actual filesystem paths
array(
"type" => "yml",
"namespace" => "Entity",
"path" => __DIR__."/Resources/mappings"
),
),
),
));
// Setup entity manager (Possible Hack)
$paths = array($app['orm.em.options']['mappings'][0]['path']);
$config = Setup::createYAMLMetadataConfiguration($paths, $app['debug']);
$app['orm.em'] = EntityManager::create($app['db.options'], $config);
cli-config.php
<?php
// ...
$app = require_once __DIR__.'/../src/app.php';
$isDevMode = $app['debug'];
$paths = array($app['orm.em.options']['mappings'][0]['path']);
$config = Setup::createYAMLMetadataConfiguration($paths, $isDevMode);
$entityManager = EntityManager::create($app['db.options'], $config);
$commands = array(
new \UseAllFive\Command\LoadDataFixturesDoctrineCommand(),
);
return ConsoleRunner::createHelperSet($entityManager);
Now here are the models:
District.dcm.yml
District:
type: entity
table: pac_district
repositoryClass: DistrictRepository
id:
id:
type: integer
id: true
generator:
strategy: AUTO
fields:
name:
type: string
length: 64
nullable: false
manyToOne:
region:
targetEntity: Region
joinColumn:
name: region_id
referencedColumnName: id
onDelete: RESTRICT
onUpdate: CASCADE
district_type:
targetEntity: DistrictType
joinColumn:
name: district_type_id
referencedColumnName: id
onDelete: RESTRICT
onUpdate: CASCADE
uniqueConstraints:
uidx_district_name:
columns: [name]
DistrictType.dcm.yml
DistrictType:
type: entity
table: pac_district_type
repositoryClass: DistrictTypeRepository
id:
id:
type: integer
id: true
generator:
strategy: AUTO
fields:
name:
type: string
length: 64
nullable: false
uniqueConstraints:
uidx_district_type_name:
columns: [name]
Region.dcm.yml
Region:
type: entity
table: pac_region
repositoryClass: RegionRepository
id:
id:
type: integer
id: true
generator:
strategy: AUTO
fields:
name:
type: string
length: 64
nullable: false
uniqueConstraints:
uidx_region_name:
columns: [name]
composer.json
{
"require": {
"silex/silex": "2.0.*#dev",
"symfony/yaml": "2.6.7",
"doctrine/dbal": "~2.2",
"doctrine/orm": ">=2.1",
"dflydev/doctrine-orm-service-provider": "2.0.*#dev"
},
"autoload": {
"psr-0": {"Controller": "src/"},
"psr-0": {"Entity": "src/"}
}
}
These are the results of the following commands:
root#yourbox:~/path/to/project$ vendor/bin/doctrine orm:generate-entities src/Entity/
Processing entity "Region"
Processing entity "DistrictType"
Processing entity "District"
Entity classes generated to "/path/to/project/src/Entity"
root#yourbox:~/path/to/project$ vendor/bin/doctrine orm:schema-tool:create
[Doctrine\Common\Persistence\Mapping\MappingException]
Class 'DistrictType' does not exist
I have struggled with this for two days straight - and can't see what I'm doing wrong - can anyone spot what Imay be doing wrong?
It is quite simple actually. What you are doing wrong is - autoloading files. The way your composer file is configured now, it will not autoload the entity files and the schema creation will fail.
Modify your composer autoload section by passing an empty string as first parameter, and add Entity to the path, like this:
"autoload": {
"psr-0": {"Controller": "src/"},
"psr-0": {"": "src/Entity/"}
}
Then run composer update and you would be able to generate your entities. On a side note, currently I am developing a small project with Silex as well, and I would strongly recommend you switch to using Namespaces.
Hello #Artamiel that fixed my problem, it was a combination of adding the autoload in composer and fixing the namespace, I mean my autoload now has:
"psr-0": {"Entity": "config/doctrine/"}
And as I have defined the namespace as Entity created such a folder and move the entities there, and finally I am up and running. Thanks

Doctrine2 designing problems with inheritance

I am currently setting up a new application and decided to use doctrine2 as an orm.
I am new to doctrine2, and having quite some difficulties getting my design the way I want it.
This is what I'm trying to do:
I have the following classes:
class User {
protected $userid;
protected $role;
protected $lang;
protected $email;
protected $disabled;
...
+ getters and setters
}
class Person extends User {
protected $personid;
protected $name;
protected $firstname;
protected $company;
protected $functiontitle
...
+ getters and setters
}
class Candidate extends User {
protected $candidateid;
protected $name;
protected $firstname;
protected $title;
protected $birthdate;
...
+ getters and setters
}
Both Candidate and Person inherit the User properties, but have their own set op specific properties.
In the postgresql database I currently have a similar set up, 3 tables, with each their set of specific columns.
Now I would like to map this using yaml, and want all 3 of the classes to be accessible as entities.
I also don't want to have to duplicate a lot of fields in my database.
How can I accomplish this?
I've been looking for solutions for days but haven't come up with anything working.
If what I am trying to do is not possible then please explain what my options are, and why this isn't supported.
Without an ORM it seems that I could easily add foreign keys to candidate and person to join with the user table, but I can't get that to work with doctrine.
This is the yaml file I currently have to set it up as a Class Table Inheritance:
User:
MyProject\model\User:
type: entity
table: `user`
id:
userid:
column: userid
type: integer
nullable: false
comment: ''
id: true
fields:
role:
column: role
type: string
nullable: true
length: null
fixed: false
comment: ''
email:
type: string
nullable: true
length: null
fixed: false
comment: ''
disabled:
type: boolean
nullable: true
comment: ''
InheritanceType: JOINED
DiscriminatorColumn:
name: discr
type: string
DiscriminatorMap:
person: Person
candidate: Candidate
lifecycleCallbacks: { }
Person:
MyProject\model\Person:
type: entity
table: person
fields:
name:
type: string
nullable: true
length: null
fixed: false
comment: ''
firstname:
type: string
nullable: true
length: null
fixed: false
comment: ''
company:
type: string
nullable: true
length: null
fixed: false
comment: ''
functiontitle:
type: string
nullable: true
length: null
fixed: false
comment: ''
...
lifecycleCallbacks: { }
But this doesn't work.
To avoid injury, sit on your hands before reading further. Don't want to give yourself a concussion with a face palm.
...
ready?
...
Lower case the first letter of inheritanceType, discriminatorColumn and discriminatorMap.
Drop the schema and rebuild.
I am assuming that you already changed the discriminator column to discr.