This repository has been archived by the owner on Feb 13, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit aaa48a8
Showing
8 changed files
with
251 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
name: tests | ||
|
||
on: [push] | ||
|
||
jobs: | ||
test: | ||
name: PHP ${{ matrix.php }} - Laravel ${{ matrix.laravel }} | ||
runs-on: ${{ matrix.os }} | ||
strategy: | ||
fail-fast: false | ||
matrix: | ||
php: [8.0, 7.4, 7.1] | ||
laravel: [8.*, 7.*, 6.*, 5.8.*] | ||
os: [ubuntu-latest] | ||
include: | ||
- laravel: 8.* | ||
testbench: 6.* | ||
- laravel: 7.* | ||
testbench: 5.* | ||
- laravel: 6.* | ||
testbench: 4.* | ||
- laravel: 5.8.* | ||
testbench: 3.8.* | ||
exclude: | ||
- laravel: 8.* | ||
php: 7.1 | ||
- laravel: 7.* | ||
php: 7.1 | ||
- laravel: 6.* | ||
php: 7.1 | ||
- laravel: 5.8.* | ||
php: 8.0 | ||
steps: | ||
- name: Checkout code | ||
uses: actions/checkout@v1 | ||
|
||
- name: Setup PHP | ||
uses: shivammathur/setup-php@v2 | ||
with: | ||
php-version: ${{ matrix.php }} | ||
coverage: none | ||
|
||
- name: Install dependencies | ||
run: | | ||
composer config -g github-oauth.github.com ${{ secrets.GITHUB_TOKEN }} | ||
composer require "laravel/framework:${{ matrix.laravel }}" "orchestra/testbench:${{ matrix.testbench }}" --no-interaction --no-update | ||
composer update --prefer-stable --prefer-dist --no-interaction --no-suggest | ||
- name: Execute tests | ||
run: composer test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
composer.lock | ||
.idea | ||
vendor |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<?php declare(strict_types=1); | ||
|
||
namespace Temper\NullableProperties; | ||
|
||
use Illuminate\Database\Eloquent\Model; | ||
|
||
class NullableObserver | ||
{ | ||
public function saving(Model $model): bool | ||
{ | ||
if (!$model->nullable) return true; | ||
|
||
foreach ($model->toArray() as $property => $value) { | ||
if ($value === '' && $model->isDirty($property) && in_array($property, $model->nullable, true)) { | ||
$model->$property = null; | ||
} | ||
} | ||
|
||
return true; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
<?php declare(strict_types=1); | ||
|
||
namespace Temper\NullableProperties; | ||
|
||
use Illuminate\Database\Eloquent\Model; | ||
|
||
/** | ||
* Trait NullableProperties | ||
* @package Temper\NullableProperties | ||
* @mixin Model | ||
*/ | ||
trait NullableProperties { | ||
|
||
public static function bootNullableProperties(): void | ||
{ | ||
static::observe(new NullableObserver()); | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
<?php declare(strict_types=1); | ||
|
||
namespace Temper\NullableProperties\Providers; | ||
|
||
use Illuminate\Support\ServiceProvider; | ||
|
||
class NullablePropertiesServiceProvider extends ServiceProvider | ||
{ | ||
protected $defer; | ||
|
||
public function boot(): void | ||
{ | ||
// | ||
} | ||
|
||
public function register(): void | ||
{ | ||
// | ||
} | ||
|
||
public function provides(): array | ||
{ | ||
return []; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
<?php declare(strict_types=1); | ||
|
||
namespace Temper\NullableProperties\Tests; | ||
|
||
use Illuminate\Database\Eloquent\Model; | ||
use PHPUnit\Framework\TestCase; | ||
use Temper\NullableProperties\NullableProperties; | ||
|
||
class NullablePropertiesTest extends TestCase | ||
{ | ||
/** @dataProvider provides_values */ | ||
public function test_it_converts_empty_strings_to_null($propertyName, $initialValue, $expectedResult) | ||
{ | ||
/** @var Model $model */ | ||
$model = new class() extends Model { | ||
use NullableProperties; | ||
|
||
protected $nullable = ['nullableProperty']; | ||
public function save(array $options = []) { return $this->fireModelEvent('saving'); } | ||
}; | ||
|
||
$model->$propertyName = $initialValue; | ||
|
||
$this->assertEquals($initialValue, $model->$propertyName); | ||
$this->assertEquals(true, $model->save()); | ||
$this->assertEquals($expectedResult, $model->$propertyName); | ||
} | ||
|
||
public function provides_values() | ||
{ | ||
return [ | ||
['nullableProperty', '', null], | ||
['nullableProperty', 'string', 'string'], | ||
['nullableProperty', null, null], | ||
['nullableProperty', [], []], | ||
['nullableProperty', false, false], | ||
['nullableProperty', 0, 0], | ||
['otherProperty', '', ''], | ||
]; | ||
} | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
{ | ||
"name": "temper/laravel-nullable-properties", | ||
"description": "", | ||
"authors": [ | ||
{ | ||
"name": "Temper", | ||
"email": "info@temper.works" | ||
} | ||
], | ||
"require": { | ||
"php": ">=7.0" | ||
}, | ||
"require-dev": { | ||
"phpunit/phpunit": "*", | ||
"orchestra/testbench": "^6.12" | ||
}, | ||
"extra": { | ||
"laravel": { | ||
"providers": [ | ||
"Temper\\NullableProperties\\Providers\\NullablePropertiesServiceProvider" | ||
], | ||
"aliases": { | ||
|
||
} | ||
} | ||
}, | ||
"autoload": { | ||
"psr-4": { | ||
"Temper\\NullableProperties\\": "" | ||
} | ||
}, | ||
"scripts": { | ||
"test": [ | ||
"./vendor/bin/phpunit Tests/" | ||
] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
# Nullable Properties | ||
|
||
This package provides automatically nulled properties for Eloquent Models. | ||
|
||
When patching an Eloquent Model, it might be common to do something like this: | ||
|
||
```php | ||
$this->property = $request->get('property'); | ||
``` | ||
|
||
Or even: | ||
|
||
```php | ||
$this->fill($request->all()); | ||
``` | ||
|
||
A side effect of this is that empty fields in forms are stored in the database as empty strings, even when the database column is nullable. | ||
|
||
This can interfere with future queries such as: | ||
|
||
``` | ||
$users = User::whereNull('favoriteColor')->get(); | ||
``` | ||
|
||
## Usage | ||
|
||
Usage is simple. Add: | ||
|
||
* The `NullableProperties` trait | ||
* An array named `$nullable`, containing Model property names (similar to arrays like `$fillable` and `$casts`): | ||
|
||
```php | ||
<?php | ||
|
||
use Illuminate\Database\Eloquent\Model; | ||
use Temper\NullableProperties\NullableProperties; | ||
|
||
class User extends Model { | ||
use NullableProperties; | ||
|
||
public $nullable = ['favoriteColor']; | ||
}; | ||
``` | ||
|
||
Properties in this array are not allowed to be stored as empty strings, they will always default back to `null` when empty. | ||
|
||
Laravel can not easily detect nullable values at runtime. but you can easily get a table's nullable properties from the database: | ||
|
||
```mysql | ||
select concat('protected $nullable = [', group_concat(concat("'",column_name,"'")),'];') | ||
from information_schema.columns | ||
where table_name = 'users' and is_nullable = 'YES' | ||
and data_type = 'varchar'; | ||
``` |