Confused between array and objects in Laravel

2020-02-22 12:46发布

问题:

I'm learning Laravel and it uses OOPS concepts. Now I'm finding it hard to understand the real difference between array and objects. I actually know what an array and object is.

Array can hold more than one variable where as an object is an independent entity which has its own arguments and methods. We usually use foreach loop to loop through them.

In laravel, data is returned in the form of model instance as object. When the query response has multiple results, then data is returned in the form of an array which contains objects. I was trying to understand Collection Class used in laravel.

Codebright reference says

The Collection class itself, is merely a wrapper for an array of objects, but has a bunch of other interesting methods to help you pluck items out of the array.

Now coming back to my confusion. I was using different methods like all() and first() methods to fetch the result. But sometimes when i used arrow (->) to fetch the data using a foreach loop, from an object (contained in an array), it showed an error that says something like it is a non object. Then I used square brackets and the data was displayed.

I know we use [] to fetch data from arrays and we use -> to fetch data from objects. But I'm still confused about Laravel. Can someone clearly state the difference between them in reference to Collection class used in Laravel?

Edit:: The confusion began while using this code:

foreach($self_conversations as $self_conversations_fetch){
    //fetching each conversation id
    $conversation_id = Conversation::find($self_conversations_fetch->conversation_id);
    $user_id = array();

//fetching each conversation member's id
    foreach($conversation_id->conversationsMember as $conversationmembers)
        $user_id[] = $conversationmembers->user_id;

        $self_id = User::where('email', Session::get('email'))->first()->id;
        $self_id_array = array($self_id);
        $friend_id_array = array_diff($user_id, $self_id_array);

        foreach($friend_id_array as $friend_id) array_push($friend_ids, $friend_id);

    $conversations_reply_obj = ConversationReply::where('conversation_id', $self_conversations_fetch->conversation_id)->orderBy('updated_at', 'desc')->first();

    $conversations_reply[] = $conversations_reply_obj['reply'];
}

As you can see, i have used square brackets to fetch the data(in the last line).

$conversations_reply[] = $conversations_reply_obj['reply'];

i was expecting arrow to work here

回答1:

Actually the Collection class is a wrapper object which returns a collection of objects. For example, if you have a Model for example, User then you may use it in various ways, to get all records you may use User::all() and to get a single record you may use User::find(1) and there are other ways as well.

If you use all(), get() methods then you'll get a collection object, it means a collection of User models when you use these methods on User model and remember all() and get() always returns a collection of models even if there is only one model in it, so check this examaple:

$users = User::all(); // returns a collection

You may use first() method of Collection object like this:

$users = User::all();
$users->first();

Or directly just:

$user = User::first();

You may also use last to get the last item/model from the collection. You may also use get() like this:

$users = User::all();
$users = User::get(0) // to get first item/model
$users = User::get(1) // to get second item/model

You may also use a loop like this:

$users = User::get(); // same as all
// pass the collection to the view
return View::make('users.index')->with('users', $users);

Now in your views/users/index.blade.php view you may use a loop like this:

@foreach($users as $user)
    {{ $user->username }}<br />
    {{ $user->email }}<br />
@endforeach

It's important to knoe that, all() and get() methods returns a collection and first() and find(id) returns a single model object, so if you have a single model then you may directly use it like this:

$user = user::find(1); // 1 is id for example
return View::make('users.index')->with('user', $user);

In your view you may use:

{{ $user->email }}

You may use an object using -> for example $user->name and an array using $user['name'] but in this case you may use both syntax because Laravel's Eloquent/Model implements ArrayAccess (along with others) interface so every model that extends Eloquent could be used using both array and object syntax to access properties. So, following is possible:

$user = User::where('username', 'me')->get();
return View::make('users.index')->with('user', $user);

In the view you may use:

{{ $user->name }}
{{ $user['name'] }}

For better understanding of the Collection class and it's methods check the source code, you may find it at vendor/laravel/framework/src/Illuminate/Database/Eloquent/Collection.php of your local installation and it extends Illuminate/Support/Collection.php class. Check both classes. You may also read this article, it'll help you more.



回答2:

I think I know the source of your problem, as I've been having to work around it. If you are using the arrow notation on a model object and there is no record in the relationship, then you'll get the "non-object" error. For example, if you have the line

$student->school->school_name

and a given $student doesn't have a school object, you'll get the non-object error. I typically add checks for empty($student->school) or empty($student->school_id) or the like to avoid this when I run into it (or heaven forbid forsee the problem when doing my initial coding pass).

EDIT: So, to clarify, Laravel doesn't say "oh, there's a relationship there, so school is an object which happens to be empty, so I'll return null for school_name", it says "there's no school, so ->school_name is an invalid call to an object property"