NovinkaZverejnili sme 50+ Laravel balíkov ako open source
Custom AI apps, agents and automation — Roundly ConsultingRoundly
Všetky balíky
Tags for Laravel

Správa štítkov

Tags::type($type) je katalóg jedného typu. Každý zápis ide cez neho — model Tag slúži len na čítanie — takže slugy, cesty, počty použití aj udalosti zostanú správne aj pri súbežných zápisoch.

Vytváranie a seedovanie

use RoundlyConsulting\Tags\DataTransferObjects\TagData;

$genres = Tags::type('genre');

// The builder…
$music = $genres->make(['en' => 'Music', 'sk' => 'Hudba'])->color('#f24e29')->create();
$jazz = $genres->make('Jazz')->under($music)->position(0)->create();

// …or the DTO — the same code path
$rock = $genres->create(new TagData(name: 'Rock', parent: $music, icon: 'guitar'));

// Idempotent seeding: an existing tag is returned unchanged (never moved, recoloured or renamed),
// a missing one is created with every attribute — so the seeder may run again
$bebop = $genres->make('Bebop')->under($jazz)->color('#a7c4d6')->findOrCreate();
$live = Tags::type('label')->findOrCreate('Live');            // a name, a locale map or a TagData

create() odmietne názov, ktorý v niektorom jazyku drží živý štítok toho istého typu a rozsahu (DuplicateTagException), a obnoví zmazaný štítok, ktorý ho drží, s novými atribútmi a na pôvodnom mieste, pokiaľ nezadáte rodiča (namiesto TagCreated sa spustí TagRestored). findOrCreate() hľadá názov v rozsahu, inak globálne, a nájdený štítok vráti bez zmeny — zmazaný sa vráti taký, aký bol, a presunie ho len zadaný rodič (pozrite Názvy, slugy a preklady); mapa jazykov sa porovnáva podľa záznamu aktuálneho jazyka (inak prvého) a ostatné záznamy len doplnia novovytvorený štítok. Je povolené aj pre kurátorované typy — ide o výslovné volanie katalógu — a dve súbežné volania skončia jedným štítkom.

Hľadanie

$genres = Tags::type('genre');

$genres->find('jazz');              // a live tag by slug or name (along the locale chain), a key or a model
$genres->find(12);                  // by primary key (int)
$genres->findOrFail('jazz');        // TagNotFoundException when missing
$genres->findMany($ids);            // by keys, in the order given — malformed, foreign or missing keys skipped
$genres->findTrashed('jazz');       // a deleted tag of exactly this handle's scope, to restore it

$genres->all();                     // every live tag of the type, by position
$genres->roots();                   // the roots (every tag of a flat type)
$genres->query()->where('usage_count', '>', 10)->get();   // Builder<Tag> of the readable scopes

Tags::find($key);                   // a live tag of any type by primary key
Tags::findOrFail($key);

Úpravy

use RoundlyConsulting\Tags\DataTransferObjects\UpdateTagData;

// Fluently — only what you call changes
Tags::type('genre')->edit($jazz)->name('Jazz music')->color(null)->save();

// A rename of the current locale, or of several locales at once
Tags::type('genre')->rename($jazz, 'Jazz music');
Tags::type('genre')->rename($jazz, ['en' => 'Jazz music', 'sk' => 'Jazzová hudba']);

// The DTO — fields left out stay; null clears a description, colour or icon
Tags::type('genre')->update($jazz, new UpdateTagData(description: null, icon: 'sax'));

// A null (or blank) description entry clears that locale only
Tags::type('genre')->edit($jazz)->description(['sk' => null])->save();

Mapa názvu či popisu sa zlúči s uloženou po jazykoch; prázdna alebo null položka popisu vymaže len daný jazyk. Premenovanie na slug, ktorý drží iný štítok, sa odmietne — a ak ho drží zmazaný štítok, odkáže na restore(). TagUpdated sa spustí so zmenenými atribútmi (name, description, slug, color, icon); volanie, ktoré nič nezmení, nespustí nič.

Mazanie a obnova

use RoundlyConsulting\Tags\Enums\TagChildren;

$genres = Tags::type('genre');

$genres->delete($rock);                                   // soft-deletes it and detaches it everywhere
$genres->delete($music);                                  // TagHasChildrenException while it has live children
$genres->delete($music, TagChildren::Reparent);           // children move up to its parent
$genres->delete($music, TagChildren::Delete);             // the whole subtree goes

