PHP code example of ca-santos / laravel-support

1. Go to this page and download the library: Download ca-santos/laravel-support library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

ca-santos / laravel-support example snippets


use CaueSantos\Support\Helpers\StringHelper;
use CaueSantos\Support\Helpers\ArrayHelper;
use CaueSantos\Support\Helpers\DateHelper;

StringHelper::toSnakeSlug('My Cool Title');              // "my_cool_title"
ArrayHelper::isListOfArrays([['id' => 1], ['id' => 2]]); // true
DateHelper::formatUkDate('2024-03-05');                  // "05/03/2024"

use CaueSantos\Support\Helpers\StringHelper;

StringHelper::randomStr(12);

use CaueSantos\Support\Helpers\StringHelper;

StringHelper::toSnakeSlug('My Cool Title');           // "my_cool_title"
StringHelper::toSnakeSlug('My Cool Title', '-');      // "my-cool-title"

StringHelper::randomStr(10);                          // e.g. "qQqqOaTImp" (letters only — Str::random() mixes in digits)
StringHelper::lowerRandomStr(16);                     // e.g. "wowzultbfpokgxaf"

StringHelper::formatTags('Hello {{name}}!', ['name' => 'Ada']); // "Hello Ada!"
StringHelper::formatTags('Hi [name]', ['name' => 'Ada'], fn ($tag) => "[{$tag}]"); // "Hi Ada"

StringHelper::initials('John Doe'); // "JD"
StringHelper::initials('Ada Lovelace Byron', 3); // "ALB"

StringHelper::toDottedClassName('App\Models\UserAccount');   // "app.models.user-account"
StringHelper::fromDottedClassName('app.models.user-account'); // "App\Models\UserAccount"

StringHelper::autoEncodeToUtf8($legacyString);        // detects the current encoding and converts to UTF-8
StringHelper::decodeLegacyText($latin1String);        // collapses whitespace, strips &nbsp;, decodes Latin-1 (deprecated: only for known non-UTF-8 input)

use CaueSantos\Support\Helpers\ArrayHelper;

ArrayHelper::unsetRecursive(
    ['a' => 1, 'b' => ['c' => 2, 'd' => 'remove-me']],
    ['remove-me']
); // ['a' => 1, 'b' => ['c' => 2]]

ArrayHelper::removeEmpty([
    'name' => 'Ada', 'nickname' => '', 'age' => 0, 'tags' => [],
]); // ['name' => 'Ada', 'age' => 0] — 0/false are kept, blank values are stripped

ArrayHelper::deepMerge(
    ['settings' => ['theme' => 'dark', 'tags' => ['a']]],
    ['settings' => ['locale' => 'en', 'tags' => ['b']]],
); // ['settings' => ['theme' => 'dark', 'tags' => ['a', 'b'], 'locale' => 'en']]

ArrayHelper::diffRecursive(
    ['name' => 'Ada', 'address' => ['city' => 'Paris', 'zip' => 'E1']],
    ['name' => 'Ada', 'address' => ['city' => 'London', 'zip' => 'E1']],
); // ['address' => ['city' => 'Paris']] — only the changed leaf, not the whole nested array

ArrayHelper::toTree([
    ['id' => 1, 'parent_id' => null, 'name' => 'Root'],
    ['id' => 2, 'parent_id' => 1, 'name' => 'Child'],
]); // [['id' => 1, ..., 'children' => [['id' => 2, ..., 'children' => []]]]]

ArrayHelper::valuesRecursive(['a' => 1, 'b' => ['a' => 2, 'c' => 3]], 'a'); // [1, 2]

ArrayHelper::pluckRecursive(['id' => 1, 'child' => ['id' => 2]], 'id');    // [1, 2]

ArrayHelper::renameKeysNested(
    [['old' => 1, 'keep' => 'x']],
    ['old' => 'new']
); // [['new' => 1, 'keep' => 'x']]

ArrayHelper::convertKeysToCamel(['foo_bar' => 1, 'baz_qux' => 2]);
// ['fooBar' => 1, 'bazQux' => 2]

ArrayHelper::isListOfArrays([['id' => 1], ['id' => 2]]); // true — a sequential list containing at least one array
ArrayHelper::isListOfArrays(['id' => 1]);                // false

// Normalize request-style scalars: "true"/"false"/"123" -> real bool/int
ArrayHelper::normalizeScalarsRecursive(['active' => 'true', 'count' => '5']);
// ['active' => true, 'count' => 5]

