Skip to content

Commit 1b781d4

Browse files
author
Tom H Anderson
committed
Release 1.0
1 parent 41adf47 commit 1b781d4

File tree

3 files changed

+110
-8
lines changed

3 files changed

+110
-8
lines changed

README.md

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,41 @@
1+
Doctrine ORM Data Validation
2+
============================
3+
4+
For one reason or another you will build an ORM on top of an existing database. The existing database may
5+
not have referential integrity for all it's relationships.
6+
7+
You now have a database with an ORM and there is probably bad data in the database which does not conform
8+
to the relationships defined in the ORM.
9+
10+
This tool is intended for devleopment only.
11+
12+
113
Foreign Key Validation
2-
======================
14+
----------------------
15+
16+
Create a report by scanning every relationship defined in your ORM for data
17+
which is missing it's foreign key. Nullable relationships are not evaluated.
18+
19+
```sh
20+
php index.php orm:data-validation:relationship --object-manager="doctrine.entitymanager.orm_default"
21+
```
22+
23+
24+
Configure Zend Framework 2 Module
25+
---------------------------------
26+
27+
```php
28+
composer require "api-skeletons/zf-doctrine-orm-data-validation": "^1.0"
29+
```
30+
31+
Add to `config/development.config.php.dist`:
32+
```php
33+
return array(
34+
'modules' => array(
35+
'ZF\\Doctrine\\Audit'
36+
...
37+
),
38+
```
339

4-
This library will generate sql to test for invalid data based on relationships between related tables. This can happen if you overlay an Doctrine ORM on an existing database then use that metadata to create the database and import the old data in.
40+
Enable development mode to copy `development.config.php.dist` to `development.config.php`
541

6-
At import foreign key checks will be ignored. This corrects for that inability to check relationships upon import.

config/module.config.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
'routes' => [
1414
'zf-doctrine-orm-data-validation-scan' => [
1515
'options' => [
16-
'route' => 'orm:data-validation:relationship --objectManager=',
16+
'route' => 'orm:data-validation:relationship --object-manager=',
1717
'defaults' => [
1818
'controller' => 'ZF\Doctrine\ORM\DataValidation\Controller\ForeignKey',
1919
'action' => 'relationship',

src/Controller/ForeignKeyController.php

Lines changed: 71 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,80 @@ public function relationshipAction()
2727

2828
$console = $this->getServiceLocator()->get('console');
2929

30-
$objectManagerAlias = $this->params()->fromRoute('objectManager');
30+
$objectManagerAlias = $this->params()->fromRoute('object-manager');
3131
$objectManager = $this->getServiceLocator()->get($objectManagerAlias);
3232

33-
$metadataFactory = $objectManager->getMetadataFactory();
33+
$console->write(
34+
'Count'
35+
. "\t"
36+
. 'Child Field'
37+
. "\t"
38+
. 'Child Entity'
39+
. "\t"
40+
. 'Parent Entity'
41+
. "\n"
42+
);
3443

35-
print_r($metadataFactory->getLoadedMetadata());
44+
$allMetadata = $objectManager->getMetadataFactory()->getAllMetadata();
45+
foreach ($allMetadata as $metadata) {
3646

37-
$console->write("End Metadata\n", Color::GREEN);
47+
foreach ($metadata->getAssociationMappings() as $mapping) {
48+
if ($mapping['type'] == 2) {
49+
$queryBuilder = $objectManager->createQueryBuilder();
50+
$queryBuilder2 = $objectManager->createQueryBuilder();
51+
52+
$queryBuilder->select(
53+
"count(child) as ct, '"
54+
. $mapping['fieldName']
55+
. "' as childField, '"
56+
. $metadata->getName()
57+
. "' as childEntity, '"
58+
. $mapping['targetEntity']
59+
. "' as parentEntity"
60+
)
61+
->from($metadata->getName(), 'child')
62+
->andWhere($queryBuilder->expr()->not(
63+
$queryBuilder->expr()->exists(
64+
$queryBuilder2->select('parent')
65+
->from($mapping['targetEntity'], 'parent')
66+
->andWhere($queryBuilder2->expr()->eq(
67+
'child.' . $mapping['fieldName'],
68+
'parent'
69+
))
70+
->getQuery()
71+
->getDql()
72+
)
73+
)
74+
)
75+
;
76+
77+
// Do not query columns which are nullable and are null
78+
$childFieldMapping = $objectManager->getMetadataFactory()
79+
->getMetadataFor($metadata->getName())
80+
->getAssociationMapping($mapping['fieldName'])
81+
;
82+
83+
if (! isset($childFieldMapping['joinColumns'][0]['nullable'])
84+
|| ! $childFieldMapping['joinColumns'][0]['nullable']) {
85+
86+
$queryBuilder->andWhere($queryBuilder->expr()->isNotNull('child.' . $mapping['fieldName']));
87+
}
88+
89+
$result = $queryBuilder->getQuery()->getOneOrNullResult();
90+
91+
if ($result['ct']) {
92+
$console->write($result['ct']
93+
. "\t"
94+
. $result['childField']
95+
. "\t"
96+
. $result['childEntity']
97+
. "\t"
98+
. $result['parentEntity']
99+
. "\n"
100+
);
101+
}
102+
}
103+
}
104+
}
38105
}
39106
}

0 commit comments

Comments
 (0)