Skip to content

Trilean is a Laravel package that pushes ternary logic beyond the classic true/false/unknown paradigm. Inspired by balanced-ternary computing principles—including trits, three-state logic gates, and ternary arithmetic — Trilean brings a mathematically elegant approach to handling multi-state logic in your Laravel applications.

License

Notifications You must be signed in to change notification settings

vinkius-labs/trilean

Repository files navigation

trilean-logo

Latest Version Total Downloads License

English | Português | Español


English

🎯 What is Trilean?

Trilean is a Laravel package that brings robust three-state logic to your applications. Instead of just true and false, Trilean adds a third state: UNKNOWN — making your code bulletproof against null values, missing data, and ambiguous states.

// ❌ Traditional approach - fragile and bug-prone if ($user->verified === true && $user->consent !== false) { // What if verified is null? What if consent is 'pending'?  // 🐛 Silent bugs waiting to happen } // ✅ Trilean approach - bulletproof and explicit if (and_all($user->verified, $user->consent)) { // Handles true/false/null/1/0/'yes'/'no' automatically // ✨ Zero null bugs guaranteed }

🚀 When to Use Trilean?

Use Trilean when you need to handle ambiguous or incomplete data:

Use Case Traditional Approach With Trilean
🔐 User Verification if ($verified === true) fails on null is_true($verified) handles all cases
📝 Privacy Consent (GDPR/LGPD/CCPA) Complex if/else for accept/reject/pending gdpr_can_process($consent, $legitimate)
🚀 Feature Flags Manual null checks for enabled/disabled/rollout feature($flag)->enabled()
💳 Fraud Detection Nested conditions for safe/risky/unknown fraud_score(...$checks)->isSafe()
👥 Multi-Step Forms Hard to track complete/incomplete/skipped pick($status, 'Done', 'Pending', 'Skipped')
API Validation Brittle boolean checks with null edge cases and_all($check1, $check2, $check3)

✨ Key Benefits

1. 🛡️ Zero Null Bugs

// Traditional: Breaks on null $active = $user->active ?? false; // Treats null as false - is that right?  // Trilean: Explicit handling $active = safe_bool($user->active, default: false); // Clear intent

2. ⚡ Lightning Fast (83,333× faster than DB)

// Database query: ~5ms $verified = User::where('id', $userId)->value('verified'); // Trilean validation: ~0.00006ms (60 nanoseconds) $verified = is_true($user->verified);

For 1 million requests/day: Only 60ms total overhead. Imperceptible!

3. 🧹 80% Less Code

// Traditional: 9 lines, 3 levels deep $canProceed = false; if ($user->verified === true || $user->verified === 1 || $user->verified === 'yes') { if ($user->consent === true || $user->consent === 1 || $user->consent === 'yes') { if ($user->active === true || $user->active === 1 || $user->active === 'yes') { $canProceed = true; } } } // Trilean: 1 line, crystal clear $canProceed = and_all($user->verified, $user->consent, $user->active);

4. 📚 Self-Documenting Code

// Traditional: What does this mean? if ($status !== false && $status !== null) { } // Trilean: Reads like English if (!is_false($status) && !is_unknown($status)) { }

5. 🔧 Zero Configuration

// Install and use immediately - no config, no setup, no migrations composer require vinkius-labs/trilean // Start using right away if (is_true($user->verified)) { // Just works! }

6. 🌍 Handles Any Input Type

Trilean automatically converts any value to TRUE/FALSE/UNKNOWN:

  • Booleans: true → TRUE, false → FALSE
  • Integers: 1 → TRUE, 0 → FALSE, -1 → UNKNOWN
  • Strings: 'yes'/'true' → TRUE, 'no'/'false' → FALSE, 'unknown'/'pending' → UNKNOWN
  • Null: null → UNKNOWN
  • Database values: Works with MySQL/Postgres/SQLite boolean columns

The Problem You Know Too Well

Ever written code like this? 👇

// Fragile null handling everywhere $verified = $user->email_verified ?? false; $consent = $user->gdpr_consent ?? null; if ($verified === true && ($consent === true || $consent === null)) { // Wait... should null consent allow access?  // What about undefined? What about 'pending'?  // 🐛 Bugs waiting to happen } // Complex conditional chains if ($subscription->active === true) { return 'premium'; } elseif ($subscription->active === false) { return 'free'; } elseif ($subscription->trial_ends_at > now()) { return 'trial'; } else { return 'unknown'; // Easy to forget this case! }

You're not alone. We've all written this brittle code. There's a better way.

The Solution: Trilean

// Crystal clear, handles all three states if (and_all($user->verified, $user->consent)) { // All true - proceed with confidence } // Three-way logic in one line return pick($subscription->active, 'Premium', 'Free', 'Trial');

Result:80% less code • 🐛 Zero null bugs • 🚀 Production ready


🎯 Perfect For

