Express Data Objects: Remove requirement from a many-to-many association

I have two Express Data Objects: Products and Customer Cases. They have a many-to-many relation between them: a single Product might appear in many Customer Cases and one Customer Case might talk about many Products.

When I try to insert a new Product that has no Customer Case associated with it yet, I get an error message saying that I need to select a Customer Case. The Customer Case is not required on the form, so it seems that somehow the association creates the requirement.

Is there any way that I can either specify that the many-to-many relation is not required or work around that requirement?

I don’t know if it was fixed in latest 8.x branch, but if not, follow instructions in comment:

<?php

/*
Bug: You can't add Express entry with empty association in 8.x version
https://github.com/concrete5/concrete5/issues/9428
Solution
https://github.com/concrete5/concrete5/commit/b5375bfa54a8d58d5a424784f7e127e9ab538b2a#diff-816ae1f5e226b6ab522591fa6bfef766851d181742d350b32c49ecaab9bff25f

1) Copy this modified file to:
application/src/Express/Form/Control/Validator/AssociationControlValidator.php

2) Skip this part if you are auto-loading classes from src folder:
application/bootstrap/autoload.php
$classLoader = new \Symfony\Component\ClassLoader\Psr4ClassLoader();
$classLoader->addPrefix('Application', DIR_APPLICATION . '/' . DIRNAME_CLASSES);
$classLoader->register();

3) Override core file
application/bootstrap/app.php
$app->bind('\Concrete\Core\Express\Form\Control\Validator\AssociationControlValidator', function() {
    return new Application\Express\Form\Control\Validator\AssociationControlValidator(new Concrete\Core\Error\ErrorList\ErrorList());
});
*/

namespace Application\Express\Form\Control\Validator;

use Concrete\Core\Entity\Express\Control\AssociationControl;
use Concrete\Core\Entity\Express\Control\Control;
use Concrete\Core\Error\ErrorList\ErrorList;
use Symfony\Component\HttpFoundation\Request;

class AssociationControlValidator implements \Concrete\Core\Express\Form\Control\Validator\ValidatorInterface
{
    /**
     * @var ErrorList
     */
    protected $errorList;

    public function __construct(ErrorList $errorList)
    {
        $this->errorList = $errorList;
    }

    public function validateRequest(Control $control, Request $request)
    {
        if ($control->isRequired()) {
            $associationValue = $request->request->get('express_association_' . $control->getId());
            if (!$associationValue) {
                /**
                 * @var AssociationControl
                 */
                $this->errorList->add(t('You must select a valid %s', $control->getAssociation()->getTargetEntity()->getName()));
            }
        }

        return $this->errorList;
    }
}
1 Like

Thanks, that worked. I did change $app->bind() to Core::bind() in the bootstrap file.