DNAngel's avatar

Laravel 5: Trying to get property of non-object

Received this error

ErrorException in b836960d8afb261ac0cd337b0ac052bd22c615b4.php line 2:
Trying to get property of non-object (View: C:\wamp64\www\peepbox\resources\views\timeline\partials\friendtofriendstatusblock.blade.php) (View: C:\wamp64\www\peepbox\resources\views\timeline\partials\friendtofriendstatusblock.blade.php)

HomeController.php

class HomeController extends Controller {

    public function index(Request $request) {

        if(Auth::check()) {

            $statuses = Status::NotReply()->NotFriendPostUserProfile()->where(function($query) {
                return $query->where('user_id', Auth::user()->id)
                            ->orWhereIn('user_id', Auth::user()->friends()->lists('id'));
            })->orderBy('created_at', 'desc')->paginate(4);

            $friendPosts = Status::NotReply()->FriendPostUserProfile()->where(function($query) {
                return $query->where('user_id', Auth::user()->id)
                            ->orWhereIn('user_id', Auth::user()->friends()->lists('id'));
            })->orderBy('created_at', 'desc')->paginate(4);


            if($request->ajax()) {

                return view('timeline.ajax.index')->with('statuses', $statuses)->with('friendPosts', $friendPosts)->render();
            }

            return view('timeline.index')->with('statuses', $statuses)->with('friendPosts', $friendPosts);
        }

        return view('home');
    }
}

timeline/indexx.blade.php

@extends('templates.default')

@section('content')
<div class="row">
    <div class="col-lg-6">
        <form role="form" action="{{ route('post.status') }}" method="post">
            <div class="form-group{{ $errors->has('status') ? ' has-error' : '' }}">
                <textarea placeholder="What's up {{ Auth::user()->getFirstNameOrUsername() }}?" name="status" class="form-control" rows="2"></textarea>
                @if($errors->has('status'))
                    <span class = "help-block">{{ $errors->first('status') }}</span>
                @endif
            </div>
            <button type="submit" class="btn btn-default">Post status</button>
            <input type = "hidden" name = "_token" value = "{{ Session::token() }}">
        </form>
        <hr>
    </div>
</div>

<div class="row">
    <div class="col-lg-5">
        @if(!$statuses->count())
            <p>There's nothing in your timeline yet.</p>
        @else
            @foreach($statuses as $index => $status)
                @include('timeline.partials.statusblock')
                @include('timeline.partials.friendtofriendstatusblock')
            @endforeach
            {{ $statuses->render() }}
            {{ $friendPosts->render() }}

        @endif
    </div>
</div>
@stop
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

<script>

$document.ready(function() {

    $('body').on('click', '.pagination a', function(e) {

        e.preventDefault();
        var page = $(this).attr('href');
        
        $.get(page, function(data) {
            $('.statuses').html(data);
        });
    });
});
    
</script>

timeline/partial/friendtofriendstatusblock.blade.php

