Home > Net >  Return collection of one without "Trying to get property of non-object" error
Return collection of one without "Trying to get property of non-object" error

Time:02-01

I have a SearchController where I check a search term against two tables, first for exact matches (followed by a redirect table to the relevant manufacturer page) and then for partial matches - four conditions in total. All of these conditions work except the last one, probably because it often needs to return just one result inside of a collection.

I need this to be the case as I would like to do $results->slug, $results->name, etc. throughout the view no matter which search condition is being triggered. Currently I'm able to do this to access the search results of all the conditions except the third one.

Search Controller class, where everything but the third condition is working as it should:

class SearchController extends Controller
{
        public function index() {
            if (request("search")) {

            # Works as expected
            $exact_terms = SearchTerm::with("manufacturer")->where('term', request("search"))->get();
            if($exact_terms->isNotEmpty()) {
                echo "Exact search term match!";
                $results = $exact_terms;

                foreach ($results as $result) {
                    $slug = $result->manufacturer->slug;
                }

                return redirect()->action([ManufacturerController::class, 'index'], ["manufacturer" => $slug]); 
            }

            # Works as expected
            $exact_make = Manufacturer::where('slug', request("search"))->get();
            if($exact_make->isNotEmpty()) {
                echo "Exact manufacturer match!";
                $results = $exact_make;

                foreach ($results as $result) {
                    $slug = $result->slug;
                }
                return redirect()->action([ManufacturerController::class, 'index'], ["manufacturer" => $slug]); 
            }

            # Doesn't work
            $search_terms = SearchTerm::with("manufacturer")->where('term', "like", '%' . request("search") . '%')->get()->unique("manufacturers");
            if($search_terms->isNotEmpty()) {
                echo "Search term match!";
                foreach ($search_terms as $search_term) {
                    $search_term = $search_term->manufacturer;
                }
                $results = collect($search_term);
            } 

            # Works as expected
            $search_make = Manufacturer::where('slug', 'like', '%' . request("search") . '%')->get();
            if($search_make->isNotEmpty()) {
                echo "Manufacturer match!";
                $results = $search_make;
            }

        $results = isset($results) ? $results : collect();
        }
        
        return view("search", [
        "manufacturer" => $manufacturer,
        "results" => $results,
    ]);
    }
}

View file:

@if($results)
       
<h1 > {{ $results->count() }} {{ $results->count() == 1 ? "result" : "results" }} found for <i>{{ request("search") }}</i></h1>

@foreach ($results as $result)

{{ $result->slug }}

@endforeach    
@else
<p><h1>Sorry! We couldn't find any results for <i>"{{ request("search") }}"</i>.</h1></p>
@endif

Result of a dd($results) when triggering the condition just before the foreach loop:

Illuminate\Support\Collection {#1406 ▼
#items: array:5 [▼
    "id" => 15
    "slug" => "ford"
    "name" => "Ford"
    "created_at" => "2022-01-28T19:53:28.000000Z"
    "updated_at" => "2022-01-28T19:53:28.000000Z"
]
#escapeWhenCastingToString: false
}

Result of a dd($result) when triggering the condition inside of the foreach loop (shows nothing from the array but the primary key):

15

CodePudding user response:

You can't add a Model to a Collection via the constructor, it will end up pulling the attributes from it since Model is Arrayable (it will call toArray on it and get the attributes/appends/relationships as an array). You could call add on the Collection to add the Model.

$results = collect()->add($search_term);

Or you can pass an array to collect which it is expecting:

$results = collect([$search_term]);

On a side note, you are doing a lot of iterating to just get the last value from a Collection to use in all of these conditions. You could call last on the Collection to get the last value, or even restrict your query to return a single result instead of an entire result set since you are literally not using any of the result set except the last record.

  •  Tags:  
  • Related