skip to content

Fluent Strings & Dates

Laravel's Str and Number helpers, fluent Stringable chains, and Carbon dates via now() and the Date facade. Interviewers look for idiomatic formatting instead of hand-rolled string code.

on this pageshow

explore

questions

6

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%

answer

  1. Illuminate\Support\Carbon via the Date facade
  2. today() is midnight
  3. diffForHumans() adds 'ago'
  4. Carbon 3: diffInDays is a signed float
  5. optional time zone argument

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'.

solid answer

~30 s

`now($tz = null)` and `today($tz = null)` are helpers for `Date::now()` and `Date::today()`, so by default they return `Illuminate\Support\Carbon`, Laravel's subclass of `Carbon\Carbon`, in the app's time zone; `today()` is the current date at `00:00:00`. For relative labels, Eloquent timestamps are already Carbon instances, so `$order->created_at->diffForHumans()` gives `3 days ago` for a past date and `3 days from now` for a future one. For numbers, remember that Laravel 13 ships Carbon 3, where `diffInDays()` and friends return a **float** and are **signed**: `Carbon::parse('2026-09-29')->diffInDays('2026-09-26')` is `-3.0`. Pass `absolute: true` or cast when you need a positive whole number.

code

php · 11 lines
php
<?php

use App\Models\Order;

$order = Order::findOrFail($id);

$placedLabel = $order->created_at->diffForHumans(); // "3 days ago"

$ageInDays = (int) $order->created_at->diffInDays(now(), absolute: true); // 3

$isToday = $order->created_at->greaterThanOrEqualTo(today());

go deeper

for a junior

Recall that now() is the current moment, today() is midnight, both return Carbon, and diffForHumans() makes labels like '3 days ago'.

for a middle

Explain the Date facade behind the helpers, how diffForHumans() words past and future dates, and Carbon 3's signed float diffInDays().

for a senior

Catch Carbon 2 assumptions after upgrades — unsigned integer diffs — and mutation of model timestamps in date arithmetic.

for a principal

Set conventions for date handling across the codebase: helpers over native classes, explicit absolute diffs, and immutability where values are shared.

## now() and today() Both are global helpers defined in the framework's foundation helpers: - `now($tz = null)` returns `Date::now($tz)` — the **current moment**; - `today($tz = null)` returns `Date::today($tz)` — the **current date at midnight**. `Date` is Laravel's date facade over `Illuminate\Support\DateFactory`. Unless you configure otherwise, it creates **`Illuminate\Support\Carbon`**, a thin subclass of `Carbon\Carbon` that adds a few Laravel traits. Both helpers accept an optional time-zone argument; without it they use the application time zone from `config/app.php`. | Call | Example value on 2026-09-29 at 14:05 | |---|---| | `now()` | `2026-09-29 14:05:12` | | `today()` | `2026-09-29 00:00:00` | | `now()->startOfDay()` | `2026-09-29 00:00:00` (same as `today()`) | | `today()->subDays(3)` | `2026-09-26 00:00:00` | Prefer the helpers over `new DateTime()` in application code: they go through the date factory (so a global switch to immutable dates applies), and tests can freeze time for everything that uses them. ## Relative labels with diffForHumans() Eloquent timestamp columns such as `created_at` are returned as Carbon instances, so the label is one call: ```php <?php $order->created_at->diffForHumans(); // "3 days ago" $order->ships_at->diffForHumans(); // "2 days from now" $order->created_at->diffForHumans(short: true); // "3d ago" ``` How it decides the wording: 1. with no argument, it compares with **now**, adding `ago` for past dates and `from now` for future ones; 2. with another date, it says `before` or `after` that date instead; 3. `$parts` controls precision — `diffForHumans(parts: 2)` gives `3 days 4 hours ago`; 4. the language follows the configured locale; translating those labels is a localization topic. ## Numeric differences changed in Carbon 3 Laravel 13's framework requires `nesbot/carbon` `^3.8.4`. Carbon 3 changed the `diffIn*` family: | Behaviour | Carbon 2 | Carbon 3 (Laravel 13) | |---|---|---| | Return type | `int` | `float` | | Sign | absolute by default | **signed**: negative when the argument is earlier | | Signature | `diffInDays($date, $absolute = true)` | `diffInDays($date = null, bool $absolute = false, bool $utc = false)` | ```php <?php use Illuminate\Support\Carbon; Carbon::parse('2026-09-29')->diffInDays('2026-09-26'); // -3.0 Carbon::parse('2026-09-29')->diffInDays('2026-09-26', absolute: true); // 3.0 (int) now()->diffInDays($order->created_at, absolute: true); // whole days ``` Code written against Carbon 2 that does `if ($order->created_at->diffInDays() > 30)` still works for past dates, because the argument defaults to now and now is later, so the result is positive; code that calls it the other way round, `now()->diffInDays($order->created_at)`, silently turns negative and the comparison never fires. ## Formatting for display Carbon formats with PHP date format characters or with localized helpers: - `$order->created_at->format('Y-m-d H:i')` — fixed technical format; - `$order->created_at->toDateString()` — `2026-09-26`; - `$order->created_at->isoFormat('LL')` — a locale-aware long date; - `$order->created_at->toIso8601String()` — for APIs and `<time datetime>` attributes. A good order page shows the relative label and keeps the absolute timestamp available, for example in a `title` attribute, so support staff can see the exact moment when a customer says "I ordered yesterday". ## Helpers versus facade versus class | Form | Example | When it fits | |---|---|---| | helper | `now()`, `today()` | everyday application code | | facade | `Date::now()`, `Date::parse($s)` | when you want the configured date class explicitly | | class | `Carbon::parse($s)`, `Carbon::create(2026, 9, 29)` | constructing specific dates, or code that type-hints Carbon | All three end up with Carbon instances; the helper and facade forms respect a global `Date::use()` configuration, while calling a concrete class creates that class regardless. ## Pitfalls interviewers look for - **Mutation:** `Illuminate\Support\Carbon` is mutable, so after `$start = $order->created_at; $end = $start->addDays(14);` the variable `$start` has moved as well. Copy first, or configure immutable dates globally. - **Midnight versus now:** comparing a timestamp with `today()` rather than `now()` shifts results by up to a day. - **Time zones:** `now('Europe/Berlin')` changes the zone of the returned instance, not the application's; storage and zone strategy belong to PHP's date handling in general.

  • Why can now()->diffInDays($order->created_at) be negative in Laravel 13?
    Laravel 13 uses Carbon 3, where `diffInDays()` is signed and returns a float. The method measures from the receiver to the argument, so when the argument is earlier — an order created in the past — the result is negative, for example `-3.25`. Pass `absolute: true` or reverse the operands, then cast if you need an integer.
  • In Laravel, what is the difference between comparing an order's timestamp with now() and with today()?
    `now()` is the current moment; `today()` is midnight at the start of the current day. `created_at >= today()` asks whether the order was placed today at all, while `created_at >= now()->subDay()` asks whether it was placed within the last 24 hours — different answers late in the evening.

diffForHumans() is the shop assistant who says 'that was three days ago', while diffInDays() is the ledger that writes -3.0 and expects you to know which column you subtracted from which.

saying these in an interview costs you the question

  • Thinks now() returns a string or a native DateTime.
  • Believes today() returns the current time of day.
  • Assumes diffInDays() always returns a positive integer in Laravel 13.
  • Formats relative ages by hand from timestamps instead of diffForHumans().
  • Reuses one Carbon variable as the base for several addDays() calls.
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

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, 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