skip to content

Everyday Helpers

The general-purpose tools Laravel ships beside HTTP and the database: collections, Str and Number, the Http client, and Process. Interviewers expect idiomatic use over hand-rolled code.

on this pageshow

explore

questions

27

In Laravel, what does collect() return, and does chaining map() and filter() on it change the original collection?

level: juniorimportance: must knowfreq 72%

answer

  1. a wrapper class, not an array
  2. Illuminate\Support\Collection
  3. each call hands back a new instance
  4. filter() with no callback drops falsy
  5. objects inside are shared, not copied

basics

~10 s

collect() wraps an array or iterable in an Illuminate\Support\Collection. map() and filter() each return a new Collection and leave the original untouched, which is what makes long chains safe to write.

solid answer

~40 s

`collect($items)` is a helper for `new Collection($items)`: it wraps an array (or any iterable, a single scalar, or `null` for an empty one) in `Illuminate\Support\Collection`. Most methods, including `map()`, `filter()` and `reject()`, build their result with `new static(...)`, so every step of a chain returns a fresh collection and the variable you started from keeps its items. That is why `$raw->filter(...)->map(...)` reads as a pipeline and why a bare `$raw->map(...)` with no assignment does nothing useful. `filter()` without a callback drops every falsy item (`0`, `''`, `null`, `false`, `[]`). The copy is shallow: if the items are objects, the old and new collections point at the same objects.

code

php · 13 lines
php
<?php

use Illuminate\Support\Collection;

$raw = collect([4, 0, 5, null, 3]);

$kept = $raw->filter();            // [0 => 4, 2 => 5, 4 => 3]
$doubled = $kept->map(fn (int $s) => $s * 2);

$raw->map(fn ($s) => $s * 100);   // result discarded: $raw is unchanged

var_dump($raw->count());          // int(5)
var_dump($doubled instanceof Collection); // bool(true)

go deeper

for a junior

Recall that collect() gives you an Illuminate\Support\Collection and that map(), filter() and reject() return new collections, so you must assign or chain the result.

for a middle

Explain the new static() contract, what filter() drops without a callback, and why the copy is shallow when the items are models or other objects.

for a senior

Point out where shared object handles let a supposedly pure chain mutate data used elsewhere, and set a team habit of returning new values from map callbacks.

for a principal

Weigh collection pipelines against plain loops for readability and allocation cost in hot paths, and decide where the codebase needs explicit copies rather than trusting immutability.