// Join several attributes of ONE related record with " - "
ArrayHelper::joinRelationAttributes(
    ['user' => ['first_name' => 'Ada', 'last_name' => 'Lovelace']],
    ['user', 'first_name@last_name']
); // "Ada - Lovelace"

use CaueSantos\Support\Helpers\ObjectHelper;

ObjectHelper::toArray((object) ['a' => 1, 'b' => (object) ['c' => 2]]);
// ['a' => 1, 'b' => ['c' => 2]]

ObjectHelper::toStdClass(['a' => 1, 'b' => ['c' => 2]]);
// stdClass { a: 1, b: stdClass { c: 2 } }

use CaueSantos\Support\Helpers\DateHelper;

DateHelper::isValidDate('2024-01-31', 'Y-m-d'); // true
DateHelper::isValidDate('2024-02-30', 'Y-m-d'); // false (not a real date)

DateHelper::formatUkDate('2024-03-05');               // "05/03/2024"
DateHelper::formatUkDate('2024-03-05 14:30:00', true); // "05/03/2024 14:30h"

DateHelper::minutesToHours(90);  // "1:30"
DateHelper::minutesToHours(65);  // "1:05"
DateHelper::minutesToHours(120); // "2"

use CaueSantos\Support\Helpers\NumberHelper;

NumberHelper::formatBytes(1536);          // "1.5 KB"
NumberHelper::formatBytes(1024 * 1024);   // "1 MB"

NumberHelper::clamp(15, 0, 10); // 10 — constrain a value between a min and max

NumberHelper::memoryUsage(); // e.g. "2.34 megabytes" — current PHP memory usage

// A low-stakes, human-facing id — NOT guaranteed unique, don't use for
// primary keys or anything security-sensitive.
NumberHelper::almostUniqueId();

use CaueSantos\Support\Helpers\MoneyHelper;

MoneyHelper::toCents(19.99);          // 1999
MoneyHelper::fromCents(1999);         // 19.99
MoneyHelper::formatFromCents(1999);   // "19.99"

// Split $10.00 three ways without losing or gaining a cent to float rounding
MoneyHelper::allocate(1000, 3); // [334, 333, 333] — sums back to exactly 1000

use CaueSantos\Support\Helpers\ValueHelper;

ValueHelper::firstValue(null, '', 'fallback', 'unused'); // "fallback"
ValueHelper::firstValue(null, '', 0, 'unused');          // 0 — Laravel's filled() treats 0 as filled

ValueHelper::valueOrNull('');   // null
ValueHelper::valueOrNull('x');  // "x"

ValueHelper::emptyMultiple(null, '', 0, []); // true
ValueHelper::emptyMultiple(null, 'x');       // false

ValueHelper::isInstanceOfAny($object, [Countable::class, Traversable::class]);
ValueHelper::isInstanceOfAll($object, [Countable::class, Traversable::class]);

use CaueSantos\Support\Helpers\ValidationHelper;

ValidationHelper::toRowValidationAttributes(['name' => 'Name', 'email' => 'Email'], 'rows');
// ['rows.*.name' => 'Name', 'rows.*.email' => 'Email']

use CaueSantos\Support\Helpers\HtmlHelper;

// Safe to drop straight into a Blade attribute: <div data-payload="{{ ... }}">
HtmlHelper::encodeForHtmlAttribute(['id' => 1, 'name' => 'Ada']);

// Array -> HTML attribute string, for contexts outside a Blade component's
// attribute bag (mailables, PDFs, plain-PHP string building)
HtmlHelper::attributes(['class' => 'btn', 'disabled' => true, 'title' => null]);
// 'class="btn" disabled' — true renders bare, false/null are omitted

// A quick Bootstrap-styled <table> from an array/Collection of rows
HtmlHelper::simpleTable(
    [['name' => 'Bob', 'age' => 30], ['name' => 'Sue', 'age' => 25]],
    [
        'name',                                    // dotted attribute path
        'age',
        'label' => fn ($value, $row) => strtoupper($row['name']), // computed column
    ]
);

use CaueSantos\Support\Helpers\FileHelper;

// Written now, deleted automatically at the end of the request
$path = FileHelper::temporaryFile('report.csv', $csvContents);

FileHelper::zip(storage_path('archive.zip'), ['report.csv' => $path]);
FileHelper::unzip(storage_path('extracted'), storage_path('archive.zip'));

FileHelper::generateCsvString([['name', 'age'], ['Ada', 36]]); // "name,age\nAda,36\n"

