心之码客 / 对象模型
为Laravel项目添加模式、控制和将PHP JSON转换为对象和数组的包
1.1.14
2023-06-10 20:57 UTC
Requires
- php: ^8.1
- ext-json: *
- illuminate/support: ^10.0 || ^9.0 || ^10.0
- illuminate/validation: ^8.0 || ^9.0 || ^10.0
- nesbot/carbon: ^2.61
Requires (Dev)
- pestphp/pest: ^v2.1.0
- symfony/var-dumper: ^6.1
README
此Laravel包
- 提供了一种流畅的方式来定义对象的架构/模式
- 允许您以一致的方式验证这些对象
- 轻松地将eloquent JSON属性转换为ObjectModels以方便处理
- 减少您的应用程序中的元数据表数量
要求
此包需要
- PHP 8.1和
- Laravel 8.0或更高版本(包括10)。
安装
安装它
composer require coder-at-heart/object-models
定义ObjectModels
扩展ObjectModel类并重写properties()
方法
我通常创建一个app/ObjectModels
文件夹来存储我的模型
以下是从测试文件夹的示例
<?php namespace CoderAtHeart\ObjectModel\Tests\Models; use Carbon\Carbon; use CoderAtHeart\ObjectModel\ObjectModel; use CoderAtHeart\ObjectModel\Property; /** * @property string name * @property int age * @property string email * @property Address home * @property Address business * @property Phone[] phone_numbers * @property Carbon birthday * @property Carbon alarm * @property bool subscribed * @property array friends * @property Carbon[] important_dates */ class Person extends ObjectModel { public static function properties(): array { return [ Property::string('name')->required(), Property::integer('age')->nullable(), Property::email('email'), Property::objectModel('home', Address::class), Property::objectModel('business', Address::class), Property::objectModelArray('phone_numbers', Phone::class), Property::date('birthday'), Property::time('alarm')->default('08:00:00'), Property::bool('subscribed')->default(false), Property::array('friends'), Property::propertyArray('important_dates', Property::date('date')), ]; } }
以及Address
namespace CoderAtHeart\ObjectModel\Tests\Models; use CoderAtHeart\ObjectModel\ObjectModel; use CoderAtHeart\ObjectModel\Property; use CoderAtHeart\ObjectModel\Tests\ENUMs\Country; /** * @property string address_1 * @property string address_2 * @property string city * @property string postcode * @property Country country_code */ class Address extends ObjectModel { public static function properties(): array { return [ Property::string('address_1'), Property::string('address_2'), Property::string('city'), Property::enum('country_code', Country::class)->default(Country::GB)->required(), Property::string('postcode'), ]; } }
Country
枚举
<?php namespace CoderAtHeart\ObjectModel\Tests\ENUMs; enum Country : string { case US = 'us'; case GB = 'gb'; }
以及Phone
<?php namespace CoderAtHeart\ObjectModel\Tests\Models; use CoderAtHeart\ObjectModel\ObjectModel; use CoderAtHeart\ObjectModel\Property; /** * @property string label * @property string number */ class Phone extends ObjectModel { public static function properties(): array { return [ Property::string('label'), Property::string('number'), ]; } }
注意类顶部使用的docBlock - 这有助于在ide中完成类型提示。
实例化对象
可以通过数组、json或直接完成
// Create from an array of data $person = Person::createFrom(array:[ 'name' => 'Coder At Heart', 'age' => 30, 'email' => 'coderatheart@gmail.com', 'home' => [ 'address_1' => 'Some Street', 'address_2' => 'Some Area', 'city' => 'Some City', 'postcode' => 'AB12 3CD', ], 'business' => [ 'address_1' => 'Some Business', 'address_2' => 'Some Location', 'city' => 'Some City', 'postcode' => 'AB99 9DC', ], 'phone_numbers' => [ [ 'label' => 'home', 'number' => '01234 67890' ], [ 'label' => 'mobile', 'number' => '09999 123456' ], ], 'birthday' => '1990-01-01' 'important_dates' => [ '2011-01-01 01:01:01', '2012-02-02 02:02:02', '2013-03-03 03:03:03', '2014-04-06 04:04:04', '2015-05-06 05:05:05', ] ]); echo $person->name; // the return value is the underlying object. in this case // a Carbon Object echo $person->birthday->format('js F Y'); // Access deep objects echo $person->home->address_1; echo $person->phone_numbers[1]->number; // Save this to json $json = $person->toJson(); // Create a new person $bob = Person::createFrom(json: $json) $bob->name = 'Bob'; // Convert the person to an array $array = $bob->toArray(); $fred= Person::createFrom(array: $bob) $fred->name = 'Fred'; $fred->age = 25; // Just like a normal object: $isabel = new Person(); $isabel->name = 'Isabel'; $isabel->age = 35; $isabel->birthday = new Carbon("2002-11-23");
ArrayModels
您不需要对象模型就可以使用数组对象
<?php use CoderAtHeart\ObjectModel\ArrayModel; $numbers = ArrayModel::create(objectModel: Phone::class); // Create a new phone number $homePhone = new Phone(); $homePhone->label = 'home'; $homePhone->number = '01234 567890'; $numbers[] = $homePhone; echo $numbers[0]->number; // add to it like a normal array $numbers[] = [ 'label' => 'business', 'number' => '01234 567890', ]; // Access it like an object echo $numbers[1]->label;
转换eloquent模型属性和json列
您可以在应用程序中创建自定义转换时使用ObjectModels和ArrayModels - 尤其是当转换json列时非常有用。
ObjectModels
<?php namespace App\Casts; use App\ObjectModels\Person; use Illuminate\Contracts\Database\Eloquent\CastsAttributes; use Illuminate\Database\Eloquent\Model; class PersonCast implements CastsAttributes { public function get($model, string $key, $value, array $attributes) { return Person::create(json: $value); } public function set($model, string $key, $value, array $attributes) { return $value->toJson(); } }
以及ArrayModels
<?php namespace App\Casts; use App\ObjectModels\PhonesNumbers; use CoderAtHeart\ObjectModel\ArrayModel;use CoderAtHeart\ObjectModel\Tests\Models\Person;use Illuminate\Contracts\Database\Eloquent\CastsAttributes; use Illuminate\Database\Eloquent\Model; class LogCast implements CastsAttributes { public function get($model, string $key, $value, array $attributes) { return PhonesNumbers::create(json: $value); // or return ArrayModel::create(json: $value, objectModel: Phone::class); } public function set($model, string $key, $value, array $attributes) { return $value->toJson(); } }
内置属性类型
自定义属性类型
扩展Property
类以添加您自己的属性。
<?php use CoderAtHeart\ObjectModel\Property; /** * @property string label * @property string number */ class CustomProperties extends Property { /** * zipCode * * @param string $name * * @return static */ public static function zipCode(string $name): Property { return self::property($name) ->addRule('numeric|min:5') // jsonCallback will be called when teh object is converted to json ->jsonCallback(function ($value) { return str_replace(' ', '', $value); }) // This callback is called when the value is set ->setCallback(function ($value) { return (string) $value; }) ->set(null); } }
两个主要的回调是jsonCallback
,当属性即将被转换为json时调用,以及当属性被分配值时调用的setCallback
。
这是一个使用自定义属性的示例对象
<?php use CoderAtHeart\ObjectModel\ObjectModel; use CoderAtHeart\ObjectModel\CustomProperties; /** * @property string address_1 * @property string address_2 * @property string city * @property string zip */ class Address extends ObjectModel { public static function properties(): array { return [ CustomProperties::string('address_1'), CustomProperties::string('address_2'), CustomProperties::string('city'), CustomProperties::zipCode('zip'), ]; } }
对象验证
对象和数组可以进行验证。您将获得的是ObjectValidation对象
<?php $validation = $person->validate(); // $validation is an ObjectModel echo $validation->valid; // or echo $validation->isValid(); // the name of the object / array echo $validation->name; // the errors dd($validation->errros);
注意:ObjectModels或ArrayModels不会自动进行验证。
添加规则
当您定义对象时,可以添加任何有效的Laravel验证规则
<?php class Person extends ObjectModel { public static function properties(): array { return [ Property::string('name')->required(), // just adds 'required' to the rules array Property::integer('age')->nullable(), // optional Property::email('email')->addRule('min:20'), Property::string('first_name')->addRule(new Rule()), // custom rules ]; } }
您可以使用$person->getRules()
在objectModel上获取规则
忽略未定义的属性
默认情况下,ObjectModels如果在尝试设置尚未定义的属性时抛出异常。
使用IgnoreUndefinedProperties特性来解决这个问题
<?php use \CoderAtHeart\ObjectModel\Traits\IgnoreUndefinedProperties; class Person extends ObjectModel { use IgnoreUndefinedProperties; public static function properties(): array { return [ Property::string('name')->required(), // just adds 'required' to the rules array Property::integer('age')->nullable(), // optional Property::email('email')->addRule('min:20'), Property::string('first_name')->addRule(new Rule()), // custom rules ]; } }
有想法/建议/改进吗?
请告诉我... somehow。
支持
许可证
ObjectModel是在MIT许可证下授权的。
v1.1.14