zfcampus / zf-apigility-doctrine

Doctrine-enabled services for Apigility
BSD 3-Clause "New" or "Revised" License
107 stars 50 forks source link

Uni-directional ManyToOne/OneToOne repeated in Entity to same Target throws fatal DBAL exception #314

Closed rkeet closed 5 years ago

rkeet commented 6 years ago

Re-report here by request


I hope this is the place to open this issue instead of in Doctrine. Not sure though, please advise.

Code to reproduce the issue

Additional config (probably not relevant)

class Company

/**
 * @var Location
 * @ORM\ManyToOne(targetEntity="Location", cascade={"persist", "remove"})
 *  // Or -> \OneToOne(targetEntity="Location", cascade={"persist", "remove"})
 * @ORM\JoinColumn(name="main_location_id", referencedColumnName="id", nullable=false)
 */
protected $mainLocation;

/**
 * @var Location
 * @ORM\ManyToOne(targetEntity="Location", cascade={"persist", "remove"})
 *  // Or -> \OneToOne(targetEntity="Location", cascade={"persist", "remove"})
 * @ORM\JoinColumn(name="billing_location_id", referencedColumnName="id", nullable=true)
 */
protected $billingLocation;

Demo POST data

{
   "name":"New Farm",
   "mainLocation":{
    "name": "The home",
    "address": "All the way down the drive 33, 12345, FarmVille"
   },
   "billingLocation":{
    "name": "The barn",
    "address": "Beyond the house 22, 12345, FarmVille"
   }
}

Expected results

I expected that I must provide the mainLocation property with a new Location object and optionally do the same for billingLocation.

Actual results

With or without billingLocation (not required) in the test data above, but with the required mainLocation, the error below appears.

