diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..e5aa5ef --- /dev/null +++ b/.travis.yml @@ -0,0 +1,10 @@ +language: php + +php: + - 5.6 + - nightly + - hhvm + +before_script: + - composer self-update + - composer install --prefer-source --no-interaction --dev diff --git a/README.md b/README.md new file mode 100644 index 0000000..0ccf340 --- /dev/null +++ b/README.md @@ -0,0 +1,99 @@ +## Laravel Value Objects +[![Build Status](https://travis-ci.org/redcrystalcode/laravel-value-objects.svg?branch=master)](https://travis-ci.org/redcrystal/cast) +[![Latest Stable Version](https://poser.pugx.org/redcrystal/cast/version.png)](https://packagist.org/packages/redcrystal/cast) +[![Total Downloads](https://poser.pugx.org/redcrystal/cast/d/total.png)](https://packagist.org/packages/redcrystal/cast) + + +Cast your Eloquent model attributes to value objects with ease! + +### Requirements + +This package requires PHP >= 5.4. Using the latest version of PHP is highly recommended. Laravel 4.x and 5.x are supported. + +> **Note:** Running tests for this package requires PHP >=5.6. + +### Install + +Require this package with composer using the following command: + +```bash +composer require redcrystal/cast +``` + +### Set Up + +This package lets you easily cast your model attributes to Value Objects that implement our `RedCrystal\Cast\ValueObject` interface. A simple example is provided below. + +```php +value = $value; + } + + public function toScalar() + { + return $this->value; + } + + public function __toString() { + return $this->toScalar(); + } +} +``` + +Set up your model by using the included `Trait` and adding a tiny bit of configuration. + +```php + name of the value object class + 'email' => Email::class + ]; + + // ... +} +``` + +### Usage + +When accessing attributes of your model normally, any attribute you've set up for casting will be returned as an instance of the Value Object. + +```php +$user = User::find($id); + +$user->email; // returns instance of App\ValueObjects\Email +$user->email->toScalar(); // "someone@example.com" +(string) $user->email; // "someone@example.com" +``` + +You can set an attribute set up for casting with either a scalar (native) value, or an instance of the Value Object. + +```php +$user = new User(); + +$user->email = "someone@example.com"; +$user->email = new Email("someone@example.com"); +``` + +### License +This package is open-source software licensed under the [MIT license](http://opensource.org/licenses/MIT). diff --git a/composer.json b/composer.json index 743604b..0657090 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "redcrystal/cast", - "description": "Cast your model attributes to value objects!", + "description": "Laravel Value Objects: Cast your Eloquent model attributes to value objects with ease!", "license": "MIT", "authors": [ { diff --git a/src/CastsValueObjects.php b/src/CastsValueObjects.php index 44547cc..56a2252 100644 --- a/src/CastsValueObjects.php +++ b/src/CastsValueObjects.php @@ -12,7 +12,7 @@ trait CastsValueObjects protected $cachedObjects = []; /** - * @param $key + * @param string $key * * @return mixed */ @@ -23,6 +23,11 @@ public function getAttribute($key) // Allow other mutators and such to do their work first. $value = parent::getAttribute($key); + // Don't cast empty $value. + if ($value === null || $value === '') { + return null; + } + // Cache the instantiated value for future access. // This allows tests such as ($model->casted === $model->casted) to be true. if (!$this->isValueObjectCached($key)) { @@ -39,8 +44,8 @@ public function getAttribute($key) } /** - * @param $key - * @param $value + * @param string $key + * @param mixed $value */ public function setAttribute($key, $value) { @@ -73,7 +78,7 @@ public function setAttribute($key, $value) } /** - * @param $key + * @param string $key * * @return mixed */ @@ -85,7 +90,7 @@ private function createValueObject($key, $value) } /** - * @param $key + * @param string $key * @param ValueObject $object */ private function cacheValueObject($key, ValueObject $object) @@ -94,7 +99,7 @@ private function cacheValueObject($key, ValueObject $object) } /** - * @param $key + * @param string $key */ private function invalidateValueObjectCache($key) { @@ -102,7 +107,7 @@ private function invalidateValueObjectCache($key) } /** - * @param $key + * @param string $key * * @return bool */ @@ -112,7 +117,7 @@ private function isValueObjectCached($key) } /** - * @param $key + * @param string $key * * @return ValueObject */ diff --git a/tests/CastsValueObjectTest.php b/tests/CastsValueObjectTest.php index eba2ff6..2c519f9 100644 --- a/tests/CastsValueObjectTest.php +++ b/tests/CastsValueObjectTest.php @@ -98,4 +98,45 @@ public function testValueObjectCacheIsInvalidatedWhenSettingScalar() $this->assertInstanceOf(EmailValueObject::class, $user->email); $this->assertEquals($email, $user->email->toScalar()); } + + public function testModelToArrayWithValueObjects() + { + $user = new UserModel(); + + $user->email = $email = 'user@example.com'; + + $array = $user->toArray(); + + $this->assertArrayHasKey('email', $array); + $this->assertTrue(is_string($array['email'])); + $this->assertFalse($array['email'] instanceof EmailValueObject); + } + + public function testModelToJsonWithValueObjects() + { + $user = new UserModel(); + + $user->email = $email = 'user@example.com'; + + $json = $user->toJson(); + + $this->assertJson($json); + $this->assertJsonStringEqualsJsonString(json_encode(['email' => $email]), $json); + } + + public function testNullValuesDontGetCast() + { + $user = new UserModel(); + + $this->assertNull($user->email); + } + + public function testEmptyStringValuesDontGetCast() + { + $user = new UserModel(); + + $user->setInternalAttributes(['email' => '']); + + $this->assertNull($user->email); + } }