Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get first item from CakePHP 3 results object

TLDR: How do I use the first item in a results object?


After getting data from the database, I want to pull the first one out and use it separately before repeating through the remaining videos. (All in my template/view file). If it were an array, I could use something like array_shift, but so far with the object, I'm coming up empty.

First, I get the data in my Controller, and pass it to the View:

$videos = $this->Videos->find();
$this->set(compact('videos'));

Then, in the View (template file), I've tried this:

$featuredVideo = $videos{0};

Error Cannot use object of type Cake\ORM\Query as array

And this:

$featuredVideo = $videos->0;

Error: syntax error, unexpected '0' (T_LNUMBER), expecting identifier (T_STRING) or variable (T_VARIABLE) or '{' or '$'

And this:

$featuredVideo = $videos->toArray()[0];

This works (kind of), but then I have to use $featuredVideo as an Array, which is different to everywhere else, and seems non-elegant.

And this:

$featuredVideo = $videos->first();

This is awesome, but it limits the entire object to only the first, so I no longer have the rest of the videos.

And this:

$allVideos = $videos;
$featuredVideo = $videos->first();

But, apparently since it's an object, the $allVideos is just a reference to the $videos, because they both get reduced to the first video.

I realize this seems like a simple question, and it's likely a simple answer, but I have looked around, and tried the suggestions on how to get the first item from an object with the above results.

like image 984
Dave Avatar asked Dec 25 '22 20:12

Dave


1 Answers

What I failed to understand was that ->find() just returns the query object until you tell it to execute via an ->all() or a ->first() or by running it through a foreach() loop.

So, I couldn't just access the first child object, since the query hadn't yet executed to show the results.

And when I was trying to do ->first() after setting the variable above it, it was actually executing the query on the query object after setting limit to 1, hence making both only have 1.

More details here.

The answer (in code):

// Controller
$videos = $this->Videos->find()->all();
$this->set(compact('videos'));

// View
$featuredVideo = $videos->first();

More details here about when query objects are lazily evaluated.


Thanks jose_zap and marc_ for helping clarify this one for me.

like image 97
Dave Avatar answered Jan 06 '23 05:01

Dave