## What collect() gives you `collect()` is a global helper defined in the framework's collections package. Its body is one line: it returns `new Collection($value)`, where `Collection` is **`Illuminate\Support\Collection`**. The constructor normalises whatever you pass: - an **array** is stored as-is, keys included; - another **collection**, an `Arrayable` object or any **iterable** is converted to an array first; - a **scalar** (a string, an int) is wrapped into a one-item array; - **`null`** becomes an empty collection, so `collect()` and `collect(null)` are both safe starting points. Eloquent queries hand you a subclass, `Illuminate\Database\Eloquent\Collection`, when you call `get()`, so everything below applies to query results too. ## Returning a new instance: the default contract The Laravel docs put it plainly: in general, collections are **immutable** — each method returns an entirely new `Collection` instance. Internally, `map()`, `filter()`, `reject()` and most of their siblings call a protected `newInstance()` helper that runs `new static($items)`. Two consequences follow: 1. **Chaining is safe.** Every arrow in `$answers->filter(...)->map(...)->sortBy(...)` works on the previous step's result, never on `$answers` itself. 2. **Forgetting to assign is a silent no-op.** `$answers->map(fn ($a) => $a['score'] * 10);` computes a new collection and throws it away; `$answers` is unchanged. A handful of methods break the rule on purpose — `transform()`, `push()`, `put()`, `forget()`, `pop()` and a few others change the collection in place. Knowing that list is its own interview question; for the everyday screen, the point is that `map` and `filter` are *not* on it. ## map(), filter() and reject() in detail | Method | Callback receives | Returns | Typical use | |---|---|---|---| | `map($cb)` | `($value, $key)` | new collection of the callback's return values, **same keys** | reshape each item | | `filter($cb = null)` | `($value, $key)` | new collection of items where the callback returned truthy | keep what matches | | `reject($cb)` | `($value, $key)` | new collection of items where the callback returned falsy | drop what matches | Details worth saying out loud in an interview: - **`filter()` with no callback** falls back to PHP's `array_filter`, removing every falsy value: `0`, `'0'`, `''`, `null`, `false` and empty arrays. - **`reject()`** is `filter()` with the test inverted; passing a plain value instead of a closure rejects items loosely equal to it. - The callback's second argument is the **key**, which is handy for associative data such as survey answers keyed by respondent ID. ## Shallow, not deep "Returns a new collection" describes the **container**, not the things inside it. When a collection holds objects — Eloquent models, DTOs — the new collection holds the **same object handles**. A `filter()` result and its source therefore share models: change `$model->score` through one and the other sees it. Arrays and scalars are copied by value, so for plain arrays the question never comes up. ## Getting a plain array back - `all()` returns the underlying PHP array exactly as stored. - `toArray()` also converts nested `Arrayable` items (models, other collections) to arrays. - Returning a collection from a route or controller lets Laravel serialise it to JSON for you. ## A worked example ```php <?php $answers = collect([ ['department' => 'Sales', 'score' => 4], ['department' => 'IT', 'score' => 0], ['department' => 'Sales', 'score' => 5], ]); $scored = $answers ->filter(fn (array $a) => $a['score'] > 0) ->map(fn (array $a) => $a['score'] * 20); // $answers still holds all three rows // $scored holds [0 => 80, 2 => 100] ``` The original `$answers` still has three rows, and `$scored` is a separate collection. Notice the keys `0` and `2` in the result: `filter()` keeps the original keys, which matters as soon as the result is serialised to JSON. ## Why interviewers ask this The question checks two things at once: that the candidate knows the collection is a **class with a fluent API** rather than syntax sugar over arrays, and that they understand **which calls produce new values**. Candidates who believe `map()` edits in place write code that works by accident until someone reuses the source collection further down the method.

  • If map() returns a new collection, can a map callback still change the original items?
    Yes, when the items are objects. The new collection is a new container, but it holds the same object handles, so `$answer->score = 0` inside the callback changes the model that the original collection also holds. Return a new value or clone the object inside the callback when you need a real copy.
  • What is the difference between all() and toArray() on a Laravel collection?
    `all()` returns the internal PHP array exactly as stored, so Eloquent models stay model objects. `toArray()` walks the items and converts anything `Arrayable` — models, nested collections — into plain arrays, which is what you want before encoding or comparing structures.

saying these in an interview costs you the question

  • Says map() rewrites the collection it was called on.
  • Calls $collection->map(...) without assigning the result and expects a change.
  • Thinks collect() returns a plain PHP array with extra functions.
  • Believes filter() with no callback returns every item unchanged.
  • Assumes a new collection deep-copies the Eloquent models inside it.
open as a page

In Laravel's HTTP client, does Http::get() throw an exception when the server answers 404 or 500, and how do you make it throw?

level: juniorimportance: must knowfreq 62%

basics

~10 s

No. Laravel's Http client returns a Response for 4xx and 5xx statuses; check successful() or failed(), or call throw() to raise RequestException. Timeouts and refused connections are different: they always throw ConnectionException.

open as a page

In Laravel, what is the difference between a Collection and a LazyCollection, and when would you reach for the lazy one?

level: juniorimportance: must knowfreq 42%

basics

~20 s

A Collection holds every item in a PHP array; a LazyCollection holds a source, usually a generator function, and pulls items one at a time only when enumerated. Use it when the data is too big for memory.

open as a page

In Laravel, what does Process::run() return when an external thumbnail command exits with a non-zero code, and how do you turn that into an exception?

level: juniorimportance: must knowfreq 42%

basics

~10 s

Process::run() returns an Illuminate\Process\ProcessResult whatever the exit code: failed() is true and exitCode() holds the code. Chain throw() to raise ProcessFailedException. Running past the 60-second default timeout always throws ProcessTimedOutException.

open as a page

In Laravel, what do now() and today() return, and how do you show an order's age as '3 days ago' with Carbon?

level: juniorimportance: must knowfreq 50%

basics

~10 s

now() returns a Carbon instance for the current moment and today() one for midnight today, both created through the Date facade. $order->created_at->diffForHumans() renders a past date relative to now, such as '3 days ago'.