<div class="media">
    <a class="pull-left" href="{{ route('profile.index', ['username' => $friendPosts[$index]->user->username]) }}">
        <img class="media-object" alt="{{ $friendPosts[$index]->user->getNameOrUsername() }}" src="{{ $friendPosts[$index]->user->getAvatarUrl() }}">
    </a>
    <div class="media-body">
        <h4 class="media-heading"><a href="{{ route('profile.index', ['username' => $friendPosts[$index]->user->username]) }}">{{ $friendPosts[$index]->user->getNameorUsername() }}</a></h4>
        <p>{{ $friendPosts[$index]->body }}</p>
        <ul class="list-inline">
            <li>{{ $friendPosts[$index]->created_at->diffForHumans() }}</li>
            @if($friendPosts[$index]->likes->where('user_id', Auth::user()->id)->count() === 1)
                <li><a href="{{ route('unlike.status', ['status_id' => $friendPosts[$index]->id]) }}">Unlike</a></li>
            @elseif(Auth::user()->isFriendsWith($friendPosts[$index]->user) || Auth::user()->id === $friendPosts[$index]->user->id)
                <li><a href="{{ route('like.status', ['status_id' => $friendPosts[$index]->id]) }}">Like</a></li>
            @endif
            @if($friendPosts[$index]->likes->count() !== 0)
                <li>{{ $friendPosts[$index]->likes->count() }} {{ str_plural('like', $friendPosts[$index]->likes->count()) }}</li>
            @endif
        </ul>
        @foreach($friendPosts[$index]->replies as $reply)
            <div class="media">
                <a class="pull-left" href="{{ route('profile.index', ['username' => $reply->user->username]) }}">
                    <img class="media-object" alt="{{ $reply->user->getNameOrUsername() }}" src="{{ $reply->user->getAvatarUrl() }}">
                </a>
                <div class="media-body">
                    <h5 class="media-heading"><a href="{{ route('profile.index', ['username' => $reply->user->username]) }}">{{ $reply->user->getNameOrUsername() }}</a></h5>
                    <p>{{ $reply->body }}</p>
                    <ul class="list-inline">
                        <li>{{ $reply->created_at->diffForHumans() }}</li>
                        @if($reply->likes()->where('user_id', Auth::user()->id)->count() > 0)
                            <li><a href="{{ route('unlike.status', ['status_id' => $reply->id]) }}">Unlike</a></li>
                        @elseif(Auth::user()->isFriendsWith($friendPosts[$index]->user)  || Auth::user()->id === $reply->user->id || Auth::user()->id === $friendPosts[$index]->user->id)
                            <li><a href="{{ route('like.status', ['status_id' => $reply->id]) }}">Like</a></li>
                        @endif
                        @if($reply->likes->count() !== 0)
                            <li>{{ $reply->likes->count() }} {{ str_plural('like', $reply->likes->count()) }}</li>
                        @endif
                    </ul>
                </div>
            </div>
        @endforeach
        
        <form role="form" action="{{ route('reply.status', ['status_id' => $friendPosts[$index]->id, 'username' => $friendPosts[$index]->user->username]) }}" method="post">
            <div class="form-group{{ $errors->has("reply-{$friendPosts[$index]->id}") ? ' has-error' : '' }}">
                <textarea name="reply-{{ $friendPosts[$index]->id }}" class="form-control" rows="2" placeholder="Reply to this status"></textarea>
                @if($errors->has("reply-{$friendPosts[$index]->id}"))
                    <span class="help-block">{{ $errors->first("reply-{$friendPosts[$index]->id}") }}</span>
                @endif
            </div>
            <input type="submit" value="Reply" class="btn btn-default btn-sm">
            <input type="hidden" name="_token" value="{{ Session::token() }}">
        </form>
    </div>
</div>

I think the problem is because of this @foreach($statuses as $index => $status), and causes error on this ['username' => $friendPosts[$index]->user->username] which is in friendtofriendstatusblock.blade.php

0 likes
20 replies
davorminchorov's avatar

This means that one of the queries is returning null or the result you are looking for is returning null, so you check the status of the variables using dd() in your controller.

DNAngel's avatar

Nope, none of them returned null. I checked each of them, and they did return values. I deleted some of the parts in the script below, but it's giving me the same error.

timeline/partial/friendtofriendstatusblock.blade.php

<div class="media">
    <a class="pull-left" href="{{ route('profile.index', ['username' => $friendPosts[$index]->user->username]) }}">
        <img class="media-object" alt="{{ $friendPosts[$index]->user->getNameOrUsername() }}" src="{{ $friendPosts[$index]->user->getAvatarUrl() }}">
    </a>
    <div class="media-body">
        <h4 class="media-heading"><a href="{{ route('profile.index', ['username' => $friendPosts[$index]->user->username]) }}">{{ $friendPosts[$index]->user->getNameorUsername() }}</a></h4>
        <p>{{ $friendPosts[$index]->body }}</p>
        <ul class="list-inline">
            <li>{{ $friendPosts[$index]->created_at->diffForHumans() }}</li>
        </ul>

    </div>
</div>
DNAngel's avatar

I meant I deleted the rest of it and left only the body and created_at in the file. They both did give me values with the dd(), but when I re-ran the script below it gave me the same error.

<div class="media">
    <a class="pull-left" href="{{ route('profile.index', ['username' => $friendPosts[$index]->user->username]) }}">
        <img class="media-object" alt="{{ $friendPosts[$index]->user->getNameOrUsername() }}" src="{{ $friendPosts[$index]->user->getAvatarUrl() }}">
    </a>
    <div class="media-body">
        <h4 class="media-heading"><a href="{{ route('profile.index', ['username' => $friendPosts[$index]->user->username]) }}">{{ $friendPosts[$index]->user->getNameorUsername() }}</a></h4>
        <p>{{ $friendPosts[$index]->body }}</p>
        <ul class="list-inline">
            <li>{{ $friendPosts[$index]->created_at->diffForHumans() }}</li>
        </ul>

    </div>
</div>
DNAngel's avatar

Code that involves this line $friendPosts[$index] is giving that error mentioned in the first post. However, I dd() each of the code that involves $friendPosts[$index], and it gives value. I don't understand what's going on.

