Version 1.0.0
This commit is contained in:
22
.editorconfig
Normal file
22
.editorconfig
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
trim_trailing_whitespace = false
|
||||||
|
|
||||||
|
[*.php]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
[*.yml]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.json]
|
||||||
|
indent_size = 2
|
||||||
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
vendor/
|
||||||
|
|
||||||
|
.phpunit.cache/
|
||||||
19
LICENSE
Normal file
19
LICENSE
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
Copyright 2025 Viktor S. <thinlineseverywhere@gmail.com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the “Software”),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included
|
||||||
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||||
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
||||||
156
README.md
Normal file
156
README.md
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
# PHP DTO Library
|
||||||
|
|
||||||
|
Simple and lightweight PHP library for representing Data Transfer Objects (DTOs) with property value tracking.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Easy to use abstract `Dto` class for creating data transfer objects
|
||||||
|
- Property value tracking with `Property` wrapper class
|
||||||
|
- Support for creating DTOs from arrays with automatic property name conversion
|
||||||
|
- Track whether properties are initialized or not
|
||||||
|
- Automatic conversion between kebab-case and camelCase
|
||||||
|
- Type-safe with PHP 7.4+ and PHP 8.0+
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Install the library via Composer:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
composer require diffhead/php-dto
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
Run the test suite:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
composer test
|
||||||
|
```
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- PHP 7.4 or higher
|
||||||
|
- `diffhead/php-interfaces` ^1.0
|
||||||
|
- `jawira/case-converter` ^3.6
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
Create a DTO class by extending the `Dto` abstract class:
|
||||||
|
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Diffhead\PHP\Dto\Dto;
|
||||||
|
use Diffhead\PHP\Dto\Property;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Properties inside the Dto class
|
||||||
|
* should be camelCase named and
|
||||||
|
* protected
|
||||||
|
*/
|
||||||
|
class UserCreate extends Dto
|
||||||
|
{
|
||||||
|
protected Property $firstName;
|
||||||
|
protected Property $lastName;
|
||||||
|
protected Property $email;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Creating a DTO from Array
|
||||||
|
|
||||||
|
```php
|
||||||
|
/**
|
||||||
|
* But inside the source array you can use
|
||||||
|
* camelCase, pascal_case, kebab-case, etc
|
||||||
|
*/
|
||||||
|
$data = [
|
||||||
|
'first_name' => 'John',
|
||||||
|
'lastName' => 'Doe',
|
||||||
|
'email' => 'john@example.com'
|
||||||
|
];
|
||||||
|
|
||||||
|
$user = UserCreate::fromArray($data);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Accessing Properties
|
||||||
|
|
||||||
|
Access properties using magic methods.
|
||||||
|
Each property returns a `Property` object that
|
||||||
|
tracks both the value and whether it exists:
|
||||||
|
|
||||||
|
```php
|
||||||
|
/**
|
||||||
|
* Get the property object
|
||||||
|
*/
|
||||||
|
$firstName = $user->firstName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check property exists and set
|
||||||
|
*/
|
||||||
|
if ($firstName->exists()) {
|
||||||
|
echo $firstName->value(); // Output: John
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Working with Property Objects
|
||||||
|
|
||||||
|
The `Property` class wraps values and tracks their existence:
|
||||||
|
|
||||||
|
```php
|
||||||
|
$property = new \Diffhead\PHP\Dto\Property('1', true);
|
||||||
|
|
||||||
|
$property->value(); // Returns: '1'
|
||||||
|
$property->exists(); // Returns: true
|
||||||
|
$property->toInt(); // Returns: 1
|
||||||
|
$property->toFloat(); // Returns: 1.0
|
||||||
|
$proprety->toBool(); // Returns: true
|
||||||
|
$property->toArray(); // Returns: ['1']
|
||||||
|
$property->toString(); // Returns: '1'
|
||||||
|
|
||||||
|
$property = new \Diffhead\PHP\Dto\Property(null, false);
|
||||||
|
|
||||||
|
$property->value(); // Returns: null
|
||||||
|
$property->exists(); // Returns: false
|
||||||
|
```
|
||||||
|
|
||||||
|
### Retrieving Values
|
||||||
|
|
||||||
|
Get multiple property values at once:
|
||||||
|
|
||||||
|
```php
|
||||||
|
/**
|
||||||
|
* Get all properties values
|
||||||
|
*
|
||||||
|
* output: ['first_name' => 'John', 'lastName' => 'Doe', 'email' => 'john@example.com', 'age' => null]
|
||||||
|
*/
|
||||||
|
$values = $user->getValues(['first_name', 'lastName', 'email', 'age']);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get only existing properties values
|
||||||
|
*
|
||||||
|
* output: ['first-name' => 'John', 'last.name' => 'Doe', 'email' => 'john@example.com']
|
||||||
|
*/
|
||||||
|
$values = $user->getValues(['first-name', 'last.name', 'email', 'age'], true);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Property Name Conversion
|
||||||
|
|
||||||
|
The library automatically handles
|
||||||
|
class property name conversion:
|
||||||
|
|
||||||
|
- **dot.case** (e.g., `first.name`) → **camelCase** (e.g., `firstName`)
|
||||||
|
- **kebab-case** (e.g., `first-name`) → **camelCase** (e.g., `firstName`)
|
||||||
|
- **snake_case** (e.g., `first_name`) → **camelCase** (e.g., `firstName`)
|
||||||
|
|
||||||
|
This makes it easy to work with API responses and
|
||||||
|
form data that might use different naming conventions.
|
||||||
|
|
||||||
|
But `Diffhead\PHP\Dto\Dto::getValues` method
|
||||||
|
returns raw array keys as they was been passed.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
|
||||||
|
|
||||||
35
composer.json
Normal file
35
composer.json
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"name": "diffhead/php-dto",
|
||||||
|
"description": "",
|
||||||
|
"type": "library",
|
||||||
|
"license": "MIT",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"keywords": [
|
||||||
|
"php", "data interaction", "data transfer object",
|
||||||
|
"dto", "library", "package", "php8"
|
||||||
|
],
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Diffhead\\PHP\\Dto\\": "src/",
|
||||||
|
"Diffhead\\PHP\\Dto\\Tests\\": "tests/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": "^7.4 || ^8.0",
|
||||||
|
"diffhead/php-interfaces": "^1.0",
|
||||||
|
"jawira/case-converter": "^3.6"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^9.0"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"test": "phpunit"
|
||||||
|
},
|
||||||
|
"minimum-stability": "stable",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Viktor S.",
|
||||||
|
"email": "thinlineseverywhere@gmail.com"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
1935
composer.lock
generated
Normal file
1935
composer.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
17
phpunit.xml
Normal file
17
phpunit.xml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
|
||||||
|
bootstrap="vendor/autoload.php"
|
||||||
|
executionOrder="depends,defects"
|
||||||
|
beStrictAboutOutputDuringTests="true"
|
||||||
|
failOnRisky="true"
|
||||||
|
failOnWarning="true"
|
||||||
|
testdox="true"
|
||||||
|
colors="true"
|
||||||
|
cacheResult="false">
|
||||||
|
<testsuites>
|
||||||
|
<testsuite name="Unit">
|
||||||
|
<directory>tests</directory>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
|
</phpunit>
|
||||||
101
src/Dto.php
Normal file
101
src/Dto.php
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Diffhead\PHP\Dto;
|
||||||
|
|
||||||
|
use Diffhead\PHP\Interfaces\Object\ArrayInstantiable;
|
||||||
|
use Jawira\CaseConverter\Convert;
|
||||||
|
use TypeError;
|
||||||
|
|
||||||
|
abstract class Dto implements ArrayInstantiable
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array<int,string>
|
||||||
|
*/
|
||||||
|
private array $initializedProperties = [];
|
||||||
|
|
||||||
|
public static function fromArray(array $data): static
|
||||||
|
{
|
||||||
|
$dto = new static();
|
||||||
|
|
||||||
|
foreach ($data as $prop => $value) {
|
||||||
|
if (str_contains($prop, '-')) {
|
||||||
|
$prop = str_replace('-', '_', $prop);
|
||||||
|
}
|
||||||
|
|
||||||
|
$propConverter = new Convert($prop);
|
||||||
|
$prop = $propConverter->toCamel();
|
||||||
|
|
||||||
|
if (property_exists($dto, $prop)) {
|
||||||
|
$dto->setProperty($prop, $value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $dto;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __get(string $name): Property
|
||||||
|
{
|
||||||
|
return $this->getProperty($name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<int,string> $properties
|
||||||
|
* @param bool $existingOnly
|
||||||
|
*
|
||||||
|
* @return array<string,mixed>
|
||||||
|
*/
|
||||||
|
public function getValues(array $properties, bool $existingOnly = false): array
|
||||||
|
{
|
||||||
|
$values = [];
|
||||||
|
|
||||||
|
foreach ($properties as $property) {
|
||||||
|
if (! is_string($property)) {
|
||||||
|
throw new TypeError(
|
||||||
|
sprintf('Expected string as prop name. Passed "%s"', $property)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$propertyNotExisting = ! $this->getProperty($property)->exists();
|
||||||
|
|
||||||
|
if ($existingOnly && $propertyNotExisting) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$values[$property] = $this->getProperty($property)->value();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $values;
|
||||||
|
}
|
||||||
|
|
||||||
|
final protected function setProperty(string $propName, mixed $value): void
|
||||||
|
{
|
||||||
|
$this->$propName = new Property($value);
|
||||||
|
$this->setPropertyInitialized($propName);
|
||||||
|
}
|
||||||
|
|
||||||
|
final protected function getProperty(string $name): Property
|
||||||
|
{
|
||||||
|
$nameConvert = new Convert($name);
|
||||||
|
|
||||||
|
$propExists = property_exists($this, $name)
|
||||||
|
|| property_exists($this, $name = $nameConvert->toCamel());
|
||||||
|
|
||||||
|
if ($propExists && $this->isPropertyInitialized($name)) {
|
||||||
|
return $this->$name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Property(null, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function setPropertyInitialized(string $propName): void
|
||||||
|
{
|
||||||
|
$this->initializedProperties[] = $propName;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function isPropertyInitialized(string $propName): bool
|
||||||
|
{
|
||||||
|
return in_array($propName, $this->initializedProperties);
|
||||||
|
}
|
||||||
|
}
|
||||||
69
src/Property.php
Normal file
69
src/Property.php
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Diffhead\PHP\Dto;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @template ValueType
|
||||||
|
*/
|
||||||
|
class Property
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var ValueType
|
||||||
|
*/
|
||||||
|
private $value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private bool $exists;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ValueType $value
|
||||||
|
* @param bool $exists
|
||||||
|
*/
|
||||||
|
public function __construct($value, bool $exists = true)
|
||||||
|
{
|
||||||
|
$this->value = $value;
|
||||||
|
$this->exists = $exists;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return ValueType
|
||||||
|
*/
|
||||||
|
public function value()
|
||||||
|
{
|
||||||
|
return $this->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toBool(): bool
|
||||||
|
{
|
||||||
|
return (bool) $this->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toInt(): int
|
||||||
|
{
|
||||||
|
return (int) $this->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toFloat(): float
|
||||||
|
{
|
||||||
|
return (float) $this->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toString(): string
|
||||||
|
{
|
||||||
|
return (string) $this->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toArray(): array
|
||||||
|
{
|
||||||
|
return (array) $this->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function exists(): bool
|
||||||
|
{
|
||||||
|
return $this->exists;
|
||||||
|
}
|
||||||
|
}
|
||||||
176
tests/DtoTest.php
Normal file
176
tests/DtoTest.php
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Diffhead\PHP\Dto\Tests;
|
||||||
|
|
||||||
|
use Diffhead\PHP\Dto\Dto;
|
||||||
|
use Diffhead\PHP\Dto\Property;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class DtoTest extends TestCase
|
||||||
|
{
|
||||||
|
public function testProperlyInitializes(): void
|
||||||
|
{
|
||||||
|
$dto = DtoExample::fromArray([
|
||||||
|
'name' => 'John Doe',
|
||||||
|
'age' => 30,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->assertSame('John Doe', $dto->name->value());
|
||||||
|
$this->assertTrue($dto->name->exists());
|
||||||
|
$this->assertSame(30, $dto->age->value());
|
||||||
|
$this->assertTrue($dto->age->exists());
|
||||||
|
$this->assertNull($dto->homeAddress->value());
|
||||||
|
$this->assertFalse($dto->homeAddress->exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInitializationFromKebabCase(): void
|
||||||
|
{
|
||||||
|
$dto = DtoExample::fromArray([
|
||||||
|
'name' => 'Jane Doe',
|
||||||
|
'age' => 25,
|
||||||
|
'home-address' => '39 Vicar Lane, Sandilands, United Kingdom',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->assertSame('Jane Doe', $dto->name->value());
|
||||||
|
$this->assertTrue($dto->name->exists());
|
||||||
|
$this->assertSame(25, $dto->age->value());
|
||||||
|
$this->assertTrue($dto->age->exists());
|
||||||
|
$this->assertSame('39 Vicar Lane, Sandilands, United Kingdom', $dto->homeAddress->value());
|
||||||
|
$this->assertTrue($dto->homeAddress->exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInitializationFromPascalCase(): void
|
||||||
|
{
|
||||||
|
$dto = DtoExample::fromArray([
|
||||||
|
'name' => 'Alice',
|
||||||
|
'age' => 28,
|
||||||
|
'home_address' => '123 Main St, Anytown, USA',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->assertSame('Alice', $dto->name->value());
|
||||||
|
$this->assertTrue($dto->name->exists());
|
||||||
|
$this->assertSame(28, $dto->age->value());
|
||||||
|
$this->assertTrue($dto->age->exists());
|
||||||
|
$this->assertSame('123 Main St, Anytown, USA', $dto->homeAddress->value());
|
||||||
|
$this->assertTrue($dto->homeAddress->exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInitializationFromCamelCase(): void
|
||||||
|
{
|
||||||
|
$dto = DtoExample::fromArray([
|
||||||
|
'name' => 'Bob',
|
||||||
|
'age' => 35,
|
||||||
|
'homeAddress' => '456 Elm St, Othertown, USA',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->assertSame('Bob', $dto->name->value());
|
||||||
|
$this->assertTrue($dto->name->exists());
|
||||||
|
$this->assertSame(35, $dto->age->value());
|
||||||
|
$this->assertTrue($dto->age->exists());
|
||||||
|
$this->assertSame('456 Elm St, Othertown, USA', $dto->homeAddress->value());
|
||||||
|
$this->assertTrue($dto->homeAddress->exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetStrictExistingPropertiesValues(): void
|
||||||
|
{
|
||||||
|
$dto = DtoExample::fromArray([
|
||||||
|
'name' => 'Charlie',
|
||||||
|
'age' => 40,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$values = $dto->getValues(['name', 'age', 'home_address'], true);
|
||||||
|
|
||||||
|
$this->assertArrayHasKey('name', $values);
|
||||||
|
$this->assertSame('Charlie', $values['name']);
|
||||||
|
$this->assertArrayHasKey('age', $values);
|
||||||
|
$this->assertSame(40, $values['age']);
|
||||||
|
$this->assertArrayNotHasKey('home_address', $values);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetNonStrictExistingPropertiesValues(): void
|
||||||
|
{
|
||||||
|
$dto = DtoExample::fromArray([
|
||||||
|
'name' => 'Diana',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$values = $dto->getValues(['name', 'age', 'home_address'], false);
|
||||||
|
|
||||||
|
$this->assertArrayHasKey('name', $values);
|
||||||
|
$this->assertSame('Diana', $values['name']);
|
||||||
|
$this->assertArrayHasKey('age', $values);
|
||||||
|
$this->assertNull($values['age']);
|
||||||
|
$this->assertArrayHasKey('home_address', $values);
|
||||||
|
$this->assertNull($values['home_address']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetStrictNonExistingPropertiesValues(): void
|
||||||
|
{
|
||||||
|
$dto = DtoExample::fromArray([]);
|
||||||
|
|
||||||
|
$values = $dto->getValues(['name', 'age'], true);
|
||||||
|
|
||||||
|
$this->assertEmpty($values);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetNonStrictNonExistingPropertiesValues(): void
|
||||||
|
{
|
||||||
|
$dto = DtoExample::fromArray([]);
|
||||||
|
|
||||||
|
$values = $dto->getValues(['name', 'age'], false);
|
||||||
|
|
||||||
|
$this->assertArrayHasKey('name', $values);
|
||||||
|
$this->assertNull($values['name']);
|
||||||
|
$this->assertArrayHasKey('age', $values);
|
||||||
|
$this->assertNull($values['age']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetKebabCasePropertiesValues(): void
|
||||||
|
{
|
||||||
|
$dto = DtoExample::fromArray([
|
||||||
|
'name' => 'Eve',
|
||||||
|
'age' => 29,
|
||||||
|
'home-address' => '789 Oak St, Sometown, USA',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$values = $dto->getValues(['name', 'age', 'home-address'], false);
|
||||||
|
|
||||||
|
$this->assertArrayHasKey('name', $values);
|
||||||
|
$this->assertSame('Eve', $values['name']);
|
||||||
|
$this->assertArrayHasKey('age', $values);
|
||||||
|
$this->assertSame(29, $values['age']);
|
||||||
|
$this->assertArrayHasKey('home-address', $values);
|
||||||
|
$this->assertSame('789 Oak St, Sometown, USA', $values['home-address']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetCamelCasePropertiesValues(): void
|
||||||
|
{
|
||||||
|
$dto = DtoExample::fromArray([
|
||||||
|
'name' => 'Frank',
|
||||||
|
'age' => 33,
|
||||||
|
'homeAddress' => '101 Pine St, Newcity, USA',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$values = $dto->getValues(['name', 'age', 'homeAddress'], false);
|
||||||
|
|
||||||
|
$this->assertArrayHasKey('name', $values);
|
||||||
|
$this->assertSame('Frank', $values['name']);
|
||||||
|
$this->assertArrayHasKey('age', $values);
|
||||||
|
$this->assertSame(33, $values['age']);
|
||||||
|
$this->assertArrayHasKey('homeAddress', $values);
|
||||||
|
$this->assertSame('101 Pine St, Newcity, USA', $values['homeAddress']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property \Diffhead\PHP\Dto\Property<string> $name
|
||||||
|
* @property \Diffhead\PHP\Dto\Property<int> $age
|
||||||
|
* @property \Diffhead\PHP\Dto\Property<string> $homeAddress
|
||||||
|
*/
|
||||||
|
class DtoExample extends Dto
|
||||||
|
{
|
||||||
|
protected Property $name;
|
||||||
|
protected Property $age;
|
||||||
|
protected Property $homeAddress;
|
||||||
|
}
|
||||||
35
tests/PropertyTest.php
Normal file
35
tests/PropertyTest.php
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Diffhead\PHP\Dto\Tests;
|
||||||
|
|
||||||
|
use Diffhead\PHP\Dto\Property;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class PropertyTest extends TestCase
|
||||||
|
{
|
||||||
|
public function testProperlyInitializes(): void
|
||||||
|
{
|
||||||
|
$property = new Property(131, true);
|
||||||
|
|
||||||
|
$this->assertSame(131, $property->value());
|
||||||
|
$this->assertTrue($property->exists());
|
||||||
|
|
||||||
|
$property = new Property(null, false);
|
||||||
|
|
||||||
|
$this->assertNull($property->value());
|
||||||
|
$this->assertFalse($property->exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testValueCasting(): void
|
||||||
|
{
|
||||||
|
$property = new Property('1', true);
|
||||||
|
|
||||||
|
$this->assertSame('1', $property->toString());
|
||||||
|
$this->assertSame(1, $property->toInt());
|
||||||
|
$this->assertSame(1.0, $property->toFloat());
|
||||||
|
$this->assertTrue($property->toBool());
|
||||||
|
$this->assertSame(['1'], $property->toArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user