PHP code example of wwwision / types

1. Go to this page and download the library: Download wwwision/types 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/ */

    

wwwision / types example snippets


class Contact {
    public function __construct(public string $name, public int $age) {}
}

final class ContactName {
    public function __construct(public string $value) {}
}
final class ContactAge {
    public function __construct(public int $value) {}
}

#[Description('The full name of a contact, e.g. "John Doe"')]
#[StringBased(minLength: 1, maxLength: 200)]
final class ContactName {
    public function __construct(public string $value) {}
}

#[Description('The current age of a contact, e.g. 45')]
#[IntegerBased(minimum: 1, maximum: 130)]
final class ContactAge {
    public function __construct(public int $value) {}
}

#[Description('The full name of a contact, e.g. "John Doe"')]
#[StringBased(minLength: 1, maxLength: 200)]
final class ContactName {
    private function __construct(public readonly string $value) {}
}

#[Description('The current age of a contact, e.g. 45')]
#[IntegerBased(minimum: 1, maximum: 130)]
final class ContactAge {
    private function __construct(public readonly int $value) {}
}

final class Contact {
    public function __construct(
        public readonly ContactName $name,
        public readonly ContactAge $age,
    ) {}
}

// ...
instantiate(Contact::class, ['name' => 'John Doe', 'age' => 45]);

// ...

#[ListBased(itemClassName: Contact::class)]
final class Contacts implements IteratorAggregate {
    private function __construct(private readonly array $contacts) {}
    
    public function getIterator() : Traversable {
        return new ArrayIterator($this->contacts);
    }
}

interface ContactRepository {
    public function findByName(ContactName $name): Contacts;
}

final class DatabaseContactRepository implements ContactRepository {

    public function __construct(private readonly PDO $pdo) {}

    public function findByName(ContactName $name): Contacts
    {
        $statement = $this->pdo->prepare('SELECT name, age FROM contacts WHERE name = :name');
        $statement->execute(['name' => $name->value]);
        return instantiate(Contacts::class, $statement->fetchAll(PDO::FETCH_ASSOC));
    }
}

#[StringBased]
final class SomeValueObject {
    private function __construct(public readonly string $value) {}
}

// ...

final class SomeComposite {
    public function __construct(
        public readonly SomeValueObject $alreadyValidated,
        public readonly bool $neverInvalid,
    ) {}
}

// this is fine:
instantiate(SomeComposite::class, ['alreadyValidated' => 'some value', 'neverInvalid' => true]);

// and so is this:
new SomeComposite(instantiate(SomeValueObject::class, 'some value'), true);

#[StringBased(format: StringTypeFormat::date, pattern: '^1980')]
final class Date {
    private function __construct(public readonly string $value) {}
    
    public function add(\DateInterval $interval): self
    {
        return instantiate(self::class, \DateTimeImmutable::createFromFormat('Y-m-d', $this->value)->add($interval)->format('Y-m-d'));
    }
}

$date = instantiate(Date::class, '1980-12-30');
$date = $date->add(new \DateInterval('P1D'));

// this is fine
assert($date->value === '1980-12-31');

// this is not because of the "pattern"
$date = $date->add(new \DateInterval('P1D'));

// Exception: Failed to cast string of "1981-01-01" to Date: invalid_string (Value does not match regular expression)

#[Description('This is a description for this class')]
final class SomeClass {

    public function __construct(
        #[Description('This is some overridden description for this parameter')]
        public readonly bool $someProperty,
    ) {}
}

assert(Parser::getSchema(SomeClass::class)->overriddenPropertyDescription('someProperty') === 'This is some overridden description for this parameter');

#[IntegerBased(minimum: 0, maximum: 123)]
final class SomeIntBased {
    private function __construct(public readonly int $value) {}
}

instantiate(SomeIntBased::class, '-5');

// Exception: Failed to cast string of "-5" to SomeIntBased: too_small (Number must be greater than or equal to 0)

#[FloatBased(minimum: 12.34, maximum: 30)]
final class SomeFloatBased {
    private function __construct(public readonly float $value) {}
}

instantiate(SomeFloatBased::class, 12);

// Exception: Failed to cast integer value of 12 to SomeFloatBased: too_small (Number must be greater than or equal to 12.340)

#[StringBased(minLength: 1, maxLength: 200)]
final class GivenName {
    private function __construct(public readonly string $value) {}
}

instantiate(GivenName::class, '');

// Exception: Failed to cast string of "" to GivenName: too_small (String must contain at least 1 character(s))

#[StringBased(format: StringTypeFormat::email, pattern: '@your.org$')]
final class EmployeeEmailAddress {
    private function __construct(public readonly string $value) {}
}

instantiate(EmployeeEmailAddress::class, '[email protected]');

// Exception: Failed to cast string of "[email protected]" to EmployeeEmailAddress: invalid_string (Value does not match regular expression)