{
    "trace": [
        {
            "file": "C:\\xampp\\htdocs\\api\\vendor\\doctrine\\dbal\\lib\\Doctrine\\DBAL\\DBALException.php",
            "line": 184,
            "function": "convertException",
            "class": "Doctrine\\DBAL\\Driver\\AbstractMySQLDriver",
            "type": "->",
            "args": [
                "An exception occurred while executing 'INSERT INTO companies (name, main_location_id, billing_location_id) VALUES (?, ?, ?)' with params [\"New Farm\", null, null]:\n\nSQLSTATE[23000]: Integrity constraint violation: 1048 Column 'main_location_id' cannot be null",
                {
                    "errorInfo": [
                        "23000",
                        1048,
                        "Column 'main_location_id' cannot be null"
                    ],

If I make mainLocation nullable (nullable=true) OR remove the other references to Location, this setup works.


Now I've traced this into the UnitOfWork where I found that it tries to create the Company without first creating the Location object(s). As such, they "don't exist for real". They do in memory and they are persisted, just not flushed prior to Company, thus have no ID, inspecting the $entity variable confirms this.


Any help to point in a right direction or provide a solution would be greatly appreciated. I've been bashing this issue for 2 days straight now.

rkeet commented 6 years ago

Additional information:

Just tried to hydrate database with data fixtures and got the same problem with updated entities:


Because it's starting to be a real issue, I've created Zend Skeleton application project and created a self-contained module, whose only function is to create a Company with 2 contacts (like above).

This does not present the same problem, leading me to believe the issue must really be on the Apigility side of things.

314.zip

To test with project, just unpack where you host your projects and run:

Then visit the project with relative url /bug.

All code for this test is contained in the Bug module (apart from Bug module loading).

TomHAnderson commented 5 years ago

I think you are talking about circular references: https://github.com/zfcampus/zf-hal/blob/master/src/Plugin/Hal.php#L680-L683

You have an issue because you are not using a hydrator on one of the two referenced entities.

user > address > user > address

In this example the address does not need the user so the reference to user should be filtered out using a hydrator filter. Event better you should use an EntityLink hydrator strategy.

rkeet commented 5 years ago

@TomHAnderson Was your comment meant for this ticket?

I do not have a User Entity in the report or the example send in the zip file.


If it is related to this ticket, both Location Entities are annotated the exact same way on the Company Entity (see initial report above). Also, with the relations being uni-directional (also in the provided example code), a circular reference is not possible. So it's got to be something else ;-)

michalbundyra commented 5 years ago

@rkeet I've tried to run your attached code. I can't run composer install because I got the exception:

$ composer install
Loading composer repositories with package information
Installing dependencies (including require-dev) from lock file
Warning: The lock file is not up to date with the latest changes in composer.json. You may be getting outdated dependencies. Run update to update them.

  [UnexpectedValueException]                                                         
  Link constraint in __ROOT__ requires > php should be a string, got array (array (  
  ))                                                                                 

install [--prefer-source] [--prefer-dist] [--dry-run] [--dev] [--no-dev] [--no-custom-installers] [--no-autoloader] [--no-scripts] [--no-progress] [--no-suggest] [-v|vv|vvv|--verbose] [-o|--optimize-autoloader] [-a|--classmap-authoritative] [--apcu-autoloader] [--ignore-platform-reqs] [--] [<packages>]...

so I run composer update and it's fine.

There are my packages installed:

$ composer show
container-interop/container-interop          1.2.0   Promoting the interoperability of container objects (DIC, SL, etc.)
doctrine/annotations                         v1.6.0  Docblock Annotations Parser
doctrine/cache                               v1.8.0  Caching library offering an object-oriented API for many cache backends
doctrine/collections                         v1.5.0  Collections Abstraction library
doctrine/common                              v2.10.0 PHP Doctrine Common project is a library that provides additional functionality that other Doctrine projects depend on such as better reflection support, ...
doctrine/dbal                                v2.8.0  Database Abstraction Layer
doctrine/doctrine-module                     1.2.0   Zend Framework Module that provides Doctrine basic functionality required for ORM and ODM modules
doctrine/doctrine-orm-module                 1.1.8   Zend Framework Module that provides Doctrine ORM functionality
doctrine/event-manager                       v1.0.0  Doctrine Event Manager component
doctrine/inflector                           v1.3.0  Common String Manipulations with regard to casing and singular/plural rules.
doctrine/instantiator                        1.1.0   A small, lightweight utility to instantiate objects in PHP without invoking their constructors
doctrine/lexer                               v1.0.1  Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.
doctrine/orm                                 v2.6.3  Object-Relational-Mapper for PHP
doctrine/persistence                         v1.1.0  The Doctrine Persistence project is a set of shared interfaces and functionality that the different Doctrine object mappers share.
doctrine/reflection                          v1.0.0  Doctrine Reflection component
psr/cache                                    1.0.1   Common interface for caching libraries
psr/container                                1.0.0   Common Container Interface (PHP FIG PSR-11)
psr/log                                      1.1.0   Common interface for logging libraries
psr/simple-cache                             1.0.1   Common interfaces for simple caching
symfony/console                              v3.4.19 Symfony Console Component
symfony/debug                                v4.2.0  Symfony Debug Component
symfony/polyfill-mbstring                    v1.10.0 Symfony polyfill for the Mbstring extension
zendframework/zend-authentication            2.6.0   provides an API for authentication and includes concrete authentication adapters for common use case scenarios
zendframework/zend-cache                     2.8.2   Caching implementation with a variety of storage options, as well as codified caching strategies for callbacks, classes, and output
zendframework/zend-code                      3.3.1   provides facilities to generate arbitrary code using an object oriented interface
zendframework/zend-component-installer       1.1.1   Composer plugin for automating component registration in zend-mvc and Expressive applications
zendframework/zend-config                    3.2.0   provides a nested object property based user interface for accessing this configuration data within application code
zendframework/zend-di                        2.6.1  
zendframework/zend-escaper                   2.6.0   Securely and safely escape HTML, HTML attributes, JavaScript, CSS, and URLs
zendframework/zend-eventmanager              3.2.1   Trigger and listen to events within a PHP application
zendframework/zend-filter                    2.8.0   provides a set of commonly needed data filters
zendframework/zend-form                      2.12.0  Validate and display simple and complex forms, casting forms to business objects and vice versa
zendframework/zend-http                      2.8.2   Provides an easy interface for performing Hyper-Text Transfer Protocol (HTTP) requests
zendframework/zend-hydrator                  2.4.1   Serialize objects to arrays, and vice versa
zendframework/zend-i18n                      2.9.0   Provide translations for your application, and filter and validate internationalized values
zendframework/zend-inputfilter               2.8.2   Normalize and validate input sets from the web, APIs, the CLI, and more, including files
zendframework/zend-loader                    2.6.0   Autoloading and plugin loading strategies
zendframework/zend-modulemanager             2.8.2   Modular application system for zend-mvc applications
zendframework/zend-mvc                       3.1.1   Zend Framework's event-driven MVC layer, including MVC Applications, Controllers, and Plugins
zendframework/zend-mvc-form                  1.0.0   Metapackage with all requirements needed to use zend-form with zend-mvc.
zendframework/zend-mvc-i18n                  1.1.0   Integration between zend-mvc and zend-i18n
zendframework/zend-mvc-plugin-fileprg        1.1.0   Post/Redirect/Get plugin with file upload handling for zend-mvc controllers
zendframework/zend-mvc-plugin-flashmessenger 1.1.0   Plugin for creating and exposing flash messages via zend-mvc controllers
zendframework/zend-mvc-plugin-identity       1.1.0   Plugin for retrieving the current authenticated identity within zend-mvc controllers
zendframework/zend-mvc-plugin-prg            1.1.0   Post/Redirect/Get plugin for zend-mvc controllers
zendframework/zend-mvc-plugins               1.0.1   Collection of all stable zend-mvc plugins served via separate packages.
zendframework/zend-paginator                 2.8.1   zend-paginator is a flexible component for paginating collections of data and presenting that data to users.
zendframework/zend-router                    3.2.0   Flexible routing system for HTTP and console applications
zendframework/zend-servicemanager            3.3.2   Factory-Driven Dependency Injection Container
zendframework/zend-servicemanager-di         1.2.0   zend-di integration for zend-servicemanager
zendframework/zend-session                   2.8.5   manage and preserve session data, a logical complement of cookie data, across multiple page requests by the same client
zendframework/zend-stdlib                    3.2.1   SPL extensions, array utilities, error handlers, and more
zendframework/zend-uri                       2.6.1   A component that aids in manipulating and validating » Uniform Resource Identifiers (URIs)
zendframework/zend-validator                 2.10.2  provides a set of commonly needed validators
zendframework/zend-view                      2.10.0  provides a system of helpers, output filters, and variable escaping
zfcampus/zf-development-mode                 3.2.0   Zend Framework development mode script

and when I open /bug this is what I can see:

screenshot 2018-12-03 at 09 19 15

Can you confirm that the bug is still present with the latest repositories? Maybe it was fixed in some dependent library - or I am doing something wrong?

rkeet commented 5 years ago

@webimpress weird, getting that same error on composer install now.

Running composer update does change some of the versions from what they were. Also not getting the bug I reported with updated packages.

Getting the same response as you.


As an aside, I do not want to make the time to find this bug again (with the version changes from half a year ago until now), so recommend this be closed.