{"record":{"id":"99098fec5199a873","repo":"doctrine/orm","slug":"using-append-true-does-not-have-an-effect-with","errorCode":null,"errorMessage":"Using $append = true does not have an effect with 'where' or 'having' parts. See QueryBuilder#andWhere() for an example for correct usage.","messagePattern":"Using \\$append = true does not have an effect with 'where' or 'having' parts\\. See QueryBuilder#andWhere\\(\\) for an example for correct usage\\.","errorType":"exception","errorClass":"InvalidArgumentException","httpStatus":null,"severity":"error","filePath":"src/QueryBuilder.php","lineNumber":625,"sourceCode":"    public function getMaxResults(): int|null\n    {\n        return $this->maxResults;\n    }\n\n    /**\n     * Either appends to or replaces a single, generic query part.\n     *\n     * The available parts are: 'select', 'from', 'join', 'set', 'where',\n     * 'groupBy', 'having' and 'orderBy'.\n     *\n     * @phpstan-param string|object|list<string>|array{join: array<int|string, object>} $dqlPart\n     *\n     * @return $this\n     */\n    public function add(string $dqlPartName, string|object|array $dqlPart, bool $append = false): static\n    {\n        if ($append && ($dqlPartName === 'where' || $dqlPartName === 'having')) {\n            throw new InvalidArgumentException(\n                \"Using \\$append = true does not have an effect with 'where' or 'having' \" .\n                'parts. See QueryBuilder#andWhere() for an example for correct usage.',\n            );\n        }\n\n        $isMultiple = is_array($this->dqlParts[$dqlPartName])\n            && ! ($dqlPartName === 'join' && ! $append);\n\n        // Allow adding any part retrieved from self::getDQLParts().\n        if (is_array($dqlPart) && $dqlPartName !== 'join') {\n            $dqlPart = reset($dqlPart);\n        }\n\n        if ($dqlPartName === 'join') {\n            $newDqlPart = [];\n\n            foreach ($dqlPart as $k => $v) {\n                if (is_numeric($k)) {","sourceCodeStart":607,"sourceCodeEnd":643,"githubUrl":"https://github.com/doctrine/orm/blob/d9b9ff73016bf598ae07515f97289ce8074e97a5/src/QueryBuilder.php#L607-L643","documentation":"add($dqlPartName, $dqlPart, $append) is QueryBuilder's low-level part setter. For 'where' and 'having', blindly appending another part would stack predicates in a way that matches no boolean semantics users actually want, so the builder rejects $append = true for exactly those two part names and points you to andWhere()/orWhere()/andHaving()/orHaving(), which build the combined expression explicitly.","triggerScenarios":"$qb->add('where', $expr, true); $qb->add('having', $havingExpr, true); builder-merge utilities that loop over getDQLParts() re-adding every part with $append = true and hit the 'where'/'having' keys.","commonSituations":"Utilities that clone or merge QueryBuilders by copying parts wholesale; porting old code that treated 'where' as a list; generic filter pipelines built on add().","solutions":["Replace add('where', $x, true) with $qb->andWhere($x) (or orWhere) so the combination is explicit; likewise andHaving/orHaving.","When merging builders, special-case where/having: fetch getDQLPart('where') and combine via andWhere()/andHaving().","Use add() without the append flag only where you truly mean replacement."],"exampleFix":"// before\n$qbTarget->add('where', $qbSource->getDQLPart('where'), true); // InvalidArgumentException\n\n// after\n$where = $qbSource->getDQLPart('where');\nif ($where !== null) {\n    $qbTarget->andWhere($where);\n}","handlingStrategy":"validation","validationCode":"if ($append && in_array($part, ['where', 'having'], true)) {\n    // combine explicitly instead of add(..., true)\n    $part === 'where' ? $qb->andWhere($value) : $qb->andHaving($value);\n} else {\n    $qb->add($part, $value, $append);\n}","typeGuard":null,"tryCatchPattern":"In generic part copiers, catch \\InvalidArgumentException and fail loudly with the part name: catch (\\InvalidArgumentException $e) { throw new LogicException(\"Cannot append part '$part'\", 0, $e); }","preventionTips":["Prefer typed part methods (andWhere, andHaving, addOrderBy) over add().","Never loop blindly over getDQLParts() with append=true.","Know which parts are single-valued (where, having) versus lists (join, groupBy, orderBy)."],"tags":["doctrine-orm","query-builder","where","having","dql-parts"],"backgroundTag":"invalid-method-argument","analyzedSha":"d9b9ff73016bf598ae07515f97289ce8074e97a5","analyzedAt":"2026-08-21T06:13:15.863Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}