$genres->restore($rock);                                  // back, with no old taggings
$genres->restore($genres->findTrashed('rock'));           // find it by name first

delete() štítok soft-deletne a v tej istej transakcii ho odpojí od každého modelu, takže znovu vytvorený štítok s rovnakým názvom nikdy neoznačí staré záznamy. Untagged pre jednotlivé modely sa nespustí — TagDeleted nesie počet odstránených priradení. Zmazanie už zmazaného štítku či obnova živého ho vráti bez zmeny a nespustí nič. restore() odmietne dieťa, ktorého rodič je stále zmazaný, prepočíta jeho cestu podľa aktuálneho miesta rodiča — kde sa spolu so živým podstromom musí zmestiť do limitu hĺbky typu — a pod nezmeneným rodičom mu ponechá pozíciu; obnova rodiča obnoví len tento štítok.

Obyčajné $tag->delete()

// An admin panel calling Eloquent directly — safe, but it detaches nothing
$tag->delete();

// Reads ignore the leftover taggings at once; a restore through the package starts clean,
// and tags:doctor reports them as an error until you run:
// php artisan tags:repair --orphans

Model Tag

RoundlyConsulting\Tags\Models\Tag sa dá vymeniť cez tags.models.tag (podtriedou). Používa HasSlug zo sluggable, HasTranslations z translatable, SoftDeletes a HasFactory:

$jazz->type;                   // 'genre'
$jazz->name;                   // in the current locale
$jazz->slug;                   // in the current locale
$jazz->slugFor('sk');          // one locale's slug, or null
$jazz->description;
$jazz->color;                  // '#f24e29' or null
$jazz->icon;
$jazz->parent_id;
$jazz->depth;                  // 1 for a root
$jazz->position;               // among its siblings
$jazz->usage_count;            // taggings, kept in the same transaction as each write
$jazz->definition();           // its TagType

Tag::query()->ofType('genre')->within($team)->roots()->ordered()->get();
AtribútVýznam
typeNázov typu; nikdy sa nemení.
scope_type, scope_id, scope()Vlastník štítku s rozsahom (pri globálnom null); nikdy sa nemení. scope_type je pri serializácii skrytý.
scope_keyInterný a skrytý: '' pre globálny štítok, inak morph trieda a kľúč vlastníka, aby unikátny index slugov viazal aj globálne štítky. Odvodí sa pri každom uložení.
parent_id, path, depthStrom: path je zhmotnená reťaz kľúčov predkov (/ pre koreň), depth 1 pre koreň.
positionPoradie medzi súrodencami (0 je prvé).
name, description, slugPreložiteľné: čítajú sa v aktuálnom jazyku; getTranslations('name') vráti mapu jazykov, slugFor($locale) slug jedného jazyka.
color, icon#rrggbb alebo null; identifikátor či emoji, alebo null.
usage_countPočet priradení štítku, upravený v tej istej transakcii ako každý zápis — všetky triedy modelov, vrátane soft-deleted modelov.
wasRecentlyRestoredObyčajná vlastnosť, obdoba wasRecentlyCreated: inštancia bola práve obnovená zo zmazaných.
MetódaČo robí
definition()Vyhodnotený TagType štítku.
parent() / children()BelongsTo a HasMany; deti podľa pozície.
ancestors()Od koreňa, jedným dotazom — alebo bez dotazu, ak ich načítal loadAncestors(). Vždy nová kolekcia.
descendants() / siblings()Buildery živých štítkov pod ním a živých štítkov s rovnakým rodičom, typom a rozsahom.
isRoot()Bez rodiča.
taggings()HasMany riadkov spojovacej tabuľky (Models\Tagging).
taggedModels($class)Modely jednej triedy, ktoré štítok nesú — len na čítanie, ako tags().
ofType(), within($scope, $includeGlobal = true), global(), roots(), descendantsOf($tag, self: false), ordered()Query scopes na Tag::query().

Prejavte lásku k open source

Tento balík je zadarmo pod licenciou MIT. Ak vám šetrí čas, jednorazový príspevok alebo členstvo na Patreone nám pomôže ho ďalej udržiavať, testovať a dokumentovať.

Ďalšie spôsoby podpory vrátane kryptomien

Odoslaním daru súhlasíte s našimi podmienkami prijímania darov.

Chcete to zabudovať do svojho produktu?

Naše balíky integrujeme do zákazkových Laravel a AI riešení. Napíšte nám, na čom pracujete, a ozveme sa do 48 hodín.