open as a page

In Laravel, what do Str::slug(), Str::limit() and Str::mask() do to a product title and a card number on an order page?

level: juniorimportance: must knowfreq 55%

basics

~20 s

Str::slug() turns a title into a lower-case, dash-separated URL segment; Str::limit() cuts text to a character count and appends '...'; Str::mask() replaces part of a string with a repeated character, such as all but the last four card digits.

open as a page

With Laravel collections, how do pluck(), keyBy() and groupBy() differ when summarising survey answers by department?

level: middleimportance: must knowfreq 58%

basics

~10 s

pluck() extracts one field per item, keyBy() indexes whole items by a field with one item per key, and groupBy() builds a collection of sub-collections, one per distinct value, so duplicates are kept.

open as a page

In Laravel's HTTP client, how does Http::retry(3, 100) count attempts, which failures does it retry, and what does its when-callback do?

level: middleimportance: must knowfreq 50%

basics

~20 s

Http::retry(3, 100) makes at most three attempts, sleeping 100 ms between them. Without a when-callback it retries every failed status and connection error; the callback decides per failure. Exhausted attempts throw RequestException unless throw: false is passed.

open as a page

In Laravel, when does a closure passed to defer() run, when is it skipped, and when should the work be a queued job instead?

level: seniorimportance: must knowfreq 38%

basics

~20 s

defer() runs a closure after the response is sent, or after a command or queued job ends, and only on success (status below 400) unless always() is chained. Nothing retries it, so work that must happen belongs in a queued job.

open as a page

In Laravel's HTTP client, what body does Http::post() send by default, and how do asForm(), attach(), withToken() and acceptJson() change the request?

level: juniorimportance: should knowfreq 44%

basics

~20 s

Http::post() encodes its array as a JSON body with Content-Type application/json. asForm() sends URL-encoded form fields, attach() switches to multipart with a file part, withToken() adds an Authorization: Bearer header, and acceptJson() sets only the Accept header.

open as a page

Why does a Laravel collection returned after filter() or sortBy() sometimes serialize to a JSON object instead of an array?

level: middleimportance: should knowfreq 45%

basics

~20 s

filter(), reject(), sortBy(), unique() and partition() keep each item's original key. Once the keys are no longer 0, 1, 2 in order, json_encode emits an object; calling values() last re-indexes the collection so it serializes as an array.

open as a page

What are higher-order messages on Laravel collections, such as $responses->each->markReviewed(), and where do they stop working?

level: middleimportance: should knowfreq 30%

basics

~10 s

A higher-order message is a shortcut where a collection method name, used as a property, forwards the next property read or method call to every item: $responses->sum->score or $responses->each->markReviewed().

open as a page

In Laravel, how do Http::macro() and baseUrl() build a reusable client for one third-party API, and why does Http::withToken($t); Http::get($url) lose the token?

level: middleimportance: should knowfreq 30%

basics

~10 s

Register Http::macro('carrier', fn () => Http::baseUrl(...)->withToken(...)->timeout(5)) in a service provider's boot(), then call Http::carrier()->get('rates'). Each static Http:: call builds a new PendingRequest, so configuration lasts only within one chain.

open as a page

How would you use Laravel's LazyCollection::make() to count visits per country in a 4 GB access log without exhausting memory?

level: middleimportance: should knowfreq 38%

basics

~20 s

Pass LazyCollection::make() a closure that opens the file and yields one line at a time, then chain map() to extract the country and countBy() to tally; only one line plus one counter per country is held in memory.

open as a page

In Laravel's Process facade, when do you use start(), Process::pool() or Process::pipe() instead of run(), and what does each give back?

level: middleimportance: should knowfreq 28%

basics

~20 s

start() launches a command in the background and returns an InvokedProcess to poll or wait() on. Process::pool() starts several commands at once and wait() returns their results by key. Process::pipe() feeds each command's output into the next and returns one result.

open as a page

In Laravel, what does Str::of() return, and why does comparing the end of a Stringable chain with === to a string fail?

level: middleimportance: should knowfreq 38%

basics

~10 s

Str::of($value) and str($value) return an Illuminate\Support\Stringable object whose methods each return a new Stringable. It is not a PHP string, so === against a string is false; call toString() or use exactly().

open as a page

