{"id":13601107,"url":"https://github.com/smartemailing/types","last_synced_at":"2026-01-14T11:17:26.732Z","repository":{"id":30188077,"uuid":"120154082","full_name":"smartemailing/types","owner":"smartemailing","description":"Missing data types for PHP. Highly extendable.","archived":false,"fork":false,"pushed_at":"2025-09-05T07:52:55.000Z","size":727,"stargazers_count":94,"open_issues_count":4,"forks_count":12,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-10-24T18:21:45.693Z","etag":null,"topics":["php","strict-types","validation","value-object"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/smartemailing.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2018-02-04T04:17:52.000Z","updated_at":"2025-09-08T15:11:24.000Z","dependencies_parsed_at":"2024-01-16T23:26:38.851Z","dependency_job_id":"08804bdb-4fca-4530-b85e-5738aeacd50a","html_url":"https://github.com/smartemailing/types","commit_stats":{"total_commits":327,"total_committers":12,"mean_commits":27.25,"dds":0.4709480122324159,"last_synced_commit":"6aa3ccbd4b8e10e6939eaae2c86f4429e79a997d"},"previous_names":[],"tags_count":26,"template":false,"template_full_name":null,"purl":"pkg:github/smartemailing/types","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smartemailing%2Ftypes","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smartemailing%2Ftypes/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smartemailing%2Ftypes/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smartemailing%2Ftypes/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/smartemailing","download_url":"https://codeload.github.com/smartemailing/types/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smartemailing%2Ftypes/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28418108,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T10:47:48.104Z","status":"ssl_error","status_checked_at":"2026-01-14T10:46:19.031Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["php","strict-types","validation","value-object"],"created_at":"2024-08-01T18:00:55.852Z","updated_at":"2026-01-14T11:17:26.718Z","avatar_url":"https://github.com/smartemailing.png","language":"PHP","readme":"# SmartEmailing \\ Types \n\n### Missing data types for PHP 8.1 and greater. Highly extendable, production tested.\n\n[![MIT license](https://img.shields.io/badge/License-MIT-blue.svg)](https://lbesson.mit-license.org/)\n[![Latest release](https://img.shields.io/github/release/smartemailing/types.svg)](https://github.com/smartemailing/types/releases/)\n[![Downloads](https://poser.pugx.org/smartemailing/types/d/total)](https://packagist.org/packages/smartemailing/types)\n\n[![Build Status](https://github.com/smartemailing/types/workflows/build/badge.svg)](https://github.com/smartemailing/types/actions?query=workflow%3Abuild)\n[![Code coverage](https://coveralls.io/repos/github/smartemailing/types/badge.svg?branch=master)](https://coveralls.io/github/smartemailing/types?branch=master)\n[![CodeClimate](https://api.codeclimate.com/v1/badges/538fcbbeadb10c76fe14/maintainability)](https://codeclimate.com/github/smartemailing/types/maintainability)\n\n\nNeverending data validation can be exhausting. Either you have to validate your data \nover and over again in every function you use it, or you have to rely \nit has already been validated somewhere else and risk potential problems. \n\nSmelly, right?\n\nReplacing validation hell with **Types** will make \nyour code much more readable and less vulnerable to bugs.\n\n**Types** wrap your data in value objects that are guaranteed to be \n**valid and normalized; or not to exist at all**. \nIt allows you to use specific type hints instead of primitive types or arrays.\nYour code will be unbreakable and your IDE will love it.\n\n![](./docs/img/ide-love-2.png)\n\n\n## Table of Contents\n\n  * [Installation](#installation)\n  * [How does it work](#how-does-it-work)\n    + [Wrapping raw value](#wrapping-raw-value)\n    + [Extraction from array](#extraction-from-array)\n  * [String-extractable types](#string-extractable-types)\n    + [E-mail address](#e-mail-address)\n    + [Non-empty string](#non-empty-string)\n    + [Domain](#domain)\n    + [Hex 32](#hex-32)\n    + [Hex Color](#hex-color)\n    + [Hex Color Alpha](#hex-color-alpha)\n    + [GUID](#guid)\n    + [IP address](#ip-address)\n    + [URL](#url)\n    + [Company registration number](#company-registration-number)\n    + [Phone number](#phone-number)\n    + [ZIP code](#zip-code)\n    + [JSON](#json)\n    + [Base 64](#base-64)\n    + [Iban](#iban)\n    + [SwiftBic](#swiftbic)\n    + [VatId](#vatid)\n    + [CurrencyCode](#currencycode)\n    + [CountryCode](#countrycode)\n  * [Int-extractable types](#int-extractable-types)\n    + [Port](#port)\n    + [Quantity](#quantity)\n    + [Unsigned Integer](#unsigned-integer)\n  * [Float-extractable types](#float-extractable-types)\n    + [Part](#part)\n    + [Sigmoid function value](#sigmoid-function-value)\n    + [Rectified Linear Unit function value](#rectified-linear-unit-function-value)\n    + [Unsigned Float](#unsigned-float)\n  * [Array-extractable types](#array-extractable-types)\n    + [DateTimeRange](#datetimerange)\n    + [Duration](#duration)\n    + [Address](#address)\n    + [Price](#price)\n    + [Login credentials](#login-credentials)\n    + [Key-Value pair](#key-value-pair)\n  * [Array-types](#array-types)\n    + [UniqueIntArray](#uniqueintarray)\n    + [UniqueStringArray](#uniquestringarray)\n  * [Enum-extractable types](#enum-extractable-types)\n    + [Lawful Basis For Processing](#lawful-basis-for-processing)\n    + [Country code](#country-code)\n    + [Currency code](#currency-code)\n    + [Field of Application](#field-of-application)\n    + [Time unit](#time-unit)\n    + [Relation](#relation)\n  * [Primitive types](#primitive-types-and-arrays)\n  * [DateTimes](#datetimes)\n  * [Writing your own types](#writing-your-own-types)\n  * [How to contribute](#how-to-contribute)\n\n## Installation\n\nThe recommended way to install is via Composer:\n\n```\ncomposer require smartemailing/types\n```\n\n## How does it work\n\nIt is easy. You just initialize desired value object by simple one-liner. \nFrom this point, you have sanitized, normalized and valid data; or `SmartEmailing\\Types\\InvalidTypeException` to handle.\n\n**Types** consist from:\n\n- String-extractable types - validated strings (E-mail address, Domains, Hexadecimal strings, ...)\n- Int-extractable types - validated integers (Port) \n- Float-extractable types - validated floats (SigmoidValue, Part, ...) \n- Enum-extractable types - enumerables (CountryCode, CurrencyCode, GDPR's Lawful purpose, ...)\n- Composite (Array-extractable) types - structures containing multiple another types (Address, ...)\n- DateTimes - extraction of DateTime and DateTimeImmutable\n- Primitive types extractors and unique arrays\n\nDifferent types provide different methods related to them, but all types share this extraction API:\n\n### Wrapping raw value\n\n```php\n\u003c?php\n\ndeclare(strict_types = 1);\n\nuse SmartEmailing\\Types\\Emailaddress;\nuse SmartEmailing\\Types\\InvalidTypeException;\n\n// Valid input\n\n$emailaddress = Emailaddress::from('hello@gmail.com'); // returns Emailaddress object\n$emailaddress = Emailaddress::from($emailaddress); // returns original $emailaddress\n\n// Invalid input\n\n$emailaddress = Emailaddress::from('bla bla'); // throws InvalidTypeException\n$emailaddress = Emailaddress::from(1); // throws InvalidTypeException\n$emailaddress = Emailaddress::from(false); // throws InvalidTypeException\n$emailaddress = Emailaddress::from(null); // throws InvalidTypeException\n$emailaddress = Emailaddress::from([]); // throws InvalidTypeException\n$emailaddress = Emailaddress::from(new \\StdClass()); // throws InvalidTypeException\n\n// Nullables\n\n$emailaddress = Emailaddress::fromOrNull(null); // returns NULL\n$emailaddress = Emailaddress::fromOrNull('bla bla'); // throws InvalidTypeException\n$emailaddress = Emailaddress::fromOrNull('bla bla', true); // returns null instead of throwing\n\n```\n\n### Extraction from array\n\nThis is really useful for strict-typing (validation) multidimensional arrays like API requests, forms or database data.\n\n```php\n\u003c?php\n\nuse SmartEmailing\\Types\\Emailaddress;\nuse SmartEmailing\\Types\\InvalidTypeException;\n\n$input = [\n\t'emailaddress' =\u003e 'hello@gmail.com',\n\t'already_types_emailaddress' =\u003e Emailaddress::from('hello2@gmail.com'),\n\t'invalid_data' =\u003e 'bla bla',\n];\n\n// Valid input\n\n$emailaddress = Emailaddress::extract($input, 'emailaddress'); // returns Emailaddress object\n$emailaddress = Emailaddress::extract($input, 'already_types_emailaddress'); // returns original Emailaddress object\n\n// Invalid input\n\n$emailaddress = Emailaddress::extract($input, 'invalid_data'); // throws InvalidTypeException\n$emailaddress = Emailaddress::extract($input, 'not_existing_key'); // throws InvalidTypeException\n\n// Nullables \n\n$emailaddress = Emailaddress::extractOrNull($input, 'not_existing_key'); // returns null\n$emailaddress = Emailaddress::extractOrNull($input, 'invalid_data'); //  throws InvalidTypeException\n$emailaddress = Emailaddress::extractOrNull($input, 'invalid_data', true); // returns null instead of throwing\n\n// Default values\n$emailaddress \n\t= Emailaddress::extractOrNull($input, 'not_existing_key') \n\t?? Emailaddress::from('default@domain.com'); \n\t// uses null coalescing operator to assign default value if key not present or null\n\n$emailaddress \n\t= Emailaddress::extractOrNull($input, 'not_existing_key', true) \n\t?? Emailaddress::from('default@domain.com'); \n\t// uses null coalescing operator to assign default value if key not present or null or invalid\n```\n\n## String-extractable types\n\nString-extractable types are based on validated strings. All values are trimmed before validation.\n\nThey can be easily converted back to string by string-type casting or calling `$type-\u003egetValue()`.\n\n### E-mail address\n\n`SmartEmailing\\Types\\Emailaddress`\n\nLowercased and ASCII-transformed e-mail address (`hello@gmail.com`)\n\nType-specific methods:\n- `getLocalPart() : string` returns local part of e-mail address (`hello`)\n- `getDomain() : \\SmartEmailing\\Types\\Domain` returns domain part (`gmail.com`, represented as `Types\\Domain`)\n\n### Non-empty string\n\n`SmartEmailing\\Types\\NonEmptyString`\n\nTrimmed non-empty string.\n\n### Domain\n\n`SmartEmailing\\Types\\Domain`\n\nLowercased domain name (`mx1.googlemx.google.com`)\n\nType-specific methods:\n- `getSecondLevelDomain() : \\SmartEmailing\\Types\\Domain` returns second-level domain. (`google.com`)\n\n\n### Hex 32\n\n`SmartEmailing\\Types\\Hex32`\n\nLowercased 32-characters long hexadecimal string useful as container for MD5 or UUID without dashes. (`741ecf779c9244358e6b85975bd13452`)\n\n### Hex color\n\n`SmartEmailing\\Types\\HexColor`\n\nUppercased 7-characters long string useful as container for color. (`#006EDB`)\n\n### Hex color alpha\n\n`SmartEmailing\\Types\\HexColorAlpha`\n\nUppercased 9-character long string useful as a container for color with an alpha channel (transparency). (`#FFFFFFFF`)\n\nIf you provide a standard 6-digit hex color (e.g., `#000000`), it will be automatically converted by appending FF for 100% opacity (`#000000FF`).\n\n### GUID\n\n`SmartEmailing\\Types\\Guid`\n\nLowercased Guid with dashes (`741ecf77-9c92-4435-8e6b-85975bd13452`)\n\n### IP address\n\n`SmartEmailing\\Types\\IpAddress`\n\nIP address v4 or v6. (`127.0.0.1`, `[2001:0db8:0a0b:12f0:0000:0000:0000:0001]`, `2001:db8:a0b:12f0::1`)\n\nType-specific methods:\n- `getVersion() : int` returns IP address version, `4` or `6`\n\n### URL\n\n`SmartEmailing\\Types\\UrlType`\n\nURL based on `Nette\\Http\\Url` (`https://www.google.com/search?q=all+work+and+no+play+makes+jack+a+dull+boy`)\n\n- all spaces in string are urlencoded\n- all non-ascii characters are urlencoded\n\nType-specific methods:\n- `getAuthority() : string` returns authority (`www.google.com`)\n- `getHost() : string` returns Host (`www.google.com`)\n- `getQueryString() : string` returns Query string (`q=all%20work%20and%20no%20play%20makes%20jack%20a%20dull%20boy`)\n- `getPath() : string` returns URl Path (`/search`)\n- `getAbsoluteUrl() : string` Complete URL as `string`, alias for `getValue()` \n- `getQueryParameter(string $name, mixed $default = null): mixed` Return value of parameter `$name`\n- `getBaseUrl(): string` Return URL without path, query string and hash part (`https://www.google.cz/`)\n- `getScheme(): string` Return URL scheme (`https`)\n- `hasParameters(string[] $names): bool` Returns `true` if URL parameters contain all parameters defined in `$names` array\n- `getParameters(): array` Returns all URL parameters as string-indexed array\n- `withQueryParameter(string $name, mixed $value): UrlType` Returns new instance with added query parameter.\n\n### Company registration number\n\n`SmartEmailing\\Types\\CompanyRegistrationNumber`\n\nWhitespace-free company registration number for following countries: \n`CZ`, `SK`, `CY`\n\n### Phone number\n\n`SmartEmailing\\Types\\PhoneNumber`\n\nWhitespace-free phone number in international format for following countries: \n`CZ`, `SK`, `AT`, `BE`, `FR`, `HU`, `GB`, `DE`, `US`, `PL`, `IT`, `SE`, `SI`, `MH`, `NL`, `CY`, `IE`, `DK`, `FI`, `LU`, `TR`\n\nType-specific methods:\n- `getCountry() : SmartEmailing\\Types\\CountryCode` Originating country (`CZ`)\n\n\n### ZIP code\n\n`SmartEmailing\\Types\\ZipCode`\n\nWhitespace-free ZIP code valid in following countries: \n`CZ`, `SK`, `UK`, `US`\n\n\n### JSON\n\n`SmartEmailing\\Types\\JsonString`\n\nValid JSON-encoded data as string\n\nType-specific methods:\n- `static from(mixed $data) : SmartEmailing\\Types\\JsonString` Accepts string or array. Crates JsonString from valid json string or raw data (array)\n- `static encode(mixed $data) : SmartEmailing\\Types\\JsonString` create JsonString from raw data (array)\n- `getDecodedValue() : mixed` decode JsonString back to raw data\n\n### Base 64\n\n`SmartEmailing\\Types\\Base64String`\n\nValid Base 64-encoded data as string\n\nType-specific methods:\n- `static encode(string $value) : SmartEmailing\\Types\\Base64String` create Base64String from string\n- `getDecodedValue() : string` decode Base64String back to original string\n\n\n### Iban\n\n`SmartEmailing\\Types\\Iban`\n\nType-specific methods:\n- `getFormatted(string $type = SmartEmailing\\Types\\Iban::FORMAT_ELECTRONIC): string` returns formatted Iban string. Format types: `FORMAT_ELECTRONIC`, `FORMAT_PRINT`.\n- `getCountry(): SmartEmailing\\Types\\CountryCode`\n- `getChecksum(): int` \n\n### SwiftBic\n\n`SmartEmailing\\Types\\SwiftBic`\n\nValid Swift/Bic codes.\n\n### VatId\n`SmartEmailing\\Types\\VatId`\n\nType-specific methods:\n- `static isValid(string $vatId): bool` returns true if the vat id is valid otherwise returns false\n- `getCountry(): ?Country` returns `Country` under which the subject should falls or null.\n- `getPrefix(): ?string` returns string that prefixing vat id like `EL` from `EL123456789` or null.\n- `getVatNumber(): string` returns vat number without prefix like `123456789`\n- `getValue(): string` return whole vat id `EL123456789`\n\n### CurrencyCode\n`SmartEmailing\\Types\\CurrencyCode` \n\nValid currency codes by ISO 4217\n\n### CountryCode\n`SmartEmailing\\Types\\CountryCode`\n\nValid country codes by ISO 3166-1 alpha-2\n\n\n## Int-extractable types\n\nInt-extractable types are based on validated integers.\n\nThey can be easily converted back to int by int-type casting or calling `$type-\u003egetValue()`.\n\n### Port\n\n`SmartEmailing\\Types\\Port`\n\nPort number\n\nInteger interval, `\u003c0, 65535\u003e`\n\n### Quantity\n\n`SmartEmailing\\Types\\Quantity`\n\nQuantity of items\n\nInteger interval, `\u003c1, PHP_INT_MAX\u003e`\n\n### Unsigned Integer\n\n`SmartEmailing\\Types\\UnsignedInt`\n\nUsigned integer\n\nInteger interval, `\u003c0, PHP_INT_MAX\u003e`\n\n## Float-extractable types\n\nFloat-extractable types are based on validated floats.\n\nThey can be easily converted back to float by float-type casting or calling `$type-\u003egetValue()`.\n\n### Part\n\n`SmartEmailing\\Types\\Part`\n\nPortion of the whole\n\nFloat interval `\u003c0.0, 1.0\u003e`\n\nType-specific methods:\n- `static fromRatio(float $value, float $whole): Part` creates new instance by division `$value` and `$whole`.\n-  `getPercent(): float` returns `(Ratio's value) * 100` to get percent representation\n\n### Sigmoid function value\n\n`SmartEmailing\\Types\\SigmoidValue`\n\nResult of Sigmoid function, useful when building neural networks.\n\nFloat interval `\u003c-1.0, 1.0\u003e`. \n\n### Rectified Linear Unit function value\n\n`SmartEmailing\\Types\\ReLUValue`\n\nResult of Rectified Linear Unit function, useful when building neural networks.\n\nFloat interval `\u003c0.0, Infinity)`. \n\n### Unsigned Float\n\n`SmartEmailing\\Types\\UnsignedFloat`\n\nUsigned float\n\nFloat interval, `\u003c0, PHP_FLOAT_MAX\u003e`\n\n\n## Array-extractable types\n\nArray-extractable types are composite types encapsulating one or more another types.\nThey are created from associative array. All Array-extractable types implement method \n`toArray() : array` which returns normalized array or type's data.\n\n### DateTimeRange\n\n`SmartEmailing\\Types\\DateTimeRange`\n\nRange between two `\\DateTimeInterface`s. Safe for datetimes out of range of unix timestamp.\n\nCan be created from:\n\n```php\nDateTimeRange::from(\n\t[\n\t\t'from' =\u003e 'YYYY-MM-DD HH:MM:SS',\n\t\t'to' =\u003e 'YYYY-MM-DD HH:MM:SS',\n\t]\n)\n```\nType-specific methods:\n- `getFrom(): \\DateTimeImmutable` returns `From` date and time as `\\DateTimeImmutable` instance\n- `getTo(): \\DateTimeImmutable` returns `To` date and time as `\\DateTimeImmutable` instance\n- `getDurationInSeconds(): int` returns number of seconds between `From` and `To` dates\n- `contains(\\DateTimeInterface $dateTime): bool` returns `true` if provided `\\DateTimeInterface` lies between `From` and `To` dates.\n- `getLengthInSeconds(): int` returns duration length in seconds\n\n### Duration\n\n`SmartEmailing\\Types\\Duration`\n\nHuman-readable time interval.\n\nCan be created from:\n\n```php\nDuration::from(\n\t[\n\t\t'value' =\u003e 1,\n\t\t'unit' =\u003e TimeUnit::HOURS,\n\t]\n);\n\nDuration::from(\n\t'1 hours'\n);\n```\nType-specific methods:\n- `getDateTimeModify(): string` returns string that is compatible with `\\DateTime::modify()` and `\\DateTimeImmutable::modify()`\n- `getUnit(): TimeUnit` returns `TimeUnit` enum type\n- `getValue() int` returns number of units\n- `static fromDateTimeModify(string $dateTimeModify): self` creates new instance from string compatible with `\\DateTime::modify()` and `\\DateTimeImmutable::modify()`\n\n\n### Address\n\n`SmartEmailing\\Types\\Address`\n\nLocation address contains street and number, town, zip code and country.\n\nCan be created from:\n\n```php\nAddress::from(\n\t[\n\t\t'street_and_number' =\u003e '29 Neibolt Street',\n\t\t'town' =\u003e 'Derry',\n\t\t'zip_code' =\u003e '03038',\n\t\t'country' =\u003e 'US',\n\t]\n);\n```\nType-specific methods:\n- `getStreetAndNumber(): string` returns street and number\n- `getTown(): string` returns Town\n- `getZipCode(): ZipCode` returns ZipCode instance\n- `getCountry(): CountryCode` returns CountryCode instance\n\n### Price\n\n`SmartEmailing\\Types\\Price`\n\nPrice object containing number of currency units with VAT, number of currency units without VAT and currency.\n\nCan be created from:\n\n```php\nPrice::from(\n\t[\n\t\t'with_vat' =\u003e 432.1,\n\t\t'without_vat' =\u003e 123.45,\n\t\t'currency' =\u003e CurrencyCode::EUR,\n\t]\n);\n```\nType-specific methods:\n- `getWithoutVat(): float` returns price without VAT\n- `getWithVat(): float` returns price with VAT\n- `getCurrency(): CurrencyCode` returns CurrencyCode instance\n\n### Login credentials\n\n`SmartEmailing\\Types\\LoginCredentials`\n\nValue object containing login and *plain* password. \nYou should use it just in-memory in authentication process and than drop it.\n\nCan be created from:\n\n```php\nLoginCredentials::from(\n\t[\n\t\t'login' =\u003e 'admin',\n\t\t'password' =\u003e 'BLzW75kJxEa7YXuqF9Di',\n\t]\n);\n```\nType-specific methods:\n- `getLogin(): string` returns login\n- `getPassword(): string` returns password\n\n### Key-Value pair\n\n`SmartEmailing\\Types\\KeyValue`\n\nValue object containing string key and string value. \n\nCan be created from:\n\n```php\nKeyValuePair::from(\n\t[\n\t\t'key' =\u003e 'overlook',\n\t\t'value' =\u003e 'all_work_and_no_play_makes_jack_a_dull_boy',\n\t]\n);\n```\nType-specific methods:\n- `getKey(): string` returns key\n- `getValue(): string` returns value\n\n\n### Scalar leaves array\n\n`SmartEmailing\\Types\\ScalarLeavesArray`\n\nValue object containing single or multi-dimensional array with only scalar or NULL values in it's leaves. Array keys stay untouched. \n\nCan be created from:\n\n```php\nScalarLeavesArray::from(\n\t[\n\t\t[\n\t\t\t'a',\n\t\t],\n\t\t[\n\t\t\t1,\n\t\t],\n\t\t[\n\t\t\t'b',\n\t\t\t[\n\t\t\t\ttrue,\n\t\t\t\t[\n\t\t\t\t\tnull,\n\t\t\t\t],\n\t\t\t\t[],\n\t\t\t],\n\t\t],\n\t]\n);\n```\n\nArray-types-specific extractors:\n- `static extractOrEmpty(array $data, string $key): self` Behaves like standard `::extract()` method, but returns empty ScalarLeavesArray when `$data[$key]` is `null` or not set.\n\n\n## Array-types\n\n`Types` provide another kind of Array-extractable types: Unique primitive-type arrays.\nTheir purpose is to hold unique set of primitives. \nThey implement `\\Countable` and `\\IteratorAggregate` and natively support\nset operations.\n\nAll Array-types share following features:\n- `static empty() : self` Creates new empty instance of desired array-type.\n- `split(int $chunkSize): self[]` Splits current instance into array of several instances, each with maximum data-set size of `$chunkSize`.\n- `merge(self $toBeMerged): self` Returns new instance with data-set combined from parent and `$toBeMerged` instances. Both source instances stay unchanged. \n- `deduct(self $toBeDeducted): self` Returns new instance with data-set containing all items from parent that are not contained in `$toBeDeducted`. Both source instances stay unchanged. \n- `count(): int` Returns data-set size.\n- `isEmpty(): bool` Returns `true` if data-set is empty, `false` otherwise.\n\nArray-types-specific extractors:\n- `static extractOrEmpty(array $data, string $key): self` Behaves like standard `::extract()` method, but returns empty set when `$data[$key]` is `null` or not set.\n- `static extractNotEmpty(array $data, string $key): self` Behaves like standard `::extract()` method, but throws `InvalidTypeException` when `$data[$key]` is not set, `null` or empty array.\n\n### UniqueIntArray\n\n`SmartEmailing\\Types\\UniqueIntArray`\n\nUniqueIntArray is able to hold unique set of integers. \n\nCan be created from:\n\n```php\n// duplicate values will be discarted\n// keys are ignored\n\nUniqueIntArray::from(\n\t[\n\t\t1, 2, 2, 3, 3, 3, 4 \n\t]\n);\n```\n\nType-specific methods:\n- `getValues(): int[]` Returns data-set of unique integers as array.\n- `toArray(): int[]` Is just alias for `getValues()`.\n- `add(int $id): bool` Adds another integer to the data-set. Returns `false` if integer has already been there.\n- `remove(int $id): void` Removes integer from the data-set, if present.\n- `contains(int $id): bool` Returns `true` if `$id` is contained in the data-set, `false` otherwise.\n\n### UniqueStringArray\n\n`SmartEmailing\\Types\\UniqueIntArray`\n\nUniqueStringArray is able to hold unique set of strings. \n\nCan be created from:\n\n```php\n// duplicate values will be discarted\n// keys are ignored\n\nUniqueStringArray::from(\n\t[\n\t\t'a', \n\t\t'b', \n\t\t'c', \n\t\t'all work and no play makes jack a dull boy',\n\t\t'all work and no play makes jack a dull boy',\n\t\t'all work and no play makes jack a dull boy',\n\t]\n);\n```\n\nType-specific methods:\n- `getValues(): string[]` Returns data-set of unique strings as array.\n- `toArray(): string[]` Is just alias for `getValues()`.\n- `add(string $id): bool` Adds another string to the data-set. Returns `false` if string has already been there.\n- `remove(string $id): void` Removes string from the data-set, if present.\n- `contains(string $id): bool` Returns `true` if `$id` is contained in the set, `false` otherwise.\n\n\n## Enum-extractable types\n\nEnum-extractable types are types that can contain single value from defined set. They are based on kkk\n\nAll Enum-extractable types share following features:\n- `getValue() : string` Returns enum-value\n- `equals(self $enum): bool` Returns `true` if `$enum` contains same value as parent. \n- `equalsValue(string $value): self` Returns `true` if parent contains the same value as `$value`.\n\nEnums can be created using standard extractors or using their constants:\n\n```php\nCurrencyCode::from(\n\tCurrencyCode::EUR\n);\nCurrencyCode::from(\n\t'EUR'\n);\n```\n\n\n### Lawful Basis For Processing\n\n`SmartEmailing\\Types\\LawfulBasisForProcessing`\n\nGDPR's lawful basis for processing\n\n[Available values](./src/LawfulBasisForProcessing.php)\n\n### Country code\n\n`SmartEmailing\\Types\\CountryCode`\n\nISO-3166-1 Alpha 2 country code\n\n[Available values](./src/CountryCode.php)\n\n### Currency code\n\n`SmartEmailing\\Types\\CurrencyCode`\n\nISO-4217 three-letter currency code\n\n[Available values](./src/CurrencyCode.php)\n\n### Field of Application\n\n`SmartEmailing\\Types\\FieldOfApplication`\n\nMost common fields of human applications.\n\n[Available values](./src/FieldOfApplication.php)\n\n### Time unit\n\n`SmartEmailing\\Types\\TimeUnit`\n\nTime unit compatible with `\\DateTime::modify()` argument format\n\n[Available values](./src/TimeUnit.php)\n\n### Relation\n\n`SmartEmailing\\Types\\Relation`\n\nRepresents Relation or Gate - AND / OR\n\n[Available values](./src/Relation.php)\n\n## Primitive types and Arrays\n\nTypes are able to get and extract primitives using `IntType`, `IntArray`, `FloatType`, `FloatArray`, `StringType`, `StringArray`, `BoolType`, `BoolArray` and `Array` classes. See examples below:\n\n```php\n\u003c?php\n\ndeclare(strict_types = 1);\n\nuse SmartEmailing\\Types\\Arrays;\nuse SmartEmailing\\Types\\BoolArray;\nuse SmartEmailing\\Types\\BoolType;\nuse SmartEmailing\\Types\\FloatArray;\nuse SmartEmailing\\Types\\FloatType;\nuse SmartEmailing\\Types\\IntArray;\nuse SmartEmailing\\Types\\IntType;\nuse SmartEmailing\\Types\\StringArray;\nuse SmartEmailing\\Types\\StringType;\nuse SmartEmailing\\Types\\InvalidTypeException;\n\nIntType::from(666); // 666\nIntType::from('666'); // 666\nIntType::from(666.1); // throws InvalidTypeException\nIntType::from('abcd'); // throws InvalidTypeException\nIntType::from('abcd'); // throws InvalidTypeException\nIntType::fromOrNull(null); // null\nIntType::fromOrNull(1); // 1\nIntType::fromOrNull('abcd'); // throws InvalidTypeException\nIntType::fromOrNull('abcd', true); // null\n\nFloatType::from(1.1); // 1.1\nFloatType::from('1.1'); // 1.1\nFloatType::from(1); // 1.0\nFloatType::from('1'); // 1.0\nFloatType::from('xxx'); // throws InvalidTypeException\nFloatType::fromOrNull(null); // null\nFloatType::fromOrNull(1.0); // 1.0\nFloatType::fromOrNull('abcd'); // throws InvalidTypeException\nFloatType::fromOrNull('abcd', true); // null\n\nStringType::from('xxx'); // 'xxx'\nStringType::from(5); // '5'\nStringType::from(5.0); // '5'\nStringType::from(5.1); // '5.1'\nStringType::fromOrNull(null); // null\nStringType::fromOrNull('abcd'); // 'abcd'\nStringType::fromOrNull([]); // throws InvalidTypeException\nStringType::fromOrNull([], true); // null\n\nBoolType::from(true); // true\nBoolType::from(false); // false\nBoolType::from(1); // true\nBoolType::from(0); // false\nBoolType::from('1'); // true\nBoolType::from('0'); // false\nBoolType::from('true'); // true\nBoolType::from('false'); // false\n\nArrays::from([1, 2]); // [1, 2]\nArrays::from([1, 'abcd']); // [1, 'abcd']\n\nIntArray::from([1, '2']); // [1, 2]\nIntArray::fromOrNull([1, '2']); // returns int[]|null\n\nFloatArray::from([1, '2']); // [1.0, 2.0]\nFloatArray::fromOrNull([1, '2']); // returns float[]|null\n\nStringArray::from([1, '2']); // ['1', '2']\nStringArray::fromOrNull([1, '2']); // returns string[]|null\n\nBoolArray::from([1, '1']); // [true, true]\nBoolArray::fromOrNull([1, '1']); // returns bool[]|null\n\n// All primitive types have their extract equivalent:\n\nIntType::extract($data, 'key');\nIntType::extractOrNull($data, 'key');\nIntType::extractOrNull($data, 'key', true);\n\nStringType::extract($data, 'key');\nStringType::extractOrNull($data, 'key');\nStringType::extractOrNull($data, 'key', true);\n\nFloatType::extract($data, 'key');\nFloatType::extractOrNull($data, 'key');\nFloatType::extractOrNull($data, 'key', true);\n\nArrays::extract($data, 'key'); //returns mixed[]\nArrays::extractOrNull($data, 'key'); //returns mixed[]|null\n\nIntArray::extract($data, 'key'); //returns int[]\nIntArray::extractOrNull($data, 'key'); //returns int[]|null\n\nFloatArray::extract($data, 'key'); //returns float[]\nFloatArray::extractOrNull($data, 'key'); //returns float[]|null\n\nStringArray::extract($data, 'key'); //returns string[]\nStringArray::extractOrNull($data, 'key'); //returns string[]|null\n\nBoolArray::extract($data, 'key'); //returns bool[]\nBoolArray::extractOrNull($data, 'key'); //returns bool[]|null\n\n```\n\n\n## DateTimes and DateTimesImmutable\n\nTypes are able to get and extract `\\DateTime` and `\\DateTimeImmutable` \nobjects using `DateTimes` and `DateTimesImmutable` classes.\nSupported format `Y-m-d H:s:i`. \nAPI is the same as for other types, so available methods are (shown for `DateTimes`):\n\n- `from(string $dateTime ) : \\DateTime`\n- `extract(array $data, string $index) : \\DateTime`\n- `extractOrNull(array $data, string $index, bool $getNullIfInvalid) : ?\\DateTime`\n\n## Dates and DatesImmutable\n\nTypes are able to get and extract `\\DateTime` and `\\DateTimeImmutable` \nobjects using `Dates` and `DatesImmutable` classes. Dates are created with time  sets on `00:00:00`. \nSupported format `Y-m-d`. \nAPI is the same as for other types, so available methods are (shown for `Dates`):\n\n- `from(string $dateTime ) : \\DateTime`\n- `extract(array $data, string $index) : \\DateTime`\n- `extractOrNull(array $data, string $index, bool $getNullIfInvalid) : ?\\DateTime`\n\n## Writing your own types\n\nImplementing your custom type is easy!\nAt first you have to decide what extractable-type should your new custom type be and\n`use` particular extractable-trait in it's class to enhance it by all extractable features. \nThe only thing you have to do next is implement class construtor and throw InvalidTypeException in case of invalid data.\nYou can see examples for every extractable-type below.\n\n- [String-extractable types](./src/Hex32.php)\n- [Int-extractable types](./src/Port.php) \n- [Float-extractable types](./src/Part.php) \n- [Enum-extractable types](./src/CountryCode.php) - You do not have to implement constructor here, just add your `public static` members.\n- [Composite (Array-extractable)](./src/Address.php) - Handy for forms-data or API requests validation\n\nOne more thought - if you think your new type will be useful for others, please, contribute!\n\n## How to contribute\n\nThank you for your interest in improving Types!️ ❤️ 🖖\n\nBefore you open pull request, please, make sure you \ndid not forget to **write tests** for your code. \n\nThen run following commands:\n\n1) `vendor/bin/tester tests`\nRun tests locally. It takes just two seconds :-)\n\n2) `bin/cbf`\nThis will check the code and automatically fix some code style issues \nlike indentation or line breaks.\n\n3) `bin/cs`\nThis will run another code style check that will notify you about \nproblems that must be fixed manually. \nPlease, fix them, and re-run the command.\n\n4) `bin/stan`\nPHP Static analysis tool - this will check the code for some \nsmelly constructions that should be refactored. \nPlease, fix them, and re-run the command.\n\n5) PR ready!\n## We are hiring\n\nDo you like our code? If you want to be part of SmartEmailing, [we are hiring](https://www.smartemailing.cz/kariera/programator).\n","funding_links":[],"categories":["Repositories"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmartemailing%2Ftypes","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsmartemailing%2Ftypes","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmartemailing%2Ftypes/lists"}