1

I have 2 objects that I'm not very certain what is the proper (or better) way I should use.

I have a query builder object that constructs an SQL statement like

$qb = new SelectQuery('users');
$qb->columns('id', 'email')->where('id', '=', 25);

print_r($qb->build());
print_r($qb->data());

Output

SELECT id,email FROM users WHERE  id = :a

Array
(
    [:a] => 25
)

Then I can pass that to PDO::prepare() and PDOStatement::execute() and get stuff going.

The other class I have is a kind of sorter I don't really know how to call it. It accepts a bunch of parameters and constructs some SQL that sorts and/or limits the query that is about to be run on the page.

$parser = new SQLGridParser([
    'query' => 'foo',
    'sort' => 'id-0'
]);

$parser->setSearchColumns(['email']);

print_r($parser->getFilters());
print_r($parser->getOrderBy());

Output

Array
(
    [0] =>  AND `email` LIKE :b
    [1] => Array
        (
            [:b] => %foo%
        )

)

ORDER BY `id` DESC

Now I want to be able to pass one object to the other and have a full query constructed at the end but I'm having my doubts as to which object I should pass to which.

If I pass the parser/sorter to the query builder the function will look something like

public function useSorter(SQLGridParser $parser) {
    $filters = $parser->getFilters();
    $this->where .= $filters[0];
    $this->data = array_merge($this->data, $filters[1]);

    $this->order = $parser->getOrderBy();

    // and so on..
}

If I pass the builder to the sorter then it would be something like this

public function injectSQL(Query $query) {
    $filters = $this->getFilters();
    $query->where .= $filters[0];
    $query->data = array_merge($query->data, $filters[1]);

    $query->order = $this->getOrderBy();

    // and so on...
}

The code is basically identical but what would be considered the better solution and why?

  • 1
    I guess it depends on the perspective -- you have some master source of data, and you apply filter/sorter one by one. Or in reverse -- you have some master filter/sorter and you apply it to every data source you have. Btw. IMHO the name "parser" is really awkward here, it is a filter/sorter builder, not a parser, because you build SQL out of the parameters, the reverse process would be parser. And if you are looking for "best practice" I would split sorter and filter into two builders, because you should work with "atomic" entities. And sorting and filtering are atomic/distinct operations. – greenoldman Jul 26 '16 at 6:33
3

I would do neither. There's no reason for either class to know about the other.

I would use a third class that orchestrates this work. Call it something like SQLExecutor.

I would have a method like RunQuery(query, sorter). It could then be extended to have other methods that use different kinds of sorting or parsing.

This leaves the responsibility for each piece of distinct work in distinct classes.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.