├── tests
└── .gitkeep
├── .gitignore
├── .semver
├── src
├── EloquentTypecastException.php
└── EloquentTypecastTrait.php
├── TODO.md
├── .travis.yml
├── CHANGELOG.md
├── phpunit.xml
├── composer.json
├── LICENSE.md
└── README.md
/tests/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /vendor/
2 | composer.lock
3 |
--------------------------------------------------------------------------------
/.semver:
--------------------------------------------------------------------------------
1 | ---
2 | :major: 1
3 | :minor: 0
4 | :patch: 2
5 | :special: ''
6 |
--------------------------------------------------------------------------------
/src/EloquentTypecastException.php:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 | ./tests/
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cviebrock/eloquent-typecast",
3 | "description": "Trait for Eloquent models to force type-casting on retrieved values",
4 | "keywords": ["laravel", "eloquent", "typecast", "json", "boolean", "integer", "float", "settype", "mutator"],
5 | "homepage": "https://github.com/cviebrock/eloquent-typecast",
6 | "license": "MIT",
7 | "authors": [
8 | {
9 | "name": "Colin Viebrock",
10 | "email": "colin@viebrock.ca"
11 | }
12 | ],
13 | "require": {
14 | "php": ">=5.4.0",
15 | "illuminate/database": "4.*",
16 | "illuminate/support": "4.*"
17 | },
18 | "require-dev": {
19 | "phpunit/phpunit": "4.0.*",
20 | "orchestra/testbench": "2.*",
21 | "laravelbook/ardent": "dev-master"
22 | },
23 | "autoload": {
24 | "psr-4": {
25 | "Cviebrock\\EloquentTypecast\\": "src/"
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | # The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Colin Viebrock
4 |
5 | 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:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | 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.
10 |
--------------------------------------------------------------------------------
/src/EloquentTypecastTrait.php:
--------------------------------------------------------------------------------
1 | getCastAttributes() as $attribute=>$type)
30 | {
31 | static::$mutatorCache[$class][] = $attribute;
32 | }
33 | }
34 |
35 |
36 | /**
37 | * Get the value of an attribute using its mutator. If the attribute
38 | * is typecast-able, then return the cast value instead.
39 | *
40 | * @param string $key
41 | * @param mixed $value
42 | * @return mixed
43 | * @see Illuminate\Database\Eloquent\Model::mutateAttribute()
44 | */
45 | protected function mutateAttribute($key, $value)
46 | {
47 | if ($this->isCastableAttribute($key))
48 | {
49 | return $this->castAttribute($key, $value);
50 | }
51 |
52 | return parent::mutateAttribute($key, $value);
53 | }
54 |
55 |
56 | /**
57 | * Set a given attribute on the model. If the attribute is typecast-able,
58 | * then cast the value before setting it.
59 | *
60 | * @param string $key
61 | * @param mixed $value
62 | * @return void
63 | * @see Illuminate\Database\Eloquent\Model::setAttribute()
64 | */
65 | public function setAttribute($key, $value)
66 | {
67 | if ($this->castOnSet() && $this->isCastableAttribute($key))
68 | {
69 | $value = $this->castAttribute($key, $value);
70 | }
71 | return parent::setAttribute($key, $value);
72 | }
73 |
74 | /**
75 | * Get a given attribute on the model. If the attribute is typecast-able,
76 | * then cast the value before getting it.
77 | *
78 | * @param string $key
79 | * @return mixed
80 | */
81 | protected function getAttributeValue($key)
82 | {
83 | $value = parent::getAttributeValue($key);
84 |
85 | if ($this->isCastableAttribute($key))
86 | {
87 | $value = $this->castAttribute($key, $value);
88 | }
89 |
90 | return $value;
91 | }
92 |
93 | /**
94 | * Return the array of attributes to cast.
95 | *
96 | * @return array
97 | */
98 | protected function getCastAttributes()
99 | {
100 | return isset($this->cast) ? $this->cast : array();
101 | }
102 |
103 |
104 | /**
105 | * Return the array of attributes to cast.
106 | *
107 | * @return array
108 | */
109 | protected function castOnSet()
110 | {
111 | return isset($this->castOnSet) ? $this->castOnSet : false;
112 | }
113 |
114 |
115 | /**
116 | * Is the given attribute typecast-able.
117 | *
118 | * @return bool
119 | */
120 | protected function isCastableAttribute($key)
121 | {
122 | return array_key_exists($key, $this->getCastAttributes());
123 | }
124 |
125 |
126 | /**
127 | * Cast an attribute to a PHP variable type.
128 | *
129 | * @param string $key
130 | * @param mixed $value
131 | * @throws EloquentTypecastException
132 | * @return mixed
133 | */
134 | protected function castAttribute($key, $value)
135 | {
136 | $type = $this->cast[$key];
137 |
138 | try {
139 | if ( is_null($value) ) {
140 | return null;
141 | }
142 |
143 | if ( settype($value, $type) ) {
144 | return $value;
145 | }
146 | throw new EloquentTypecastException("Value could not be cast to type \"$type\"", 1);
147 | } catch (\Exception $e) {
148 | throw new EloquentTypecastException("Value could not be cast to type \"$type\"", 1);
149 | }
150 | }
151 |
152 | }
153 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # EloquentTypecast
2 |
3 | A trait that allows a Laravel project's Eloquent models to cast attribute values to native PHP variable types.
4 |
5 |
6 | [](https://packagist.org/packages/cviebrock/eloquent-typecast)
7 | [](https://packagist.org/packages/cviebrock/eloquent-typecast)
8 |
9 | * [Background](#background)
10 | * [Installation and Requirements](#installation)
11 | * [Usage](#usage)
12 | * [Notes](#notes)
13 | * [Bugs, Suggestions and Contributions](#bugs)
14 | * [Copyright and License](#copyright)
15 |
16 |
17 | - - -
18 |
19 |
20 |
21 | ## Background: Why Do I Need This?
22 |
23 | For some database drivers, all the attributes you get back from a query are returned as strings, even when the underlaying column-type is _INTEGER_ or _FLOAT_ or _BOOLEAN_.
24 |
25 | Rather than have to use these "integer-looking" strings, etc., and rely on PHP's type-juggling, this trait will cast those attribute values to the proper native PHP variable type automagically for you.
26 |
27 | This is also going to be very handy if you are, say, building an API and would like to just return JSON-versions of Eloquent models. Using this trait, all the JSON elements are going to be the right type for consumers of your API -- instead of all strings -- saving them type-juggling on their end.
28 |
29 | > Note: I believe if you are using the mysqlnd drivers in your PHP installation, then you don't need this trait as mysqlnd handles this type casting for you. Try it out by doing a `var_dump($model->getKey())`. If it shows that the value is an integer, you don't need this package. If it shows it's a string, read on.
30 |
31 |
32 |
33 |
34 | ## Installation & Requirements
35 |
36 | In your project's composer.json file:
37 |
38 | ```json
39 | "require": {
40 | "cviebrock/eloquent-typecast": "1.*"
41 | }
42 | ```
43 |
44 | In your project's models (or your own base model):
45 |
46 | ```php
47 | use Cviebrock\EloquentTypecast\EloquentTypecastTrait;
48 |
49 | class MyModel {
50 |
51 | use EloquentTypecastTrait;
52 |
53 | // Define the attributes you want typecast here
54 | protected $cast = array(
55 | 'id' => 'integer',
56 | 'price' => 'float',
57 | 'is_awesome' => 'boolean'
58 | );
59 |
60 | ...
61 |
62 | }
63 | ```
64 |
65 | That's it. No service providers or facades required. Because it's a trait, however, you will need to be running PHP 5.4 or later.
66 |
67 |
68 |
69 |
70 | ## Usage
71 |
72 | Anytime you request an attribute listed in the `$cast` array, it will be converted from the (usually) string that your database returned into a the native PHP variable type you specified.
73 |
74 | The keys of the `$cast` array are the attribute (i.e. column) names, and the values are the types you want to cast to. Anything supported by PHP's [settype()](http://php.net/manual/en/function.settype.php) function is valid ... although casting to arrays, objects, or null could be problematic.
75 |
76 | If you set the `$castOnSet` property on your model to `true`, then setting an attribute that's in the `$cast` array will typecast that value before setting it. For example:
77 |
78 | ```php
79 | class MyModel {
80 |
81 | use EloquentTypecastTrait;
82 |
83 | protected $castOnSet = true;
84 |
85 | protected $cast = array(
86 | 'price' => 'float',
87 | );
88 |
89 | }
90 |
91 | $myModel = MyModel::find(1);
92 |
93 | $price = Input::get('price'); // this will be a string
94 | $myModel->price = $price; // the string is cast to a float before setting;
95 | ```
96 |
97 | In general, this setting isn't really necessary as Laravel and most databases will handle the string-to-column-type conversion for you on save. However, maybe there are cases where it's useful, so it's added for "feature completion".
98 |
99 |
100 |
101 |
102 | ## Notes
103 |
104 | Because of the way the trait works, you should make sure that your `$cast` array does not include:
105 |
106 | - relations
107 | - attributes for which you already have a custom mutator
108 | - attributes using Eloquent's [date mutation](http://laravel.com/docs/eloquent#date-mutators)
109 |
110 | `$model->toArray()` triggers the casting as well. `$model->getAttributes()`, however, does not. It returns the raw values from the query (not even the date mutation).
111 |
112 |
113 |
114 |
115 | ## Bugs, Suggestions and Contributions
116 |
117 | Please use Github for bugs, comments, suggestions.
118 |
119 | 1. Fork the project.
120 | 2. Create your bugfix/feature branch and write your (well-commented) code.
121 | 3. Create unit tests for your code:
122 | - Run `composer install --dev` in the root directory to install required testing packages.
123 | - Add your test methods to `eloquent-typecast/tests/TypecastTest.php`.
124 | - Run `vendor/bin/phpunit` to the new (and all previous) tests and make sure everything passes.
125 | 3. Commit your changes (and your tests) and push to your branch.
126 | 4. Create a new pull request against the `develop` branch.
127 |
128 | **Please note that you must create your pull request against the `develop` branch.**
129 |
130 |
131 |
132 |
133 | ## Copyright and License
134 |
135 | Eloquent-Typecast was written by Colin Viebrock and released under the MIT License. See the [LICENSE.md](./LICENSE.md) file for details.
136 |
137 | Copyright 2014 Colin Viebrock
138 |
--------------------------------------------------------------------------------