FileHelper::mimeLabel('image/png');         // "PNG Image"
FileHelper::mimeLabel('application/x-foo'); // "Unknown File" (default fallback)

use CaueSantos\Support\Helpers\UrlHelper;

UrlHelper::isExternal('/dashboard');                     // false — relative
UrlHelper::isExternal('https://example.com/dashboard');  // false — same host as config('app.url')
UrlHelper::isExternal('https://evil.com/dashboard');     // true

// Guard a `?redirect=` query param before redirecting a user to it
UrlHelper::isSafeRedirectTarget($request->query('redirect'));       // true only for a relative path or your own host
UrlHelper::isSafeRedirectTarget('//evil.com/path');                 // false — protocol-relative bypass
UrlHelper::isSafeRedirectTarget('https://partner.com', ['partner.com']); // true — explicit allow-list

use CaueSantos\Support\Helpers\EnumHelper;

EnumHelper::values(Status::class); // ['open', 'closed'] (backing values), or case names for a pure enum
EnumHelper::names(Status::class);  // ['Open', 'Closed']

// value => label pairs for a <select>, defaulting to a "Title Case" label
EnumHelper::toSelectOptions(Status::class);
// ['open' => 'Open', 'closed' => 'Closed']

EnumHelper::toSelectOptions(Status::class, ['Open' => 'Currently open']);
// ['open' => 'Currently open', 'closed' => 'Closed']

use CaueSantos\Support\Helpers\CollectionHelper;

$data = CollectionHelper::toDeepCollection([
    'name' => 'Ada',
    'address' => ['city' => 'London', 'zip' => 'E1'],
]);

$data->name;              // "Ada"
$data['name'];            // "Ada" — same value, array access
$data->address->city;     // "London" — nested arrays become nested Collections too
$data->toArray();         // ['name' => 'Ada', 'address' => ['city' => 'London', 'zip' => 'E1']]

use CaueSantos\Support\Helpers\EloquentHelper;

// Check a relation (or a dot-path of relations) is already loaded, without
// triggering a lazy load — safe to call speculatively.
EloquentHelper::modelHasRelations($post, 'author');
EloquentHelper::modelHasRelations($author, 'posts.comments');

// Build a fresh, unsaved model from a plain array
$mapper = EloquentHelper::mapToModel(Post::class);
$post = $mapper(['title' => 'Hello world']);

// The withXxx() methods return closures for constrained eager loading:
// `Model::with(['relation' => EloquentHelper::withXxx(...)])`. Each one
// normalizes a scalar-or-array-or-null input the way the underlying
// Eloquent method itself doesn't — for a plain where()/orderBy()/
// withTrashed() constraint, just write `fn ($q) => $q->where(...)`
// yourself, it's exactly as short.
Post::with(['author' => EloquentHelper::withoutGlobalScopes()])->get(); // removes every global scope
Post::with(['author' => EloquentHelper::withOnly(['name', 'email'])])->get();
Post::with(['comments' => EloquentHelper::without(['replies'])])->get();
Post::with(['comments' => EloquentHelper::withScope(['published', 'recent' => [30]])])->get();

use CaueSantos\Support\Helpers\SchemaHelper;

SchemaHelper::wrapColumn('name', 'users');    // "`users`.`name`" (grammar-specific quoting)
SchemaHelper::unwrapColumn('`users`.`name`'); // "users.name"

SchemaHelper::buildAggregateExpression('amount', 'sum', 'total'); // "SUM(amount) as total"
SchemaHelper::buildAggregateExpression('id');                     // "COUNT(id)"

SchemaHelper::shortForeignKeyName('a_very_long_table_name', 'a_very_long_column'); // "fk_" + 24-char hash, always <= 64 chars

SchemaHelper::dropColumnIfExists('posts', 'legacy_column');
SchemaHelper::dropForeignKeyIfExists('posts', 'author_id');
SchemaHelper::dropForeignKeyAndColumnIfExists('posts', 'author_id');

use CaueSantos\Support\Helpers\SqlHelper;

SqlHelper::getExpressionByAlias('SELECT COUNT(*) as total FROM posts', 'total'); // "COUNT(*)"

SqlHelper::containsMySQLFunction('CONCAT(first_name, last_name)'); // true
SqlHelper::containsMathOperators('price * 1.2');                  // true
SqlHelper::hasAggregation($query); // true if the query (string or Builder) contains SUM/COUNT/AVG/...

use CaueSantos\Support\Helpers\LaravelHelper;

// 409 response l dependencies.
return LaravelHelper::forceInertiaRedirect(route('posts.index'));

