Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Relax joins for child classes and parameter suffix #1438

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

dgrothaus-mc
Copy link
Contributor

Aus anderen ORM Bibliotheken bin ich es gewohnt, nicht nur rohe SQL Abfragen JOINen zu können, sondern auch eine weitere Instanz der ORM Klasse. Meiner Erfahrung nach sorgt das für weniger Fehler beim Ausführen von Abfragen mit JOINs, da sich die ORM Klasse großteils darum kümmert, dass die Abfrage ordentlich formuliet ist um im Zweifelsfall eine hilfreiche Fehlermeldung wirft.

Bei yform ist die Query Klasse leider sehr verschlossen und es ist für ableitende Klassen nicht möglich Einfluss auf einige essentielle Daten wie zum Beispiel die JOIns zu nehmen. Daher bitte ich, den Zugriff auf die JOINs etwas zu lockern.

Falls da von Interesse ist oder die Entscheidung beeinflusst, hier ist der relevante Auszug aus der ableitenden Klasse, welche von dieser Änderung profitieren würde:

<?php
class MeineQuery extends rex_yform_manager_query {
    /** @var int $subQueryCount Count the number of added sub queries to get the parameter prefix. */
    private int $subQueryCount = 0;
    /** @var bool $subQuery Is this query configured to be used as a sub query? */
    private bool $subQuery = false;
    /** @var bool $joinsForFetchAdded Internal flag to track if SQL JOIN conditions were already added to a query */
    private bool $joinsForFetchAdded = false;

    /**
     * Configure this query to be used as a sub query. e.g. to be {@see joinSubQuery() joined}
     *
     * @return $this
     */
    public function asSubQuery(): static
    {
        $this->resetSelect();
        $this->setParamSuffix('sq' . ++$this->subQueryCount);
        $this->subQuery = true;

        return $this;
    }

    /**
     * Return if this query is intended as a sub query for another query.
     *
     * @return bool
     */
    public function isSubQuery(): bool
    {
        return $this->subQuery;
    }

    /**
     * **WARNING** This method only returns _false_ **once**. This method should be called exactly when the joining of
     * related tables is about to happen and to prevent multiple joins if query methods are called multiple times on
     * the same object.
     *
     * @return bool Have related queries already been joined?
     * @internal
     */
    public function areJoinsForFetchAdded(): bool
    {
        if ($this->joinsForFetchAdded) {
            return true;
        }
        $this->joinsForFetchAdded = true;

        return false;
    }

    /**
     * Join a sub-query. The $query that is joined must be configured {@see asSubQuery() as a sub query}.
     *
     * @param string      $type      JOIN type: INNER|LEFT|OUTER|CROSS ...
     * @param MeineQuery  $query     The query to join
     * @param string      $alias     Alias that the result of the query is addressable later
     * @param string|null $condition [Optional] JOIN condition
     *
     * @return static
     */
    public function joinSubQuery(string $type, MeineQuery $query, string $alias, ?string $condition = null): static
    {
        if (true !== $query->isSubQuery()) {
            throw new InvalidArgumentException('The sub-query to be joined must be configured "asSubQuery()"');
        }

        /** {@see whereRaw()} is called, because it's the only place reachable from outside that combines two arrays
         * of parameters. Accessing the private member {@see rex_yform_manager_query::$params} is hard otherwise. */
        $this->whereRaw('1', $query->getParams());
        $type = mb_strtoupper($type);
        $join = "{$type} JOIN ({$query->resetOrderBy()->getQuery()}) AS " . $query->quoteIdentifier($alias);
        if ($condition) {
            $join .= ' ON ' . $condition;
        }
        $this->joins[] = $join;

        return $this;
    }
}

Allow child classes to modify the array of join queries.
Allow child classes to specify a suffix that's appended to each bound
parameter for a query.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant