Home > Blockchain >  Error "Call to a member function orderBy() on null"
Error "Call to a member function orderBy() on null"

Time:11-08

I'm working on a small project using PHP / Laravel, but I got an error its about 3 days now I try to fix it by my self, but I couldn't.

this is my code :

public function getCollection()
    {
        $queryStrings = $this->getQueryStrings();

        if(count($queryStrings)){
            // dd($queryStrings);
            $filteredOrSorteredCollection = $this->sortOrFilterCollection(
                $this->queryBuilder,
                $queryStrings
            );

            return $this->collection = $this->generateResults($filteredOrSorteredCollection);
        }

        return $this->collection = $this->generateResults($this->queryBuilder);
    }

public function sortOrFilterCollection($collection, $parseInfo)
    {
        foreach($parseInfo as $key => $info){

            switch($key){
                case 'sort':
                    $this->sortCollection($collection, $info);
                    break;

                case 'search':
                    // dd($collection->toSql());
                    // dd($info);
                    $this->searchCollection($collection, $info);
                    break;

                    // need more here
            }
        }
    }

private function searchCollection($collection, $info)
    {
        $countKeys = count(array_keys($info));

        if($countKeys > 1){
            dd('error'.__METHOD__);
        }
        
        if($countKeys == 1){
            // dd(12);
            $collection->where(function($collection) use ($info) {

                foreach($this->columns as $column){

                    if(isset($column['searchable']) && $column['searchable'] == true){

                        $this->resolve($collection, $column['index'], 'like', '%' . $info['all'] . '%', 'orWhere');
                    }

                }

            });
        }

    }

private function resolve($collection, $columnName, $condition, $filterValue, $clause = 'where', $method = 'resolveQuery')
    {

        if($this->enableFilterMap && isset($this->filterMap[$columnName])){
            $this->$method($collection, $this->filterMap[$columnName], $condition, $filterValue, $clause);
            // dd('block 1');
        } else if ($this->enableFilterMap && !isset($this->filterMap[$columnName])){
            // dd('block 2');
            $this->$method($collection, $columnName, $condition, $filterValue, $clause);

        } else {
            dd('block 3');
            $this->$method($collection, $columnName, $condition, $filterValue, $clause);
        }
    }

private function resolveQuery($query, $columnName, $condition, $filterValue, $clause = 'where')
    {
        if($clause === 'whereBetween'){
            return $query->$clause($columnName, $filterValue);
        } else {
            return $query->$clause($columnName, $this->operators[$condition], $filterValue);
        }
    }

public function generateResults($queryBuilderOrCollection)
    {
        // dd($queryBuilderOrCollection);
        if($this->paginate){
            if($this->itemsPerPage > 0){
                // dd(5);
                return $this->paginateResults($queryBuilderOrCollection);
            }
        }else{
            return $this->defaultResults($queryBuilderOrCollection);
        }
    }

I tried to debug so many times using dd to trace each variable from the to the end,

By the way resovleQuery (else part ) works really fine and, I get the database result I checked using dd.

Result is always :

Call to a member function orderBy() on null

    private function paginateResults($queryBuilderOrCollection){
        // dd($queryBuilderOrCollection);
        return $this->collection = $queryBuilderOrCollection->orderBy($this->index, $this->sortOrder)->paginate($this->itemsPerPage);
    }

CodePudding user response:

Edit: On second review, try my second suggestion after my "However" below, then try the first one if that doesn't work.

In getCollection() you're passing the result of sortOrFilterCollection() to generateResults(), which calls paginateResults() where the error occurs.

$filteredOrSorteredCollection = $this->sortOrFilterCollection(
    $this->queryBuilder,
    $queryStrings
);

return $this->collection = $this->generateResults($filteredOrSorteredCollection);

However, sortOrFilterCollection() does not return anything, so $filteredOrSorteredCollection will be null. (Side note: You've got a typo with "Sortered", you probably want to change it to "Sorted".) I think you need to change sortOrFilterCollection() to return the results of the functions it's calling, which also means you can remove the break statements, like this:

public function sortOrFilterCollection($collection, $parseInfo)
{
    foreach($parseInfo as $key => $info){

        switch($key){
            case 'sort':
                return this->sortCollection($collection, $info);

            case 'search':
                // dd($collection->toSql());
                // dd($info);
                return $this->searchCollection($collection, $info);

                 // need more here
        }
    }
}

However, you're also not returning anything from searchCollection or resolve.

So, on second thought, your code might be designed to be working by modifying the $queryBuilder reference. In that case, you might actually need to change the getCollection() lines to this:

// Modify `$this->queryBuilder` object
$this->sortOrFilterCollection(
    $this->queryBuilder,
    $queryStrings
);

return $this->collection = $this->generateResults($this->queryBuilder);

I'm not sure how your code is designed to work, so either you need to add return statements to several other functions, or you shouldn't expect return values and you need to pass the queryBuilder around.

  • Related