// Log a user in from a queue job without leaking a stale user between jobs
// on a long-running worker (Horizon).
LaravelHelper::queueSafeLogin($job->user_id);

// Every translation file for a locale, flattened into one array keyed by filename
LaravelHelper::loadLocaleTranslations('en');

use CaueSantos\Support\Helpers\CacheHelper;

// If the key is missing, only one process computes the callback while every
// other concurrent caller waits on a lock and then reads the fresh value —
// unlike Cache::remember(), where every concurrent miss runs the callback.
CacheHelper::rememberSafely('expensive-report', now()->addHour(), function () {
    return Report::buildExpensiveReport();
});

use CaueSantos\Support\Helpers\LabelHelper;

LabelHelper::yesNo(true);  // "Yes"
LabelHelper::yesNo(0);     // "No"

LabelHelper::boolLabel($post->is_active, 'Active', 'Inactive');

LabelHelper::statusLabel($post->status, ['draft' => 'Draft', 'published' => 'Published']);
LabelHelper::statusLabel('archived', ['draft' => 'Draft'], default: 'Unknown'); // "Unknown"

use CaueSantos\Support\Helpers\SseHelper;

SseHelper::start(); // sends SSE headers and clears output buffers

foreach ($progressUpdates as $update) {
    SseHelper::send(['percent' => $update], event: 'progress');
}

SseHelper::end('done'); // sends a final "end" event and terminates the request

use CaueSantos\Support\IsHydratable;
use CaueSantos\Support\AutoJsonSerializable;
use Illuminate\Support\Carbon;

class Address
{
    use IsHydratable, AutoJsonSerializable;

    public string $city = '';
    public ?string $zip = null;
}

class Person
{
    use IsHydratable, AutoJsonSerializable;

    public string $name = '';
    public int $age = 0;
    public ?Carbon $joinedAt = null;
    public Address $address;
}

$person = Person::hydrate([
    'name' => 'Ada',
    'age' => '36',                              // cast to int
    'joinedAt' => '2024-01-01',                  // parsed into Carbon
    'address' => ['city' => 'London', 'zip' => 'E1'], // recursively hydrated
]);

$person->age;                  // 36 (int)
$person->joinedAt->isToday();  // false — it's a real Carbon instance
$person->address->city;        // "London"

use CaueSantos\Support\HasSlug;

class Post extends Model
{
    use HasSlug;

    // Optional overrides — these are the defaults:
    public function slugSourceField(): string { return 'name'; }
    public function slugField(): string { return 'slug'; }
    public function shouldUpdateSlugOnUpdate(): bool { return false; }
}

Post::create(['name' => 'My Cool Title'])->slug; // "my-cool-title"

use CaueSantos\Support\HasMetadata;

class Post extends Model
{
    use HasMetadata;

    protected $casts = ['meta' => 'array'];
}

$post->setMeta('seo.title', 'Hello, world');
$post->getMeta('seo.title');        // "Hello, world"
$post->getMeta('seo.missing', 'x'); // "x" — default when missing
$post->hasMeta('seo.title');        // true
$post->forgetMeta('seo.title');

use CaueSantos\Support\InteractsWithEnum;

enum Status: string
{
    use InteractsWithEnum;

    case Open = 'open';
    case Closed = 'closed';
}

Status::Open->label();  // "Open" (Str::headline() of the case name)
Status::options();      // ['open' => 'Open', 'closed' => 'Closed']

use CaueSantos\Support\IsMakeable;

class Money
{
    use IsMakeable;

    public function __construct(public int $cents, public string $currency = 'USD') {}
}

Money::make(500, 'GBP'); // same as `new Money(500, 'GBP')`

use CaueSantos\Support\Component;

$component = Component::make('UserCard', ['id' => 1]);
$component->name; // "UserCard"
$component->data; // ['id' => 1]

use CaueSantos\Support\RuntimeMigration;
use Illuminate\Database\Schema\Blueprint;

$migration = RuntimeMigration::make('posts', function (Blueprint $table) {
    $table->string('title');
    $table->text('body')->nullable();
});

$path = $migration->create(database_path('migrations'));
// writes a real timestamped `..._create_posts_table.php` migration file and
// returns its path

$migration
    ->afterMigrationCreated(fn (string $file, string $table) => Log::info("Generated {$file} for {$table}"))
    ->create(database_path('migrations'));

// Generate an "update" migration for an existing table instead — its down()
// reverses the same add-column statements (MySQL/MariaDB syntax).
$migration->update(database_path('migrations'));