tykus's avatar

But is the value of $friendPosts[$index] an object?

davorminchorov's avatar

It looks like it's not an object but a value of an array. The use of $friendPosts[$index] is most likely wrong. You should be able to access stuff on it without the need for [$index], whatever that is.

Do a foreach loop and display the data like so:

@foreach($friendPosts $as $friendPost)
    {{ $friendPost->created_at->diffForHumans }} // or whatever field you need to display.
@endforeach
DNAngel's avatar

Yes, the code above did display the time. I don't understand why the way I used it is wrong. I want to run two different arrays in one foreach loop. This is why I did @foreach($statuses as $index => $status), $status and $friendPosts[$index].

Snapey's avatar

This sort of error occurs where dealing with a collection containing objects and relations where one of the relations does not exist.

If you dd within a foreach loop, you stop on the first record and it looks fine, when the error is really with the 5th record or similar.

However, the error here (in the original post) ErrorException in b836960d8afb261ac0cd337b0ac052bd22c615b4.php line 2: so really early in the output. Probably related to something like the page title?

Open up the file b836960d8afb261ac0cd337b0ac052bd22c615b4.php in the storage\framework\views folder and check line 2

1 like
DNAngel's avatar

Line 2 from ErrorException in b836960d8afb261ac0cd337b0ac052bd22c615b4.php

<a class="pull-left" href="<?php echo e(route('profile.index', ['username' => $friendPosts[$index]->user->username])); ?>">
Snapey's avatar

Do you have some dodgy data in the database, eg a friendPost that is not attributed to a user?

Can you explain the purpose of $index?

DNAngel's avatar

I dd() the $friendPosts[$index]->user->username, and it did give me a value.

Regarding the $index, I was trying to do foreach for two different arrays. I wanna output the status post and the friendPost on timeline. So, with the $index, that allows me to output two different arrays in the same foreach.

@foreach($statuses as $index => $status)
 @include('timeline.partials.statusblock')
 @include('timeline.partials.friendtofriendstatusblock')
@endforeach
Snapey's avatar

As mentioned, dd will stop on the first loop. The data might look fine there. Your code might be stopping on the second loop, or fifth, or fiftieth.

So, with the $index, that allows me to output two different arrays in the same foreach.

Thats fine as long as they are in sync, and that you have the same number of records in each set

DNAngel's avatar

I see. Is there other options for the arrays that do not have the same length?

Snapey's avatar

Better to get the data in the best format for output. Concentrate on getting one set of data merged (in date order, if appropriate). Then for each status you can decide if it needs slightly different output.

DNAngel's avatar

Ah... merge. Okay, will try that.

DNAngel's avatar
$statuses = Status::NotReply()->NotFriendPostUserProfile()->where(function($query) {
                return $query->where('user_id', Auth::user()->id)
                            ->orWhereIn('user_id', Auth::user()->friends()->lists('id'));
            });

            $friendPosts = Status::NotReply()->FriendPostUserProfile()->where(function($query) {
                return $query->where('user_id', Auth::user()->id)
                            ->orWhereIn('user_id', Auth::user()->friends()->lists('id'));
            });

I tried merging the two arrays above as the following:

$collection = collect($statuses);
$allStatuses = $collection->merge($friendPosts)->all();

When I dd($allStatuses), it shows me like the one at below. I don't see any values from the database.

array:8 [▼
  "\x00*\x00query" => Builder {#184 ▶}
  "\x00*\x00model" => Status {#185 ▶}
  "\x00*\x00eagerLoad" => []
  "\x00*\x00macros" => []
  "\x00*\x00onDelete" => null
  "\x00*\x00passthru" => array:11 [▶]
  "\x00*\x00scopes" => []
  "\x00*\x00removedScopes" => []
]

I think the way that I merged them is wrong.

Snapey's avatar

I think you merged two query builder instances since you didn't ->get() any results before the merge?

DNAngel's avatar

Yes, I missed the ->get(). Thanks.

$collection = collect($statuses->get());
$allStatuses = $collection->merge($friendPosts->get())->sortByDesc('created_at')->forPage(2,5);

The code above does not give me the second page. Is there a function that could work like paginate(n) that could automatically detect the the length of an array and assign n number of things per page ?

shaktijadon13's avatar

the solution for

(2/2) ErrorException

Trying to get property of non-object is:;:

My previous code :::

$fl = App\test::find(1); this throws the above error

use this $fl = App\test::find([1]); as array of objects

Please or to participate in this conversation.