In Laravel, when would you pick Str::ulid() or Str::uuid7() over Str::uuid() for order identifiers, and what do they return?

level: middleimportance: should knowfreq 35%

basics

~10 s

Str::uuid() gives a random version-4 UUID; Str::uuid7() and Str::ulid() start with a timestamp, so new IDs sort in creation order and index better. All three return objects, so cast them to strings.

open as a page

In Laravel, which collection methods such as transform() and push() change the collection in place, and what bugs does that cause in shared code?

level: seniorimportance: should knowfreq 35%

basics

~10 s

transform(), push(), put(), prepend(), forget(), pop(), shift(), pull() and splice() modify the collection itself. Because collections are objects passed by handle, a helper calling them changes the caller's data too.

open as a page

In Laravel 13, how does Http::pool() send requests concurrently, what does it return when one request times out, and why can't you chain withToken() before it?

level: seniorimportance: should knowfreq 30%

basics

~20 s

Http::pool() runs the requests added to its Pool concurrently and returns an array keyed by position or as() name. A timed-out entry holds a ConnectionException object instead of throwing, and headers must be set on each pooled request.

open as a page

A Laravel checkout page calls a shipping carrier's rate API with Http::retry(3, 1000)->get() and no timeout; when the carrier hangs, what happens and how do you fix it?

level: seniorimportance: should knowfreq 40%

basics

~20 s

Laravel's default 30-second timeout applies per attempt, so retry(3, 1000) can hold a PHP worker about 92 seconds per checkout. Set short timeout() and connectTimeout(), retry only transient failures, and fall back or move the call off the request.

open as a page

Which Laravel LazyCollection methods stay lazy, and which quietly pull every item into memory, such as sortBy() or groupBy()?

level: seniorimportance: should knowfreq 32%

basics

~20 s

map, filter, reject, take, skip, chunk, values and tapEach stream one item at a time. Methods that need the whole set — sortBy, sort, groupBy, reverse, shuffle, split, median, partition — collect everything into an eager array first.

open as a page

Why does enumerating the same Laravel LazyCollection twice re-run its source, and what does remember() trade to avoid that?

level: seniorimportance: should knowfreq 25%

basics

~20 s

Each enumeration calls the generator function again, so a second pass re-reads the file or re-runs the query. remember() caches items as they are first pulled and replays them later, trading memory for fewer reads or queries.

open as a page

In Laravel 13, how does Concurrency::run() execute three slow API calls at once with the default process driver, and what does that require of the closures?

level: seniorimportance: should knowfreq 30%

basics

~20 s

With the process driver, Concurrency::run() serializes each closure, runs it in its own PHP process through a hidden Artisan command, and unserializes the results by position or key. Closures, captured variables and return values must be serializable.

open as a page

In Laravel, why does $returnBy = $placedAt->addDays(30) also move $placedAt, and how does Date::use(CarbonImmutable::class) prevent it?

level: seniorimportance: should knowfreq 30%

basics

~10 s

Laravel's default Carbon class is mutable: addDays() changes the object and returns it, so both variables hold one moved date. Date::use(CarbonImmutable::class) makes now(), today() and Eloquent dates immutable, so arithmetic returns new objects.

open as a page

In Laravel, why is rendering a customer's order note with Str::markdown() risky by default, and which options make it safe?

level: seniorimportance: should knowfreq 28%

basics

~20 s

Str::markdown() passes raw HTML and javascript: links through by default, and its output must be printed unescaped, so user Markdown becomes an XSS hole. Pass html_input => 'strip' and allow_unsafe_links => false, or purify the HTML.

open as a page

In Laravel, how do you add a custom method to every collection with Collection::macro(), and where should the macro be registered?

level: middleimportance: nice to knowfreq 25%

basics

~20 s

Call Collection::macro('name', fn) with a closure in a service provider's boot() method; the Macroable trait binds the closure to the collection, so $this inside it is the instance and the method works on every Collection, including Eloquent ones.

open as a page

How does takeUntilTimeout() on a Laravel LazyCollection keep a scheduled task inside its time slot, and where can it still overrun?

level: middleimportance: nice to knowfreq 18%

basics

~10 s

takeUntilTimeout($deadline) yields items until the current time reaches the deadline, then stops pulling. It checks after each item is handed on, so an item in progress always finishes, and a slow one can overrun.

open as a page