atomsk/polyprops

A lightweight library for property validation and object-to-array/JSON conversion using Symfony Validator and traits.

Installs: 2

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Watchers: 0

Forks: 0

Open Issues: 0

pkg:composer/atomsk/polyprops

v1.0.0 2026-02-12 23:22 UTC

This package is auto-updated.

Last update: 2026-02-12 23:48:54 UTC


README

PHP Pipeline Status Downloads Latest Version

How to install

composer require atomsk/polyprops

Configuration

Polyprops uses Symfony Validator under the hood. It works out of the box with PHP attributes for validation constraints.

⚠️ IMPORTANT

For optimal performance and security:

  • Use protected properties for your data. The Validates trait uses __set to trigger validation automatically when a protected property is modified from outside (via magic setter).
  • Public properties are only validated during factory creation (fromArray, fromJson). If you modify a public property directly after the object is created, no automatic validation will occur.
  • Avoid overriding __set unless you manually call $this->validate() within it, as it may break the automatic validation mechanism.

Example

Basic Usage

<?php

use atomsk\Polyprops\Traits\Validates;
use atomsk\Polyprops\Traits\AsArray;
use atomsk\Polyprops\Contracts\Validatable;
use Symfony\Component\Validator\Constraints as Assert;

class User implements Validatable
{
    use Validates, AsArray;

    #[Assert\NotBlank]
    #[Assert\Email]
    protected string $email;

    #[Assert\Length(min: 8)]
    protected string $password;
    
    // Public properties are only validated on creation
    #[Assert\Range(min: 18)]
    public int $age;
}

// Creation via Factory (validates immediately)
$user = User::fromArray([
    'email' => 'user@example.com',
    'password' => 'secret123',
    'age' => 25
]);

// Updating a protected property (triggers automatic validation via __set)
$user->email = 'new-email@example.com'; 

// Converting back to array
$data = $user->toArray();

JSON Support

<?php

use atomsk\Polyprops\Traits\AsJson;
use atomsk\Polyprops\Contracts\Validatable;
use Symfony\Component\Validator\Constraints as Assert;

class Product implements Validatable
{
    use AsJson, Validates;

    #[Assert\NotBlank]
    protected string $sku;
}

$product = Product::fromJson('{"sku": "ABC-123"}');
echo $product->toJson();

Standalone Trait Usage

You can use AsArray or AsJson without the Validates trait if you only need the conversion features without validation.

<?php

use atomsk\Polyprops\Traits\AsArray;

class SimpleUser
{
    use AsArray;

    public string $name;
    public string $role;
}

// Works even without the Validates trait or Validatable contract
$user = SimpleUser::fromArray(['name' => 'Alice', 'role' => 'admin']);
$data = $user->toArray();

The Importance of the Validatable Contract

Automatic validation during factory creation (fromArray, fromJson) only occurs if your class implements the Validatable contract. If you use the traits without the contract, you must call validate() manually.

<?php

use atomsk\Polyprops\Traits\Validates;
use atomsk\Polyprops\Traits\AsArray;
use Symfony\Component\Validator\Constraints as Assert;

// Missing "implements Validatable"
class IncompleteUser
{
    use AsArray, Validates;

    #[Assert\Email]
    public string $email;
}

// No validation occurs here even if the email is invalid!
$user = IncompleteUser::fromArray(['email' => 'not-an-email']);

// You must validate manually if the contract is missing
// $user->validate(); 

Manual Validation & Error Handling

You can also trigger validation manually and handle errors using the ObjectValidationException.

<?php

use atomsk\Polyprops\Traits\Validates;
use atomsk\Polyprops\Exceptions\ObjectValidationException;
use Symfony\Component\Validator\Constraints as Assert;

class Contact
{
    use Validates;

    #[Assert\NotBlank]
    public string $name;

    #[Assert\Email]
    public string $email;
}

$contact = new Contact();
$contact->name = 'John';
$contact->email = 'invalid-email';

try {
    $contact->validate();
} catch (ObjectValidationException $e) {
    // Get all error messages grouped by property
    $errors = $e->errorsBag();
    
    /*
    [
        "email" => ["This value is not a valid email address."]
    ]
    */
}

AI & Automation Guidelines

This repository defines guidelines for AI-assisted work. First, read AI.md (single source of truth):

License

MIT - Open source, free to use and modify.