with
Returns the given value, optionally passing it through a closure first.
with(mixed $value, ?callable $callback = null): mixedParameters
| Parameter | Type | Description |
|---|---|---|
$$value | mixed | The value to return or to hand to the callback. |
$$callbackoptional | ?callable= null | Invoked with the value; its return value becomes the result. |
Return value
mixedThe value itself when no callback is given, otherwise whatever the callback returns.
Errors
Nothing of its own; any exception raised inside the callback propagates unchanged.
with() returns whatever you give it. Supply a second argument and it calls that callable on the value and returns the callable's return value instead. The whole implementation is is_null($callback) ? $value : $callback($value).
When to reach for it
Two situations. First, running several statements against a freshly constructed object without naming a variable for it — the fluent-interface pattern the documentation shows with with(new Book, function (Book $book) { ... }). Second, collapsing a one-off derivation: with($row, fn (array $r) => ...) reads better inside an array literal than a temporary used exactly once.
What trips people up
It is not tap(). tap() runs the closure and hands back the original value; with() hands back the closure's value. A closure whose last statement is $model->save(); with no return gives you null, and that is by far the most common surprise. If you wanted the object back, use tap() or add an explicit return.
The callback always runs, even for null or an empty string. If you want it skipped for blank input, that is transform().
Example
When to use it
- Run a couple of setup statements on a newly constructed object without naming a variable.
- Derive a value from an input inline inside an array literal.
- Wrap a computed expression so you can keep reading left to right.
Frequently asked questions
What is the difference between with() and tap() in Laravel?
tap() returns the value you passed in and ignores the closure's return; with() returns the closure's return value and ignores the original. Use tap() when you want to keep chaining on the object, with() when you want the transformed result.
Does with() call the closure when the value is null?
Yes. with() has no blankness check at all — the callback runs for null, empty strings, empty arrays and everything else. If you want the callback skipped for blank values, use transform(), which guards on filled().
Is with() the same as Eloquent's with() for eager loading?
No, they are unrelated. The eager-loading with() is a method on the Eloquent query builder, called as Post::with('comments'); the helper documented here is a global function that takes a value and an optional closure.
More examples
with() versus tap()
Both closures mutate the same collection, but only tap() gives it back. $withed is NULL because the closure has no return statement — this is the single most reported confusion between the two helpers.
<?php
use Illuminate\Support\Collection;
$collection = new Collection([1, 2, 3]);
// tap() returns the collection itself.
$tapped = tap($collection, function (Collection $c) {
$c->push(4);
});
// with() returns whatever the closure returns — here, nothing.
$withed = with($collection, function (Collection $c) {
$c->push(5);
});
var_dump($tapped instanceof Collection); // bool(true)
var_dump($withed); // NULLFluent setup on a new instance
This is the pattern the Laravel documentation demonstrates, with the explicit return added. Drop the return line and $book becomes null even though the model was saved correctly — the save happened, the value just was not passed back.
<?php
use App\Models\Book;
$book = with(new Book, function (Book $book) {
$book->title = 'Laravel';
$book->author_id = 7;
$book->save();
return $book; // without this, $book would be null
});
echo $book->title, "\n"; // LaravelInline derivation inside an array
Prints Array ( [name] => Ada Lovelace [age_in_1850] => 35 ). Each value is computed where it is used, so there is no temporary variable that exists only to be read once on the next line.
<?php
$row = ['first' => 'Ada', 'last' => 'Lovelace', 'born' => 1815];
$payload = [
'name' => with($row, fn (array $r) => trim($r['first'].' '.$r['last'])),
'age_in_1850' => with($row['born'], fn (int $y) => 1850 - $y),
];
print_r($payload);
Discussion