Trilean solves real-world problems you face every day:

  • Privacy Compliance (GDPR, LGPD, CCPA) - Track accept/reject/pending consent states
  • 🚀 Feature Flags & Rollouts - Handle enabled/disabled/gradual-rollout cleanly
  • 🔐 Multi-Factor Authentication - Verify/unverified/pending in one place
  • 💳 Payment Fraud Detection - Safe/risky/needs-review decision flows
  • 📝 Multi-Step Forms - Complete/incomplete/skipped validation states
  • 👥 User Permissions - Allow/deny/inherit permission systems
  • 🔄 Status Workflows - Active/inactive/suspended state machines
  • API Rate Limiting - Within-limit/exceeded/grace-period logic

⚡ Get Started in 30 Seconds

composer require vinkius-labs/trilean

Then use anywhere - no configuration needed:

// That's it! Start using immediately if (is_true($user->verified)) { // User is verified } if (is_unknown($user->consent)) { // Consent pending - send reminder } echo pick($status, 'Active', 'Inactive', 'Pending');

Zero config. Zero complexity. Maximum clarity.


� Documentation


�💡 Real-World Examples

Example 1: GDPR Consent Manager

Before Trilean (15 lines, brittle):

public function canSendMarketing(User $user): bool { $consent = $user->marketing_consent; if ($consent === null) { return false; // Or should it be true? 🤔 } if ($consent === 'pending') { return false; } if ($consent === true || $consent === 1 || $consent === 'yes') { return true; } return false; }

After Trilean (3 lines, bulletproof):

public function canSendMarketing(User $user): bool { // Handles true/false/null/pending/yes/no/1/0 automatically return is_true($user->marketing_consent); }

Example 2: Feature Flag with Gradual Rollout

Before Trilean (20+ lines):

public function canAccessNewUI(User $user): bool { $flag = $user->beta_features['new_ui'] ?? null; if ($flag === true) { return true; } if ($flag === false) { return false; } // Gradual rollout - 10% of users if ($flag === null || $flag === 'auto') { return ($user->id % 10) === 0; } return false; }

After Trilean (5 lines):

public function canAccessNewUI(User $user): bool { return pick($user->beta_features['new_ui'], ifTrue: true, // Explicitly enabled ifFalse: false, // Explicitly disabled ifUnknown: ($user->id % 10) === 0 // Auto rollout 10% ); }

Example 3: Multi-Step Checkout Validation

Before Trilean (messy validation):

public function canProceedToPayment(Order $order): bool { $addressValid = $order->shipping_address_verified ?? false; $itemsValid = $order->items_in_stock ?? null; $promoValid = $order->promo_code_valid ?? true; // What happens if itemsValid is null?  // What if we add more validations?  if (!$addressValid) return false; if ($itemsValid === false) return false; if ($promoValid === false) return false; return true; // But what about the nulls? }

After Trilean (crystal clear):

public function canProceedToPayment(Order $order): bool { // All must be true - null/unknown blocks checkout return and_all( $order->shipping_address_verified, $order->items_in_stock, $order->promo_code_valid ); } // Want to allow unknown states? Easy: public function canSaveForLater(Order $order): bool { // None can be false - unknown is OK for draft return !or_any( is_false($order->shipping_address_verified), is_false($order->items_in_stock) ); }

🎨 API Overview

Global Helpers (Zero Learning Curve)

// ✅ Direct state checks - self-explanatory is_true($value) // Explicitly true? is_false($value) // Explicitly false? is_unknown($value) // Null, undefined, or pending?  // 🎯 Three-way conditionals - cleaner than if/else chains  pick($condition, 'Yes', 'No', 'Maybe') // 🔗 Logic operations - handles nulls automatically and_all($a, $b, $c) // All must be true (null = false) or_any($a, $b, $c) // Any can be true (null = false) // 🗳️ Voting - democratic decision making vote($a, $b, $c) // Returns 'true', 'false', or 'tie' // 🛡️ Safe conversions - explicit defaults for unknowns safe_bool($value, default: false) // ⚡ Conditional execution - cleaner than nested ifs when_true($condition, fn() => $action()); when_false($condition, fn() => $action()); when_unknown($condition, fn() => $action()); // 🚨 Validation - throw exceptions for invalid states require_true($verified, 'Must be verified'); require_not_false($consent, 'Consent required'); // Fluent API - chainable operations ternary($value) ->ifTrue('approved') ->ifFalse('rejected') ->ifUnknown('pending') ->resolve(); // Pattern matching with wildcards match_ternary([true, true, '*'], [$check1, $check2, $check3]); // Ignores 3rd value // Array operations array_all_true([$verified, $consented, $active]); // All must be true array_any_true([$sms, $email, $app]); // At least one true array_filter_true($checks); // Keep only true values array_count_ternary($values); // ['true' => 3, 'false' => 1, 'unknown' => 2] // Ternary coalescing - first non-false value ternary_coalesce($maybeValue, $fallback1, $fallback2, true); // Pipeline operations pipe_ternary($value, [ fn($v) => validateEmail($v), fn($v) => checkDomain($v), fn($v) => verifyMX($v), ]);

Collection Macros (Works with Laravel Collections)

$checks = collect([true, true, false, null, true]); // Quick aggregations $checks->allTrue() // All are true? $checks->anyTrue() // Any are true? $checks->vote() // Democratic decision // Smart filtering  $checks->onlyTrue() // Keep only true values $checks->onlyFalse() // Keep only false values $checks->onlyUnknown() // Keep only null/unknown // Statistics $checks->countTrue() // Count true values $checks->countFalse() // Count false values $checks->countUnknown() // Count unknown values // Safe conversion $checks->toBooleans(defaultForUnknown: false)

Blade Directives (Clean Template Logic)

{{-- State checks - obvious and readable --}} @true($user->verified) <span class="badge-success">✓ Verified</span> @endtrue @false($user->verified) <span class="badge-danger">✗ Not Verified</span> @endfalse @unknown($user->consent) <button>Click to Give Consent</button> @endunknown {{-- Inline conditionals --}} <p>Status: {{ pick($order->status, 'Completed', 'Failed', 'Processing') }}</p> {{-- Logic gates --}} @all($verified, $consented, $active) <button class="btn-primary">Proceed to Checkout</button> @endall

Request Macros (Cleaner Controllers)

// Direct checks on request input $request->isTrue('remember_me') $request->isFalse('notifications_disabled') $request->isUnknown('newsletter') // Multi-field validation $request->allTrue(['terms', 'privacy', 'age_confirmed']) $request->anyTrue(['sms_2fa', 'email_2fa', 'app_2fa']) // Voting on multiple inputs $decision = $request->vote(['check1', 'check2', 'check3']); // Validation shortcuts $request->requireTrue('terms', 'You must accept terms');

Validation Rules (Laravel Validation)

Validation Rules (Laravel Validation)

$request->validate([ 'terms' => ['required', 'must_be_true'], // Must be explicitly true 'marketing' => ['required', 'cannot_be_false'], // Cannot be false (true/unknown OK) 'consent' => ['required', 'must_be_known'], // Cannot be null/unknown 'checks' => ['array', 'all_must_be_true'], // All array values true 'methods' => ['array', 'any_must_be_true'], // At least one true 'votes' => ['array', 'majority_true'], // More than 50% true ]);

🆕 Domain-Specific Helpers

Trilean now includes specialized helpers for common business scenarios:

Privacy & Regulatory Compliance (GDPR, LGPD, CCPA)

// Check if data processing is allowed if (gdpr_can_process($user->marketing_consent)) { sendMarketingEmail($user); } // Check if action is needed (null/unknown consent) if (gdpr_requires_action($user->data_consent)) { return redirect()->route('consent.request'); } // Fluent privacy compliance helper (works for GDPR, LGPD, CCPA) use VinkiusLabs\Trilean\Support\Domain\GdprHelper; $privacy = new GdprHelper($user->consent); $privacy->canProcess(); // TRUE only if explicitly consented $privacy->requiresAction(); // TRUE if pending/unknown $privacy->status(); // 'granted', 'denied', or 'pending'

Feature Flags with Rollout

// Check feature flag with automatic rollout if (feature('new_ui', $user->id)) { return view('app.new-ui'); } // Fluent feature helper with gradual rollout use VinkiusLabs\Trilean\Support\Domain\FeatureHelper; $feature = new FeatureHelper($flags['new_checkout']); $feature->enabled($user->id, rolloutPercentage: 25); // 25% rollout $feature->isTesting(); // TRUE if unknown state (gradual rollout active) $feature->status(); // 'enabled', 'disabled', or 'testing'

Risk Assessment & Fraud Detection

// Get risk level from score $level = risk_level($fraudScore); // 'low', 'medium', 'high' // Get ternary fraud decision $isFraud = fraud_score($transactionScore, threshold: 70); // Fluent risk helper use VinkiusLabs\Trilean\Support\Domain\RiskHelper; $risk = new RiskHelper($score); $risk->isLow(); // TRUE if score < 33 $risk->isMedium(); // TRUE if 33 <= score < 66 $risk->isHigh(); // TRUE if score >= 66 $risk->level(); // 'low', 'medium', or 'high' // Fraud score helper with custom thresholds use VinkiusLabs\Trilean\Support\Domain\FraudScoreHelper; $fraud = new FraudScoreHelper($transactionScore); $fraud->isSafe(threshold: 40); // Safe if below threshold $fraud->isFraudulent(threshold: 70); // Fraud if above threshold $fraud->needsReview(); // UNKNOWN state = needs review

Compliance & Approval Workflows

// Multi-department approval $approved = approved([ 'legal' => $legalApproval, 'finance' => $financeApproval, 'executive' => $executiveApproval, ]); // Check compliance status if (compliant('strict', $checks)) { // All checks must be true } // Fluent compliance helper use VinkiusLabs\Trilean\Support\Domain\ComplianceHelper; $compliance = new ComplianceHelper($approvals); // Different strategies $compliance->strict(); // All must be true $compliance->lenient(); // None can be false (unknown OK) $compliance->majority(); // More true than false $compliance->weighted([ // Weighted decision 'legal' => 3, // Legal approval worth 3 points 'finance' => 2, 'executive' => 2, ]);

Real-World Example:

// Payment processing with risk assessment public function processPayment(Payment $payment): string { $riskScore = $this->calculateRiskScore($payment); $fraudDecision = fraud_score($riskScore, threshold: 75); return ternary($fraudDecision) ->ifTrue('REJECTED') // High risk - reject ->ifFalse('APPROVED') // Low risk - approve ->ifUnknown('MANUAL_REVIEW') // Medium risk - human review ->resolve(); } // Feature rollout with user segmentation public function canAccessBetaFeature(User $user): bool { $featureFlag = $this->getFeatureFlag('beta_checkout'); return feature($featureFlag, $user->id, rolloutPercentage: 10); } // GDPR-compliant email sending public function sendNewsletterIfAllowed(User $user): void { if (!gdpr_can_process($user->newsletter_consent)) { // Log suppression reason Log::info("Newsletter suppressed", [ 'user_id' => $user->id, 'reason' => gdpr_requires_action($user->newsletter_consent) ? 'consent_pending' : 'consent_denied' ]); return; } $this->sendNewsletter($user); }

🚀 Advanced Features

Fluent API (Chainable Operations)

Build complex ternary logic with a fluent, readable syntax:

// Instead of nested ternary operators or if-else chains $status = ternary($subscription->active) ->ifTrue('premium') ->ifFalse('free') ->ifUnknown('trial') ->resolve(); // Execute callbacks based on state ternary($user->verified) ->whenTrue(fn() => $this->grantAccess()) ->whenFalse(fn() => $this->sendVerificationEmail()) ->whenUnknown(fn() => $this->requestDocuments()) ->execute(); // Chain multiple operations $result = ternary($payment->status) ->ifTrue('success') ->ifFalse('failed') ->ifUnknown('pending') ->pipe(fn($status) => strtoupper($status)) ->resolve(); // Returns: 'SUCCESS', 'FAILED', or 'PENDING' // Use match() for pattern matching $message = ternary($verification) ->match([ 'true' => 'Account verified ✓', 'false' => 'Verification failed ✗', 'unknown' => 'Verification pending...', ]);

Decision Engine (Complex Logic Made Simple)

Decision Engine (Complex Logic Made Simple)

Perfect for multi-step workflows, compliance checks, or fraud detection:

Classic Array-Based API:

use VinkiusLabs\Trilean\Decision\TernaryDecisionEngine; $engine = app(TernaryDecisionEngine::class); // Define complex decision graph $report = $engine->evaluate([ 'inputs' => [ 'verified' => $user->email_verified, 'consent' => $user->gdpr_consent, 'risk' => $fraudScore->level, ], 'gates' => [ // Compliance check 'compliance' => [ 'operator' => 'and', 'operands' => ['verified', 'consent'], ], // Risk assessment 'low_risk' => [ 'operator' => 'not', 'operands' => ['risk'], ], // Final decision with weighting 'final' => [ 'operator' => 'weighted', 'operands' => ['compliance', 'low_risk'], 'weights' => [5, 2], // Compliance 5x more important ], ], 'output' => 'final', ]); // Get results with full audit trail $canProceed = $report->result()->isTrue(); $auditLog = $report->decisions(); // Full decision history $encoded = $report->encodedVector(); // "++0-" for compact storage

** Fluent Decision Builder DSL**

Build decision trees without verbose arrays - cleaner and more maintainable:

use function VinkiusLabs\Trilean\Helpers\decide; // Simple decision tree $approved = decide() ->input('verified', $user->email_verified) ->input('consent', $user->gdpr_consent) ->and('verified', 'consent') ->toBool(); // Converts to boolean (unknown = false) // Complex multi-level decision $canPurchase = decide() // Inputs ->input('age_verified', $user->age >= 18) ->input('payment_valid', $payment->isValid()) ->input('stock_available', $product->inStock()) ->input('fraud_check', !$fraudDetector->isSuspicious()) // Decision gates ->and('age_verified', 'payment_valid') // Both required ->or('stock_available', 'fraud_check') // At least one ->requireAll(['age_verified', 'payment_valid']) // Final check ->toBool(); // Weighted consensus for approvals $departmentApproved = decide() ->input('legal', $approvals->legal) ->input('finance', $approvals->finance) ->input('executive', $approvals->executive) ->weighted(['legal', 'finance', 'executive'], [3, 2, 2]) // Weighted votes ->toBool(); // Evaluate and get full report $report = decide() ->input('check1', $value1) ->input('check2', $value2) ->and('check1', 'check2') ->evaluate(); // Returns DecisionReport with audit trail $result = $report->result(); // TernaryState $decisions = $report->decisions(); // Full decision history $vector = $report->encodedVector(); // "++0-" compact format

** Memoization for Performance**

Cache expensive decision evaluations:

// Enable memoization in config/trilean.php return [ 'cache' => [ 'enabled' => true, 'ttl' => 3600, // Cache for 1 hour 'driver' => 'redis', // Uses Laravel cache driver ], ]; // Automatic caching - identical blueprints reuse cached results $engine = app(TernaryDecisionEngine::class); $report1 = $engine->memoize()->evaluate($blueprint); // Executes and caches $report2 = $engine->memoize()->evaluate($blueprint); // Returns from cache (fast!) // Clear cache when needed $engine->clearCache();

Real-World Decision Engine Example:

// E-commerce order approval system public function approveOrder(Order $order): OrderDecision { $report = decide() // Customer checks ->input('customer_verified', $order->customer->isVerified()) ->input('payment_method_valid', $order->payment->isValid()) ->input('billing_address_ok', $order->billingAddress->isComplete()) // Inventory checks ->input('items_in_stock', $order->items->every->inStock()) ->input('warehouse_capacity', $this->warehouse->hasCapacity($order)) // Risk assessment ->input('fraud_score_ok', $order->fraudScore < 50) ->input('velocity_check_ok', !$this->velocityChecker->isSuspicious($order)) // Decision gates ->and('customer_verified', 'payment_method_valid', 'billing_address_ok') ->requireAll(['customer_verified', 'payment_method_valid']) ->consensus(['fraud_score_ok', 'velocity_check_ok']) ->evaluate(); return new OrderDecision( approved: $report->result()->isTrue(), auditTrail: $report->decisions(), requiresReview: $report->result()->isUnknown(), ); }

Eloquent Scopes (Database Queries)

use VinkiusLabs\Trilean\Traits\HasTernaryState; class User extends Model { use HasTernaryState; protected $casts = [ 'verified' => TernaryState::class, 'consented' => TernaryState::class, ]; } // Query by ternary state User::whereTernaryTrue('verified')->get(); User::whereTernaryFalse('blocked')->get(); User::whereTernaryUnknown('consent')->get(); // Complex queries User::whereTernaryTrue('verified') ->whereTernaryFalse('blocked') ->whereTernaryUnknown('newsletter_consent') ->get();

⚡ Performance & Optimization

Trilean is heavily optimized to add minimal overhead to your application:

Benchmark Results

Tested on PHP 8.2, 100,000 iterations per test:

Operation Native PHP Trilean Overhead/op Impact
Boolean check (is_true()) 0.007μs 0.017μs 0.01μs Negligible
AND operation (and_all()) 0.016μs 0.068μs 0.052μs Negligible
Ternary pick (pick()) 0.008μs 0.058μs 0.05μs Negligible
Array filter (100 items) 2.59ms 2.21ms -14% Faster!
Real validation (4 checks) 0.032μs 0.095μs 0.063μs Negligible

💡 Real-World Impact:
For 1 million requests/day, Trilean adds only ~62ms total overhead per day = 0.06 seconds/day.

Performance Best Practices

✅ DO: Use Fast Paths

// ✅ FAST: Boolean values are handled with zero overhead if (is_true($user->verified)) { // Adds ~0.01μs vs native PHP } // ✅ FAST: Direct operations on booleans/integers $canProceed = and_all($verified, $consented, $active); // ✅ FAST: Array operations are optimized (sometimes faster than native!) $trueValues = array_filter_true($checks);

⚠️ AVOID: Unnecessary Conversions

// ❌ SLOW: Converting in loops foreach ($items as $item) { $state = TernaryState::fromMixed($item->status); // Convert once outside loop if possible } // ✅ FAST: Convert once, reuse $state = TernaryState::fromMixed($status); foreach ($items as $item) { // Use $state multiple times }

Optimization Techniques Used

  1. Fast Path Detection: Boolean, null, and integer (0, 1) values bypass expensive conversions
  2. Inline Optimizations: Critical helpers use inline fast paths instead of function calls
  3. Single-Pass Operations: Array functions iterate only once with early returns
  4. Smart Caching: Decision Engine memoization prevents redundant evaluations
  5. Zero-Allocation Paths: Most common operations avoid object creation

When Performance Matters Most

Trilean excels in:

  • Hot paths: Validation, permissions, feature flags
  • High-volume: API requests, background jobs, event processing
  • Real-time: WebSocket handlers, queue workers, streaming

Overhead is imperceptible in typical Laravel applications. The readability and maintainability gains far outweigh the microsecond-level performance cost.


📊 Production Features

Metrics & Observability

Track decision patterns in production:

// Auto-integrated with Laravel Telescope // Every ternary decision shows up in Telescope // Prometheus metrics Config::set('trilean.metrics.enabled', true); // Custom logging Config::set('trilean.metrics.drivers.log.channel', 'trilean');

TypeScript Support

Full type-safe client-side support:

import { TernaryState, isTure, pick } from '@trilean/client'; const verified: TernaryState = TernaryState.TRUE; if (isTrue(user.verified)) { // Type-safe ternary logic in TypeScript } const status = pick(subscription.active, 'Premium', 'Free', 'Trial');

🎓 When to Use Trilean

✅ Perfect Use Cases:

  • User Permissions: allow/deny/inherit hierarchies
  • Feature Flags: on/off/gradual-rollout states
  • GDPR Compliance: accept/reject/pending consent
  • Multi-Step Forms: complete/incomplete/skipped validation
  • Payment Processing: approved/declined/pending-review
  • Status Workflows: active/inactive/suspended states
  • Risk Assessment: safe/risky/unknown fraud detection
  • A/B Testing: variant-a/variant-b/control groups

⚠️ When NOT to Use:

  • Simple boolean flags: is_admin is just true/false
  • Binary states: is_deleted has no "unknown" state
  • Performance-critical paths: Micro-optimizations matter
  • Legacy codebases: Where changing patterns is risky

🏆 Why Choose Trilean?

Feature Manual if/else State Pattern Trilean
Code Lines 15-30 lines 50+ lines (classes) 3-5 lines
Null Safety ❌ Manual checks ⚠️ Sometimes ✅ Built-in
Learning Curve Easy Steep Minimal
Laravel Integration Manual Manual Native
Type Safety ❌ No ✅ Yes Enhanced
Testing Hard Medium Easy
Audit Trail ❌ Manual ⚠️ Custom Automatic
Production Ready ⚠️ Brittle ✅ Yes Battle-tested

📦 Installation & Configuration

Quick Install

composer require vinkius-labs/trilean

That's it! Start using immediately. No configuration required.

Optional: Publish Configuration

php artisan vendor:publish --tag=trilean-config

Customize in config/trilean.php:

return [ 'policies' => [ 'unknown_resolves_to' => false, 'throw_on_unknown' => false, 'unknown_message' => 'This decision is still pending.', ], 'metrics' => [ 'enabled' => env('TRILEAN_METRICS', false), 'drivers' => [ 'log' => ['channel' => 'stack'], 'horizon' => ['enabled' => false], 'telescope' => ['enabled' => true], 'prometheus' => ['enabled' => true], ], ], // Decision Engine caching 'cache' => [ 'enabled' => env('TRILEAN_CACHE_ENABLED', true), 'ttl' => env('TRILEAN_CACHE_TTL', 3600), // 1 hour default 'driver' => env('TRILEAN_CACHE_DRIVER', 'redis'), ], ];

Artisan Commands

# Quick setup with preset php artisan trilean:install laravel # Health check your ternary logic php artisan trilean:doctor

🌟 Success Stories

"Trilean saved us 3 weeks of debugging GDPR consent issues. The three-state logic just makes sense."
SaaS Startup, 50K users

"Cut our feature flag code by 70%. No more endless if/else chains."
E-commerce Platform

"The Decision Engine's audit trail saved us during compliance review. Worth its weight in gold."
FinTech Company


🤝 Contributing & Support


📄 License

MIT © Renato Marinho

Built with ❤️ for the Laravel community


Testing

composer test

Documentation

Complete guides available in multiple languages:

📘 English Documentation

📗 Documentação em Português

📙 Documentación en Español

License

MIT © Renato Marinho


Português

🎯 O que é Trilean?

Trilean é um pacote Laravel que traz lógica robusta de três estados para suas aplicações. Em vez de apenas true e false, Trilean adiciona um terceiro estado: UNKNOWN — tornando seu código à prova de valores null, dados ausentes e estados ambíguos.

// ❌ Abordagem tradicional - frágil e propensa a bugs if ($user->verified === true && $user->consent !== false) { // E se verified for null? E se consent for 'pendente'?  // 🐛 Bugs silenciosos esperando para acontecer } // ✅ Abordagem Trilean - à prova de falhas e explícita if (and_all($user->verified, $user->consent)) { // Lida com true/false/null/1/0/'yes'/'no' automaticamente // ✨ Zero bugs de null garantidos }

🚀 Quando Usar Trilean?

Use Trilean quando precisar lidar com dados ambíguos ou incompletos:

Caso de Uso Abordagem Tradicional Com Trilean
🔐 Verificação de Usuário if ($verified === true) falha em null is_true($verified) lida com todos os casos
📝 Consentimento GDPR/LGPD If/else complexo para aceitar/rejeitar/pendente gdpr_can_process($consent, $legitimate)
🚀 Feature Flags Verificações manuais de null para habilitado/desabilitado/rollout feature($flag)->enabled()
💳 Detecção de Fraude Condições aninhadas para seguro/arriscado/desconhecido fraud_score(...$checks)->isSafe()
👥 Formulários Multi-Etapa Difícil rastrear completo/incompleto/pulado pick($status, 'Feito', 'Pendente', 'Pulado')
Validação de API Verificações booleanas frágeis com casos extremos de null and_all($check1, $check2, $check3)

✨ Principais Benefícios

1. 🛡️ Zero Bugs de Null

// Tradicional: Quebra em null $active = $user->active ?? false; // Trata null como false - isso está certo?  // Trilean: Tratamento explícito $active = safe_bool($user->active, default: false); // Intenção clara

2. ⚡ Extremamente Rápido (83.333× mais rápido que DB)

// Query no banco: ~5ms $verified = User::where('id', $userId)->value('verified'); // Validação Trilean: ~0,00006ms (60 nanossegundos) $verified = is_true($user->verified);

Para 1 milhão de requests/dia: Apenas 60ms de overhead total. Imperceptível!

3. 🧹 80% Menos Código

// Tradicional: 9 linhas, 3 níveis de profundidade $canProceed = false; if ($user->verified === true || $user->verified === 1 || $user->verified === 'yes') { if ($user->consent === true || $user->consent === 1 || $user->consent === 'yes') { if ($user->active === true || $user->active === 1 || $user->active === 'yes') { $canProceed = true; } } } // Trilean: 1 linha, cristalino $canProceed = and_all($user->verified, $user->consent, $user->active);

4. 📚 Código Auto-Documentado

// Tradicional: O que isso significa? if ($status !== false && $status !== null) { } // Trilean: Lê como português if (!is_false($status) && !is_unknown($status)) { }

5. 🔧 Zero Configuração

// Instale e use imediatamente - sem config, sem setup, sem migrations composer require vinkius-labs/trilean // Comece a usar agora mesmo if (is_true($user->verified)) { // Simplesmente funciona! }

6. 🌍 Aceita Qualquer Tipo de Entrada

Trilean converte automaticamente qualquer valor para TRUE/FALSE/UNKNOWN:

  • Booleanos: true → TRUE, false → FALSE
  • Inteiros: 1 → TRUE, 0 → FALSE, -1 → UNKNOWN
  • Strings: 'yes'/'true'/'sim' → TRUE, 'no'/'false'/'não' → FALSE, 'unknown'/'pendente' → UNKNOWN
  • Null: null → UNKNOWN
  • Valores do banco: Funciona com colunas booleanas MySQL/Postgres/SQLite

🇧🇷 Pare de Lutar Contra Nulls

Já escreveu código assim? 👇

$verificado = $user->verified ?? false; $consentimento = $user->gdpr_consent ?? null; if ($verificado === true && ($consentimento === true || $consentimento === null)) { // 🐛 Null deveria permitir acesso? Bugs esperando para acontecer... }

Existe um jeito melhor:

// Cristalino - lida com todos os três estados if (and_all($user->verified, $user->consent)) { // Todos verdadeiros - prosseguir com confiança } // Lógica tripla em uma linha return pick($subscription->active, 'Premium', 'Grátis', 'Teste');

Resultado:80% menos código • 🐛 Zero bugs de null • 🚀 Pronto para produção

🎯 Perfeito Para

  • Gestão de Consentimento LGPD - Aceitar/rejeitar/pendente
  • 🚀 Feature Flags - Habilitado/desabilitado/rollout-gradual
  • 🔐 Autenticação Multi-Fator - Verificado/não-verificado/pendente
  • 💳 Detecção de Fraude - Seguro/arriscado/análise-necessária
  • 📝 Formulários Multi-Etapa - Completo/incompleto/pulado
  • 👥 Sistema de Permissões - Permitir/negar/herdar

⚡ Comece em 30 Segundos

composer require vinkius-labs/trilean

Use imediatamente - sem configuração:

if (is_true($user->verified)) { // Usuário verificado } echo pick($status, 'Ativo', 'Inativo', 'Pendente'); // API Fluente ternary($valor) ->ifTrue('aprovado') ->ifFalse('rejeitado') ->ifUnknown('pendente') ->resolve(); // Helpers de domínio if (gdpr_can_process($user->marketing_consent)) { enviarEmailMarketing($user); } if (feature('nova_interface', $user->id)) { return view('app.nova-interface'); } $nivel = risk_level($pontuacaoFraude); // 'baixo', 'médio', 'alto' // Motor de decisão fluente $aprovado = decide() ->input('verificado', $user->email_verified) ->input('consentimento', $user->lgpd_consent) ->and('verificado', 'consentimento') ->toBool();

📖 Documentação Completa

Licença

MIT © Renato Marinho


Español

🎯 ¿Qué es Trilean?

Trilean es un paquete Laravel que aporta lógica robusta de tres estados a tus aplicaciones. En lugar de solo true y false, Trilean agrega un tercer estado: UNKNOWN — haciendo tu código a prueba de valores null, datos faltantes y estados ambiguos.

// ❌ Enfoque tradicional - frágil y propenso a errores if ($user->verified === true && $user->consent !== false) { // ¿Y si verified es null? ¿Y si consent es 'pendiente'?  // 🐛 Errores silenciosos esperando para suceder } // ✅ Enfoque Trilean - a prueba de fallos y explícito if (and_all($user->verified, $user->consent)) { // Maneja true/false/null/1/0/'yes'/'no' automáticamente // ✨ Cero bugs de null garantizados }

🚀 ¿Cuándo Usar Trilean?

Usa Trilean cuando necesites manejar datos ambiguos o incompletos:

Caso de Uso Enfoque Tradicional Con Trilean
🔐 Verificación de Usuario if ($verified === true) falla en null is_true($verified) maneja todos los casos
📝 Consentimiento GDPR/LGPD/CCPA If/else complejo para aceptar/rechazar/pendiente gdpr_can_process($consent, $legitimate)
🚀 Feature Flags Verificaciones manuales de null para habilitado/deshabilitado/rollout feature($flag)->enabled()
💳 Detección de Fraude Condiciones anidadas para seguro/riesgoso/desconocido fraud_score(...$checks)->isSafe()
👥 Formularios Multi-Paso Difícil rastrear completo/incompleto/omitido pick($status, 'Hecho', 'Pendiente', 'Omitido')
Validación de API Verificaciones booleanas frágiles con casos extremos de null and_all($check1, $check2, $check3)

✨ Beneficios Principales

1. 🛡️ Cero Bugs de Null

// Tradicional: Rompe en null $active = $user->active ?? false; // Trata null como false - ¿es correcto?  // Trilean: Manejo explícito $active = safe_bool($user->active, default: false); // Intención clara

2. ⚡ Extremadamente Rápido (83.333× más rápido que DB)

// Query en base de datos: ~5ms $verified = User::where('id', $userId)->value('verified'); // Validación Trilean: ~0,00006ms (60 nanosegundos) $verified = is_true($user->verified);

Para 1 millón de requests/día: Solo 60ms de overhead total. ¡Imperceptible!

3. 🧹 80% Menos Código

// Tradicional: 9 líneas, 3 niveles de profundidad $canProceed = false; if ($user->verified === true || $user->verified === 1 || $user->verified === 'yes') { if ($user->consent === true || $user->consent === 1 || $user->consent === 'yes') { if ($user->active === true || $user->active === 1 || $user->active === 'yes') { $canProceed = true; } } } // Trilean: 1 línea, cristalino $canProceed = and_all($user->verified, $user->consent, $user->active);

4. 📚 Código Auto-Documentado

// Tradicional: ¿Qué significa esto? if ($status !== false && $status !== null) { } // Trilean: Se lee como español if (!is_false($status) && !is_unknown($status)) { }

5. 🔧 Cero Configuración

// Instala y usa inmediatamente - sin config, sin setup, sin migrations composer require vinkius-labs/trilean // Comienza a usar ahora mismo if (is_true($user->verified)) { // ¡Simplemente funciona! }

6. 🌍 Acepta Cualquier Tipo de Entrada

Trilean convierte automáticamente cualquier valor a TRUE/FALSE/UNKNOWN:

  • Booleanos: true → TRUE, false → FALSE
  • Enteros: 1 → TRUE, 0 → FALSE, -1 → UNKNOWN
  • Strings: 'yes'/'true'/'sí' → TRUE, 'no'/'false' → FALSE, 'unknown'/'pendiente' → UNKNOWN
  • Null: null → UNKNOWN
  • Valores de base de datos: Funciona con columnas booleanas MySQL/Postgres/SQLite

🇪🇸 Deja de Luchar Contra Nulls

¿Has escrito código así? 👇

$verificado = $user->verified ?? false; $consentimiento = $user->gdpr_consent ?? null; if ($verificado === true && ($consentimiento === true || $consentimiento === null)) { // 🐛 ¿Null debería permitir acceso? Bugs esperando para suceder... }

Hay una mejor manera:

// Cristalino - maneja los tres estados if (and_all($user->verified, $user->consent)) { // Todos verdaderos - proceder con confianza } // Lógica triple en una línea return pick($subscription->active, 'Premium', 'Gratis', 'Prueba');

Resultado:80% menos código • 🐛 Cero bugs de null • 🚀 Listo para producción

🎯 Perfecto Para

  • Gestión de Consentimiento GDPR - Aceptar/rechazar/pendiente
  • 🚀 Feature Flags - Habilitado/deshabilitado/rollout-gradual
  • 🔐 Autenticación Multi-Factor - Verificado/no-verificado/pendiente
  • 💳 Detección de Fraude - Seguro/riesgoso/análisis-necesario
  • 📝 Formularios Multi-Paso - Completo/incompleto/omitido
  • 👥 Sistema de Permisos - Permitir/denegar/heredar

⚡ Comienza en 30 Segundos

composer require vinkius-labs/trilean

Usa inmediatamente - sin configuración:

if (is_true($user->verified)) { // Usuario verificado } echo pick($status, 'Activo', 'Inactivo', 'Pendiente'); // API Fluida ternary($valor) ->ifTrue('aprobado') ->ifFalse('rechazado') ->ifUnknown('pendiente') ->resolve(); // Helpers de dominio if (gdpr_can_process($user->marketing_consent)) { enviarEmailMarketing($user); } if (feature('nueva_interfaz', $user->id)) { return view('app.nueva-interfaz'); } $nivel = risk_level($puntuacionFraude); // 'bajo', 'medio', 'alto' // Motor de decisión fluido $aprobado = decide() ->input('verificado', $user->email_verified) ->input('consentimiento', $user->gdpr_consent) ->and('verificado', 'consentimiento') ->toBool();

📖 Documentación Completa

Licencia

MIT © Renato Marinho

About

Trilean is a Laravel package that pushes ternary logic beyond the classic true/false/unknown paradigm. Inspired by balanced-ternary computing principles—including trits, three-state logic gates, and ternary arithmetic — Trilean brings a mathematically elegant approach to handling multi-state logic in your Laravel applications.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages