artisanbr/goodies

Laravel/PHP goodies pack by Artisan Digital

Maintainers

Package info

github.com/artisanbr/goodies

Type:package

pkg:composer/artisanbr/goodies

Transparency log

Statistics

Installs: 169

Dependents: 0

Suggesters: 0

Stars: 1

Open Issues: 0

v0.0.6 2026-08-25 08:15 UTC

This package is auto-updated.

Last update: 2026-08-25 08:23:02 UTC


README

Latest Version License PHP Version Laravel

Um conjunto de "goodies" (utilitários) para projetos Laravel da Artisan Digital: macros para os componentes nativos do framework, traits para Enums, traits/observers para Models e alguns helpers globais de PHP e Blade.

Índice

Instalação

Instale o pacote via Composer:

composer require artisanbr/goodies

O pacote utiliza package discovery do Laravel, então o GoodiesServiceProvider é registrado automaticamente. Nenhuma configuração adicional é necessária para usar as macros e os helpers globais.

Configuração

Se quiser customizar as opções do pacote, publique o arquivo de configuração:

php artisan vendor:publish --provider="ArtisanBR\Goodies\GoodiesServiceProvider"

Isso irá gerar config/goodies.php:

return [
    'user_relation_key' => 'user_id',
];
  • user_relation_key: nome da coluna usada como foreign key do usuário logado pela trait BelongsToUser e pelo BelongsToUserObserver.

Macros

Todas as macros abaixo são registradas automaticamente no boot() do service provider — basta ter o pacote instalado para usá-las.

Stringable

Stringable::limitPath()

Encurta um caminho de arquivo/URL mantendo os primeiros e últimos segmentos, útil para exibir paths longos de forma legível.

str('app/Http/Controllers/Api/V1/UserController.php')
    ->limitPath(keepFirst: 1, keepLast: 2);
// "app/.../V1/UserController.php"

Assinatura: limitPath(string $path, int $keepFirst = 1, int $keepLast = 2, string $ellipsis = '...'): string

Eloquent Builder

whereAnyLike()

Busca (LIKE) em múltiplos atributos — inclusive em relacionamentos, usando a notação relacionamento.atributo — combinados com OR.

User::query()
    ->whereAnyLike(['name', 'email', 'profile.bio'], 'joão')
    ->get();

// case-sensitive
User::query()->whereAnyLike('name', 'João', sensitive: true)->get();

Assinatura: whereAnyLike(array|string $attributes, string $searchTerm, bool $sensitive = false)

Query Builder (DB)

whereLikeAny()

Equivalente ao whereAnyLike(), mas para o Query Builder puro (DB::table()), aceitando um ou vários termos de busca.

DB::table('users')
    ->whereLikeAny(['name', 'email'], ['joão', 'maria'])
    ->get();

Assinatura: whereLikeAny(array|string $attributes, array|string $searchTerm)

Collection

whereLike()

Filtra uma Collection (de arrays, objetos ou Models) verificando se algum dos atributos contém qualquer um dos termos informados. Suporta notação em "ponto" (categoria.nome) via data_get() e um callback opcional de escape.

collect($items)->whereLike(['name', 'category.name'], 'eletrônico');

collect($items)->whereLike('name', ['a', 'b'], escape: fn ($item) => $item['featured']);

even() / odd()

Filtram os itens pelo índice (chave) par ou ímpar.

collect([1, 2, 3, 4])->even(); // [0 => 1, 2 => 3]
collect([1, 2, 3, 4])->odd();  // [1 => 2, 3 => 4]

mapRecursive()

Aplica um callback recursivamente em todos os valores da coleção (via array_walk_recursive).

collect(['a' => 1, 'b' => ['c' => 2]])->mapRecursive(function (&$value) {
    $value *= 10;
});

keyByValues()

Atalho para keyBy(fn ($item) => $item) — indexa a coleção pelos próprios valores.

collect(['a', 'b', 'c'])->keyByValues();
// ['a' => 'a', 'b' => 'b', 'c' => 'c']

dataGet()

Atalho para data_get() sobre o array da coleção, já retornando uma nova Collection.

collect(['user' => ['name' => 'João']])->dataGet('user.name');

toExtensions()

Prefixa cada item da coleção com um ponto, transformando uma lista de extensões em formato .ext.

collect(['pdf', 'jpg', 'png'])->toExtensions();
// ['.pdf', '.jpg', '.png']

fromFilamentBuilder() / toFilamentBuilder()

Convertem coleções entre o formato "flat" e o formato {type, data} usado pelo Filament Builder field, útil ao persistir/ler dados de blocos dinâmicos do Filament fora do próprio field.

// De [{'type' => 'text', 'data' => ['value' => 'foo']}, ...] para [{'type' => 'text', 'value' => 'foo'}, ...]
collect($filamentBuilderState)->fromFilamentBuilder();

// E de volta ao formato do Filament Builder
collect($flatItems)->toFilamentBuilder();

Traits para Enums

Traits pensadas para Enums nativos do PHP (enum ... : string), acrescentando conveniências comuns em Enums de Laravel.

EnumToArray

use ArtisanBR\Goodies\Enums\Traits\EnumToArray;

enum Status: string
{
    use EnumToArray;

    case Active = 'active';
    case Inactive = 'inactive';
}

Status::names();  // ['Active', 'Inactive']
Status::values(); // ['active', 'inactive']
Status::array();  // ['active' => 'Active', 'inactive' => 'Inactive']
Status::toArray(); // idem a array()

EnumBase

Já inclui EnumToArray e adiciona comparações rápidas com o value do Enum.

use ArtisanBR\Goodies\Enums\Traits\EnumBase;

enum Status: string
{
    use EnumBase;

    case Active = 'active';
    case Inactive = 'inactive';
    case Blocked = 'blocked';
}

$status = Status::Active;

$status->is('active');               // true
$status->isAny('inactive', 'blocked'); // false

EnumWithTitles

Gera títulos legíveis (e traduzíveis via __()) a partir do nome de cada case, separando palavras em PascalCase/camelCase.

use ArtisanBR\Goodies\Enums\Traits\EnumWithTitles;

enum Status: string
{
    use EnumWithTitles;

    case AwaitingPayment = 'awaiting_payment';
    case Shipped = 'shipped';
}

Status::AwaitingPayment->title(); // "Awaiting Payment"
Status::titles();
// ['awaiting_payment' => 'Awaiting Payment', 'shipped' => 'Shipped']

As três traits podem ser combinadas normalmente com use EnumBase, EnumWithTitles; em um mesmo Enum.

Traits e Observers para Models

BelongsToUser + BelongsToUserObserver

A trait BelongsToUser adiciona um relacionamento user() (e o alias owner()) ao Model, usando o model de usuário configurado em auth.providers.users.model. O BelongsToUserObserver preenche automaticamente a foreign key do usuário logado ao criar um novo registro.

A coluna usada é resolvida nesta ordem: propriedade estática $userRelationKey no Model → config('goodies.user_relation_key')'user_id'.

use ArtisanBR\Goodies\Traits\BelongsToUser;
use ArtisanBR\Goodies\Observers\BelongsTo\BelongsToUserObserver;
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
use Illuminate\Database\Eloquent\Model;

#[ObservedBy(BelongsToUserObserver::class)]
class Post extends Model
{
    use BelongsToUser;

    // opcional: customiza o nome da coluna para este model
    public static string $userRelationKey = 'author_id';
}
$post = Post::create(['title' => 'Olá mundo']);
$post->user_id; // preenchido automaticamente com o id do usuário autenticado

$post->user;  // relacionamento BelongsTo
$post->owner; // alias de user()

Caso prefira registrar o observer manualmente (sem o atributo #[ObservedBy]), use Post::observe(BelongsToUserObserver::class) no boot() de um EventServiceProvider/AppServiceProvider.

SelfRelationship

Adiciona uma relação hierárquica simples (pai/filhos) a um Model que referencia a si mesmo através de uma coluna parent_id, além de scopes para filtrar por hierarquia.

use ArtisanBR\Goodies\Traits\SelfRelationship;
use Illuminate\Database\Eloquent\Model;

class Category extends Model
{
    use SelfRelationship;
}
$category->parent;   // BelongsTo self, via parent_id
$category->children; // HasMany self, via parent_id

Category::whereParent($categoryId)->get(); // filhos diretos de um registro
Category::whereIsParent()->get();          // apenas registros raiz (parent_id null)

Helpers globais

Funções globais carregadas automaticamente pelo Composer (files autoload).

array_filter_recursive()

Igual ao array_filter() nativo, mas aplicado recursivamente em arrays aninhados.

array_filter_recursive([
    'a' => 1,
    'b' => ['c' => 0, 'd' => 2],
]);
// ['a' => 1, 'b' => ['d' => 2]]

Assinatura: array_filter_recursive(array $array, ?callable $callback = null, int $mode = 0): array

Helpers de componentes Blade

Utilitários para agrupar atributos de componentes Blade por prefixo — útil para repassar, por exemplo, todos os atributos wrapper-* para o elemento wrapper de um componente e input-* para o input interno.

attributesBagGroup()

{{-- <x-field wrapper-class="mb-4" input-placeholder="Digite aqui" /> --}}

@php
    $wrapperAttrs = attributesBagGroup('wrapper', $attributes);
    $inputAttrs = attributesBagGroup('input', $attributes);
@endphp

<div {{ $wrapperAttrs }}>
    <input {{ $inputAttrs }} />
</div>

Também aceita um array de prefixos, retornando os atributos que casarem com qualquer um deles:

attributesBagGroup(['wrapper', 'container'], $attributes);

Assinatura: attributesBagGroup(string|array $groupName, ComponentAttributeBag $attributes): ComponentAttributeBag

BladeComponentPrefix

Classe invocável utilitária para prefixar nomes de componentes Blade dinamicamente (por exemplo, ao registrar um namespace de componentes de um pacote).

use ArtisanBR\Goodies\Support\Blade\BladeComponentPrefix;

$resolver = new BladeComponentPrefix('goodies');

$resolver('button'); // "goodies-button"

$resolver = new BladeComponentPrefix(null);
$resolver('button'); // "button" (sem prefixo)

Licença

Este pacote é open-source e distribuído sob a licença MIT.