#[StringBased]
final class Hobby {
    private function __construct(public readonly string $value) {}
}

#[ListBased(itemClassName: Hobby::class)]
final class Hobbies implements IteratorAggregate {
    private function __construct(private readonly array $hobbies) {}
    
    public function getIterator() : Traversable {
        return new ArrayIterator($this->hobbies);
    }
}

instantiate(Hobbies::class, ['Soccer', 'Ping Pong', 'Guitar']);

// ...

/**
 * @implements IteratorAggregate<Hobby> 
 */
#[Description('A list of hobbies')]
#[ListBased(itemClassName: Hobby::class, minCount: 1, maxCount: 3)]
final class HobbiesAdvanced implements IteratorAggregate, Countable, JsonSerializable {
    /** @param array<Hobby> $hobbies */
    private function __construct(private readonly array $hobbies) {}
    
    public function getIterator() : Traversable {
        return new ArrayIterator($this->hobbies);
    }
    
    public function count(): int {
        return count($this->hobbies);
    }
    
    public function jsonSerialize() : array {
        return array_values($this->hobbies);
    }
}

instantiate(HobbiesAdvanced::class, ['Soccer', 'Ping Pong', 'Guitar', 'Gaming']);

// Exception: Failed to cast value of type array to HobbiesAdvanced: too_big (Array must contain at most 3 element(s))

#[StringBased]
final class GivenName {
    private function __construct(public readonly string $value) {}
}

#[StringBased]
final class FamilyName {
    private function __construct(public readonly string $value) {}
}

final class FullName {
    public function __construct(
        public readonly GivenName $givenName,
        public readonly FamilyName $familyName,
    ) {}
}

#[Description('honorific title of a person')]
enum HonorificTitle
{
    #[Description('for men, regardless of marital status, who do not have another professional or academic title')]
    case MR;
    #[Description('for married women who do not have another professional or academic title')]
    case MRS;
    #[Description('for girls, unmarried women and married women who continue to use their maiden name')]
    case MISS;
    #[Description('for women, regardless of marital status or when marital status is unknown')]
    case MS;
    #[Description('for any other title that does not match the above')]
    case OTHER;
}

#[Description('A contact in the system')]
final class Contact {
    public function __construct(
        public readonly HonorificTitle $title,
        public readonly FullName $name,
        #[Description('Whether the contact is registered or not')]
        public bool $isRegistered = false,
    ) {}
}

// Create a Contact instance from an array
$person = instantiate(Contact::class, ['title' => 'MRS', 'name' => ['givenName' => 'Jane', 'familyName' => 'Doe']]);
assert($person->name->familyName->value === 'Doe');
assert($person->isRegistered === false);

// Retrieve the schema for the Contact class
$schema = Parser::getSchema(Contact::class);
assert($schema->getDescription() === 'A contact in the system');
assert($schema->propertySchemas['isRegistered']->getDescription() === 'Whether the contact is registered or not');
 (no test)
#[Generic('TKey', 'TValue')]
final class Collection {
    // ...
}

// won't work as of now:
$posts = generic(Collection::class, $dbRows, TKey: Types::int(), TValue: Types::classOf(Post::class));

interface SimpleOrComplexObject {
    public function render(): string;
}

#[StringBased]
final class SimpleObject implements SimpleOrComplexObject {
    private function __construct(private readonly string $value) {}
    public function render(): string {
        return $this->value;
    }
}

final class ComplexObject implements SimpleOrComplexObject {
    private function __construct(private readonly string $prefix, private readonly string $suffix) {}
    public function render(): string {
        return $this->prefix . $this->suffix;
    }
}

$simpleObject = instantiate(SimpleOrComplexObject::class, ['__type' => SimpleObject::class, '__value' => 'Some value']);
assert($simpleObject instanceof SimpleObject);

$complexObject = instantiate(SimpleOrComplexObject::class, ['__type' => ComplexObject::class, 'prefix' => 'Prefix', 'suffix' => 'Suffix']);
assert($complexObject instanceof ComplexObject);

// ...

#[ListBased(itemClassName: SimpleOrComplexObject::class)]
final class SimpleOrComplexObjects implements IteratorAggregate {
    public function __construct(private readonly array $objects) {}
    
    public function getIterator() : Traversable{
        return new ArrayIterator($this->objects);
    }
    
    public function map(Closure $closure): array
    {
        return array_map($closure, $this->objects);
    }
}

$objects = instantiate(SimpleOrComplexObjects::class, [
    ['__type' => SimpleObject::class, '__value' => 'Simple'],
    ['__type' => ComplexObject::class, 'prefix' => 'Com', 'suffix' => 'plex'],
]);

assert($objects->map(fn (SimpleOrComplexObject $o) => $o->render()) === ['Simple', 'Complex']);