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

Validácia naprieč atribútmi

Predvolene sa každá hodnota overuje len voči svojej definícii, takže pravidlo, ktoré sa odvoláva na iný atribút — gte:min_price, required_if:kind,physical —, ho nevidí a zlyhá. Validácia celej množiny namiesto toho overí množinu, ktorú bude vlastník mať, jedným prechodom validátora:

use RoundlyConsulting\Attributes\DataTransferObjects\AttributeDefinitionData;
use RoundlyConsulting\Attributes\Enums\AttributeType;
use RoundlyConsulting\Attributes\Facades\Attributes;

Attributes::defineMany(
    new AttributeDefinitionData('min_price', AttributeType::Integer, ['lte:max_price']),
    new AttributeDefinitionData('max_price', AttributeType::Integer, ['gte:min_price']),
    new AttributeDefinitionData('kind', AttributeType::String_, ['in:physical,digital']),
    new AttributeDefinitionData('weight', AttributeType::Float_, ['required_if:kind,physical']),
);

setValidated()

Attributes::for($owner)->setValidated([...]) vezme uložené hodnoty vlastníka — načítané nanovo, šifrované dešifrované —, prekryje ich zapisovanými, výsledok overí ako jednu množinu a potom zapíše všetko alebo nič. Prijíma rovnakú mapu metadát podľa názvu ako setMany() a vracia zapísané modely Attribute:

use RoundlyConsulting\Attributes\Facades\Attributes;

Attributes::for($product)->setValidated(['min_price' => 10, 'max_price' => 20]);
Attributes::for($product)->setValidated(['max_price' => 5]);     // throws: min_price must be ≤ 5

Attributes::for($product)->setValidated(['kind' => 'physical']); // throws: weight is required
Attributes::for($product)->setValidated(['kind' => 'physical', 'weight' => 1.5]); // fine

// The per-value path can't see the other attribute, so it fails the same rules
Attributes::for($product)->setMany(['min_price' => 1, 'max_price' => 5]); // throws

Ako sa množina overuje

  • Uplatnia sa pravidlá každej definície, na začiatku s nullable a pravidlom typu — aj pre definovaný názov, ktorý nie je pripojený, takže implicitné pravidlá (required_if, required_with) zaberú.
  • Hodnota null prejde všetkými pravidlami okrem implicitných, rovnako ako pri overovaní jednotlivých hodnôt. Voľné názvy bez definície nemajú pravidlá, no dá sa na ne odvolať.
  • Overia sa aj atribúty, na ktoré zápis nesiahne: zápis, ktorý poruší pravidlo iného atribútu, zlyhá, a už uložená neplatná hodnota blokuje zápisy, kým ju neopravíte.
  • Prísny režim a rozsahy jedinečnosti platia pre zapisované názvy ako zvyčajne; schéma modelu vlastníka sa započíta ako všade inde.
  • Ak čokoľvek zlyhá, nezapíše sa nič.

Pravidlá sa správajú presne ako vo form requeste — gte:min_price zlyhá, kým min_price chýba. Samostatnú hodnotu povolíte cez exclude_without:

// gte:min_price fails while min_price is missing — as in a form request.
// Allow a lone bound with exclude_without:
Attributes::defineMany(
    new AttributeDefinitionData('min_price', AttributeType::Integer, ['exclude_without:max_price', 'lte:max_price']),
    new AttributeDefinitionData('max_price', AttributeType::Integer, ['exclude_without:min_price', 'gte:min_price']),
);

Attributes::for($product)->setValidated(['max_price' => 3]); // fine

// A name with a dot is taken literally; escape it in a rule that refers to it
new AttributeDefinitionData('size.height', AttributeType::Integer, ['lte:size\.width']);

Chyby

Neplatná množina vyhodí InvalidAttributeValueException s bagom chýb podľa názvov atribútov:

use RoundlyConsulting\Attributes\Exceptions\InvalidAttributeValueException;

try {
    Attributes::for($product)->setValidated(['max_price' => 5]);
} catch (InvalidAttributeValueException $e) {
    $e->attributeName;       // 'min_price' — the first failing name, in definition order
    $e->errorBag()->keys();  // ['min_price', 'max_price'] — keyed by attribute name
    $e->messages();          // ['min_price: The min_price field must be less than or equal to 5.', ...]
}

Súbežné zápisy

Zápis beží v jednej transakcii so zamknutým riadkom vlastníka (SELECT … FOR UPDATE podľa primárneho kľúča), takže dva zápisy celej množiny toho istého vlastníka prebehnú jeden po druhom a druhý overí množinu, ktorú zanechal prvý — dvaja ľudia ukladajúci ten istý záznam tak nemôžu spoločne vytvoriť kombináciu, ktorú by nesmel uložiť ani jeden z nich. Ak model atribútu žije na inom spojení ako vlastník, spojenie vlastníka otvorí vlastnú transakciu, ktorá zámok drží.

  • Zápisy overujúce hodnoty jednotlivo zámok vlastníka neberú, takže miešanie oboch ciest pri jednom vlastníkovi sa neserializuje — zapnite validation.whole_set a cez zámok pôjde každý zápis.
  • Na MySQL (REPEATABLE READ) nečítajte atribúty vlastníka skôr vo vonkajšej transakcii, do ktorej zápis balíte — snímka by vznikla pred zámkom.

Pre každý zápis

Nastavte validation.whole_set a rovnakou cestou pôjdu aj bežné zapisovacie metódy. Predvolene je vypnuté:

# .env — every value write validates the owner's whole set
ATTRIBUTES_VALIDATE_WHOLE_SET=true
// With validation.whole_set on, the everyday writers validate the whole set too
Attributes::for($product)->set('max_price', 30);
Attributes::for($product)->setMany(['min_price' => 5, 'max_price' => 8]);
$product->attributes()->set('kind', 'digital')->save();
Attributes::for($product)->sync(['kind' => 'digital']);  // validates the new set alone

$product->validateAttributes(); // the stored set, as one

set(), setMany(), stage()->save() a sync() potom overujú ako setValidated() — sync overí len zadanú množinu, pretože zvyšok sa odpojí, a pri zlyhaní neodpojí nič. meta() zostáva pri overovaní po jednom názve, keďže hodnotu nemení. validateAttributes() najprv ohlási chýbajúci povinný atribút a potom overí uloženú množinu naraz.

Overenie bez zápisu

Attributes::validateSet($owner, $values) overí celú množinu a nezapíše nič — pre formulár, ktorý má ukázať chyby ešte pred uložením:

use RoundlyConsulting\Attributes\Facades\Attributes;

// Validate a complete set without writing — e.g. a form's input over the stored values
Attributes::validateSet($product, [
    ...Attributes::for($product)->toKeyValue(),
    ...$request->input('attributes', []),
]);

Odovzdajte celú množinu: validateSet() uložené hodnoty sám nedopĺňa.

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.