From 3c3ed7a4622ff41fd3916f1cf617a2d92a627ab5 Mon Sep 17 00:00:00 2001 From: Moamen Eltouny Date: Fri, 9 Oct 2026 10:57:29 +0300 Subject: [PATCH] Highlight is() checks in the documentation --- CHANGELOG.md | 6 ++++ docs/landing/01-hero.md | 6 ++-- docs/landing/02-features.md | 6 ++-- docs/landing/03-quick-look.md | 21 ++++++++------ docs/landing/04-faq.md | 4 +++ docs/sections/01-overview.md | 10 +++---- docs/sections/03-basic-usage.md | 25 +++++++++++++++++ docs/sections/06-case-checks.md | 50 +++++++++++++++++++++++++++++++-- docs/sections/10-examples.md | 27 ++++++++++++++---- 9 files changed, 128 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 24c5d7e..3e5bfaf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ All notable changes to this project will be documented in this file. +## 8.5.1 - Unreleased + +### Changed + +- Documentation puts the `is()` checks first, with a case-name-to-check table (`IN_PROGRESS` → `isInProgress()`), the names that are not checks and what to write instead, and a status-branching example. + ## 8.5.0 - 2026-10-09 ### Added diff --git a/docs/landing/01-hero.md b/docs/landing/01-hero.md index 3649c7b..6bbed3f 100644 --- a/docs/landing/01-hero.md +++ b/docs/landing/01-hero.md @@ -10,8 +10,8 @@ badges: - label: "{package.downloadsShort}+ downloads" color: blue eyebrow: "{package.name}" -title: Native enums, -highlight: a little smarter +title: Native enums that +highlight: know isActive() buttons: - label: View Full Documentation href: "{card.docsUrl}" @@ -27,4 +27,4 @@ labels: copied: Copied! --- -Add `use SmartEnum;` to any native PHP enum and get helpers for names, values, labels, options, lookup by case name, strict comparisons and `isActive()`-style checks. Your enums stay native: no base class, no code generation, no framework. +Add `use SmartEnum;` to any native PHP enum and every case can answer for itself: `$status->isActive()` for `Active`, `$order->isInProgress()` for `IN_PROGRESS`. You also get helpers for names, values, labels, options, lookup by case name and strict comparisons. Your enums stay native: no base class, no code generation, no framework. diff --git a/docs/landing/02-features.md b/docs/landing/02-features.md index 2d84e64..7e09938 100644 --- a/docs/landing/02-features.md +++ b/docs/landing/02-features.md @@ -5,6 +5,9 @@ badge: Key Features title: Everything your enums are missing subtitle: One trait, added to the enums you already have. items: + - icon: badge-check + title: isActive() for Every Case + text: "Each case gets its own check, named from the case: `isActive()` for `Active`, `isInProgress()` for `IN_PROGRESS`, `isOnHold()` for `onHold`." - icon: lines title: Names, Values & Labels text: "`names()`, `values()` and `labels()` list your cases in the shape you need." @@ -17,9 +20,6 @@ items: - icon: check-circle title: Strict Comparisons text: "`eq()`, `is()`, `isNot()`, `in()` and `notIn()` match a case, a case name or a backing value, with no type juggling." - - icon: badge-check - title: Case Checks - text: "Every case gets its own check: `$status->isActive()`, `$order->isInCooking()`." - icon: switch title: Unit & Backed Enums text: The same trait works on unit, string-backed and int-backed enums, and custom labels flow into `labels()` and `options()`. diff --git a/docs/landing/03-quick-look.md b/docs/landing/03-quick-look.md index f5c3a3f..3773934 100644 --- a/docs/landing/03-quick-look.md +++ b/docs/landing/03-quick-look.md @@ -1,22 +1,25 @@ --- view: components.packages.quick-look title: A quick look -subtitle: Add the trait to a native enum and use its helpers next to cases(), from() and tryFrom(). -file: app/Enums/Status.php +subtitle: Add the trait and every case answers its own is…() check, whatever style its name is written in. +file: app/Enums/OrderStatus.php language: php code: | use Pharaonic\SmartEnum\SmartEnum; - enum Status: string + enum OrderStatus: string { use SmartEnum; - case Pending = 'pending'; - case Active = 'active'; - case Disabled = 'disabled'; + case PENDING = 'pending'; + case IN_PROGRESS = 'in_progress'; + case OUT_FOR_DELIVERY = 'out_for_delivery'; + case Delivered = 'delivered'; } - Status::options(); // ['pending' => 'Pending', 'active' => 'Active', ...] - Status::fromName('Active')->isActive(); // true - Status::Active->in(['pending', 'active']); // true + $status = OrderStatus::IN_PROGRESS; + + $status->isInProgress(); // true + $status->isOutForDelivery(); // false + $status->in(['pending', 'in_progress']); // true --- diff --git a/docs/landing/04-faq.md b/docs/landing/04-faq.md index a3efa46..029841e 100644 --- a/docs/landing/04-faq.md +++ b/docs/landing/04-faq.md @@ -30,6 +30,10 @@ Yes. A unit enum has no backing values, so `values()`, `options()`, `hasValue()` Declare a `label()` method in the enum, or define a global `smart_enum_label()` function for every enum at once. `labels()`, `options()` and `info()` pick the change up. +## How does IN_PROGRESS become isInProgress()? + +The check is `is` plus the case name, with each underscore-separated word capitalized. A word written all in upper case is title-cased first, so `IN_PROGRESS` becomes `isInProgress()`, `PENDING` becomes `isPending()` and `onHold` becomes `isOnHold()`. + ## Will my IDE know about $status->isActive()? The `is()` checks are resolved at runtime, so add `@method bool isActive()` tags to the enum's docblock for IDEs and PHPStan. diff --git a/docs/sections/01-overview.md b/docs/sections/01-overview.md index 36707fd..8e78192 100644 --- a/docs/sections/01-overview.md +++ b/docs/sections/01-overview.md @@ -6,9 +6,12 @@ # Smart Enum -Smart, lightweight helpers for native PHP enums. Add the `SmartEnum` trait to any enum you already have and get helpers for case names, backing values, labels, select options, lookup by case name, comparisons and `is()` checks. Native methods (`cases()`, `from()`, `tryFrom()`) stay native, and the package has no base class, no generated code and no runtime dependencies. +Smart, lightweight helpers for native PHP enums. Add the `SmartEnum` trait to any enum you already have and every case can answer for itself: `$status->isActive()` for `Active`, `$order->isInProgress()` for `IN_PROGRESS`. You also get helpers for case names, backing values, labels, select options, lookup by case name and comparisons. Native methods (`cases()`, `from()`, `tryFrom()`) stay native, and the package has no base class, no generated code and no runtime dependencies. :::features +### isActive() for Every Case {icon="badge-check"} +Each case gets its own check, named from the case: IN_PROGRESS answers isInProgress(). + ### Names, Values & Labels {icon="lines"} List the case names, the backing values, or the labels of every case. @@ -21,13 +24,10 @@ Find a case by its name, the same way from() finds one by its value. ### Comparisons {icon="check-circle"} Compare a case with another case, a case name or a backing value, always strictly. -### Case Checks {icon="badge-check"} -Ask a case about itself with isActive(), isPending() and one check per case. - ### Unit & Backed Enums {icon="switch"} The same trait works on unit, string-backed and int-backed enums. ::: :::info Quick Tip -Keep using PHP's own `Status::cases()`, `Status::from()` and `Status::tryFrom()`. SmartEnum only adds what PHP doesn't have. +Write case names in the style you like. `IN_PROGRESS`, `InProgress` and `In_Progress` all get the same check, `isInProgress()`, and PHP's own `cases()`, `from()` and `tryFrom()` keep working as before. ::: diff --git a/docs/sections/03-basic-usage.md b/docs/sections/03-basic-usage.md index 8fc0c89..96e9b9b 100644 --- a/docs/sections/03-basic-usage.md +++ b/docs/sections/03-basic-usage.md @@ -50,4 +50,29 @@ $status->in([Status::Active, Status::Pending]); // true $status->isActive(); // true ``` +### Ask a case what it is + +Every case answers an `is()` check named after it. The name is built from the case name, so it reads naturally whatever style your cases use: + +```php title="app/Enums/OrderStatus.php" +enum OrderStatus: string +{ + use SmartEnum; + + case PENDING = 'pending'; + case IN_PROGRESS = 'in_progress'; + case OUT_FOR_DELIVERY = 'out_for_delivery'; + case Delivered = 'delivered'; +} +``` + +```php +$status = OrderStatus::IN_PROGRESS; + +$status->isPending(); // false +$status->isInProgress(); // true +$status->isOutForDelivery(); // false +$status->isDelivered(); // false +``` + See [Static Methods](#static-methods), [Instance Methods](#instance-methods) and [Case Checks](#case-checks) for each one. diff --git a/docs/sections/06-case-checks.md b/docs/sections/06-case-checks.md index 89c03dd..c95fe39 100644 --- a/docs/sections/06-case-checks.md +++ b/docs/sections/06-case-checks.md @@ -10,7 +10,29 @@ $status->isPending(); // false $status->isDisabled(); // false ``` -Any arguments you pass to a check are ignored. +You don't declare the checks: adding a case adds its check. + +### From case name to check + +| Case | Check | +| --- | --- | +| `Active` | `isActive()` | +| `PENDING` | `isPending()` | +| `IN_COOKING` | `isInCooking()` | +| `IN_PROGRESS` | `isInProgress()` | +| `OUT_FOR_DELIVERY` | `isOutForDelivery()` | +| `InProgress` | `isInProgress()` | +| `In_Progress` | `isInProgress()` | +| `onHold` | `isOnHold()` | +| `HTTPError` | `isHTTPError()` | +| `Level2` | `isLevel2()` | + +```php +$status = OrderStatus::IN_PROGRESS; + +$status->isInProgress(); // true +$status->isOutForDelivery(); // false +``` ### How check names are built @@ -19,7 +41,31 @@ The check name is `is` followed by the case name, with each underscore-separated - A word written entirely in upper case is title-cased: `PENDING` becomes `isPending`, `IN_COOKING` becomes `isInCooking`. - Any other word keeps its letters and gets an upper-case first letter: `onHold` becomes `isOnHold`, `HTTPError` becomes `isHTTPError`, `Level2` becomes `isLevel2`. -Check names are matched exactly. `isPENDING()`, `isonHold()`, `isHttpError()` and `IsPending()` are not checks, and calling them throws `Error: Call to undefined method`. +### Names that are not checks + +Check names are matched exactly, letter case included. Each call below throws `Error: Call to undefined method`: + +| Call | Why it fails | Write instead | +| --- | --- | --- | +| `isArchived()` | No case is named `Archived` | Add the case, or use `is('Archived')` for input you don't control | +| `pending()` | Checks start with `is` | `isPending()` | +| `hasPending()` | Only the `is` prefix makes a check | `isPending()` | +| `IsPending()` | The prefix is lower-case `is` | `isPending()` | +| `isPENDING()` | The raw case name is not used | `isPending()` | +| `isIN_COOKING()` | Underscores are removed | `isInCooking()` | +| `isinprogress()` | Each word starts with a capital letter | `isInProgress()` | +| `isonHold()` | The first letter after `is` is a capital | `isOnHold()` | +| `isHttpError()` | Mixed-case words keep their letters | `isHTTPError()` | +| `secret()` | A `protected` or `private` enum method can't be called from outside | Make it `public` | + +```php +OrderStatus::PENDING->isPENDING(); +// Error: Call to undefined method App\Enums\OrderStatus::isPENDING() +``` + +### Arguments are ignored + +A check takes no arguments. Anything you pass is ignored, so `$status->isActive('anything', 1)` is the same as `$status->isActive()`. ### Ambiguous checks diff --git a/docs/sections/10-examples.md b/docs/sections/10-examples.md index 7b2008e..844fce9 100644 --- a/docs/sections/10-examples.md +++ b/docs/sections/10-examples.md @@ -1,6 +1,23 @@ ## Examples -### 1. A select input +### 1. Branching on a status + +Read the checks like plain English when the code depends on the current case. + +```php title="src/Orders/OrderNotifier.php" +public function notify(Order $order): void +{ + if ($order->status->isOutForDelivery()) { + $this->sms->send($order->phone, 'Your order is on its way.'); + } + + if ($order->status->isDelivered()) { + $this->mailer->send(new OrderDelivered($order)); + } +} +``` + +### 2. A select input Build `