piggly / php-payload
一个简单的负载数据管理器。
Requires
- php: ^7.3 || ^8.0
- respect/validation: ^2.2
Requires (Dev)
- phpunit/phpunit: ^9.5
- roave/security-advisories: dev-latest
README
负载,正如其名,关于数据。这是传统的 getter 和 setter 模型。但是,我们不再需要模型。感谢 (Eloquent Model)[https://laravel.net.cn/docs/8.x/eloquent] 解决了这个问题。
但是,仍然有请求和响应数据,它们不是任何类型的存储数据,它们只是数据。对它们采用某种 ORM 模型... 这有点过度思考,使这些数据变得过于复杂。
这个简单的库就是为了解决这个问题。负载是更具灵活性的传统 数组
。我们在 Eloquent 模型中看到的相同灵活性,但绝对不是复杂或过于强大。它只是跨请求和响应标准化数据的一种方式。
下面是如何使用它的示例。
PayloadArray
Person
对象
namespace Piggly\Dev\Payload; use Piggly\Payload\Exceptions\InvalidDataException; use Piggly\Payload\PayloadArray; use Respect\Validation\Validator as v; class Person extends PayloadArray { /** * Import $input data to payload. * * @param array $input * @since 1.0.0 * @return self * @throws InvalidDataException */ public function import ( $input ) { $input = is_array( $input ) ? $input : json_decode($input, true); $_map = [ 'name' => 'setName', 'email' => 'setEmail', 'phone' => 'setPhone', 'address' => 'setAddress' ]; return $this->_importArray($_map, $input); } /** * Validate all data from payload. * Throw an exception when cannot validate. * * @since 1.0.0 * @return void * @throws InvalidDataException */ public function validate () { $required = [ 'address', 'name', 'email', 'phone' ]; $this->_validateRequired($required); $this->_validateDepth(); } /** * Get name. * * @since 1.0.0 * @return string */ public function getName () { return $this->get('name'); } /** * Set name. * * @param string $name Name. * @since 1.0.0 * @return self */ public function setName ( string $name ) { $this->add('name', \ucwords($name)); return $this; } /** * Get phone. * * @since 1.0.0 * @return string */ public function getPhone () { return $this->get('phone'); } /** * Set phone. * * @param string $phone Phone. * @since 1.0.0 * @return self * @throws InvalidDataException */ public function setPhone ( string $phone ) { if ( v::phone()->validate($phone) === false ) { throw InvalidDataException::invalid($this, 'phone', $phone, 'Invalid phone.'); } $this->add('phone', $phone); return $this; } /** * Get e-mail. * * @since 1.0.0 * @return string */ public function getEmail () { return $this->get('email'); } /** * Set e-mail. * * @param string $email E-mail. * @since 1.0.0 * @return self * @throws InvalidDataException */ public function setEmail ( string $email ) { if ( v::email()->validate($email) === false ) { throw InvalidDataException::invalid($this, 'email', $email, 'Invalid e-mail.'); } $this->add('email', $email); return $this; } /** * Get address. * * @since 1.0.0 * @return Address */ public function getAddress () { return $this->get('address'); } /** * Set address. * * @param Address|array $address Address. * @since 1.0.0 * @return self */ public function setAddress ( $address ) { if ( !($address instanceof Address) ) { $address = (new Address())->import($address); } $this->add('address', $address); return $this; } }
Address
对象
namespace Piggly\Dev\Payload; use Piggly\Payload\Exceptions\InvalidDataException; use Piggly\Payload\PayloadArray; use Respect\Validation\Validator as v; class Address extends PayloadArray { /** * Import $input data to payload. * * @param array $input * @since 1.0.0 * @return self * @throws InvalidDataException */ public function import ( $input ) { $input = is_array( $input ) ? $input : json_decode($input, true); $_map = [ 'address' => 'setAddress', 'number' => 'setNumber', 'complement' => 'setComplement', 'district' => 'setDistrict', 'city' => 'setCity', 'country_id' => 'setCountry', 'postal_code' => 'setPostalCode' ]; return $this->_importArray($_map, $input); } /** * Validate all data from payload. * Throw an exception when cannot validate. * * @since 1.0.0 * @return void * @throws InvalidDataException */ public function validate () { $required = [ 'address', 'number', 'district', 'city', 'country_id', 'postal_code' ]; $this->_validateRequired($required); } /** * Get address. * * @since 1.0.0 * @return string */ public function getAddress () { return $this->get('address'); } /** * Set address. * * @param string $address Address. * @since 1.0.0 * @return self */ public function setAddress ( string $address ) { $this->add('address', $address); return $this; } /** * Get complement. * * @since 1.0.0 * @return string */ public function getComplement () { return $this->get('complement'); } /** * Set complement. * * @param string $complement Complement. * @since 1.0.0 * @return self */ public function setComplement ( string $complement ) { $this->add('complement', $complement); return $this; } /** * Get number. * * @since 1.0.0 * @return string */ public function getNumber () { return $this->get('number'); } /** * Set number. * * @param string $number Number. * @since 1.0.0 * @return self */ public function setNumber ( string $number ) { $this->add('number', $number); return $this; } /** * Get district name. * @since 1.0.0 * @return string */ public function getDistrict () { return $this->get('district'); } /** * Set district name. * * @param string $district District name. * @since 1.0.0 * @return self */ public function setDistrict ( string $district ) { $this->add('district', \ucwords($district)); return $this; } /** * Get city name. * * @since 1.0.0 * @return string */ public function getCity () { return $this->get('city'); } /** * Set city name. * * @param string $city City name. * @since 1.0.0 * @return self */ public function setCity ( string $city ) { $this->add('city', \ucwords($city)); return $this; } /** * Get country ID. * * @since 1.0.0 * @return string */ public function getCountry () { return $this->get('country_id'); } /** * Set country ID. * * @param string $country_id Country ID. * @since 1.0.0 * @return self * @throws InvalidDataException */ public function setCountry ( string $country_id ) { if ( v::countryCode()->validate($country_id) === false ) { throw InvalidDataException::invalid($this, 'country_id', $country_id, 'Invalid country code.'); } $this->add('country_id', \strtoupper($country_id)); return $this; } /** * Get postal Code. * * @since 1.0.0 * @return string */ public function getPostalCode () { return $this->get('postal_code'); } /** * Set postal Code. * * @param string $postal_code Postal Code. * @since 1.0.0 * @return self * @throws InvalidDataException */ public function setPostalCode ( string $postal_code ) { if ( v::postalCode( $this->get('country_id', 'US') )->validate($postal_code) === false ) { throw InvalidDataException::invalid($this, 'postal_code', $postal_code, 'Invalid postal code.'); } $this->add('postal_code', \preg_replace('/[^\d]/', '', $postal_code)); return $this; } }
用法
use Piggly\Dev\Payload\Person; $person = [ 'name' => 'John Connor', 'email' => 'john@skynet.com', 'phone' => '+1-202-555-0172', 'address' => [ 'address' => 'Future Avenue', 'number' => '2047', 'complement' => 'High Tech World', 'district' => 'Nobody\'s Alive', 'city' => 'Unknown', 'country_id' => 'US', 'postal_code' => '55372' ] ]; // Import from an array $person = (new Person())->import($person); // Validate (throw an exception if can't) $person->validate(); // Payload object to array $_array = $person->toArray(); // Payload object to json $_json = $person->toJson(); // Alternative way to converto to json $_json = json_encode($person); // Serialize $_serialized = serialize($person); // Unserialize $_unserialized = unserialize($_serialized);
PayloadMap
PayloadMap
类强制负载使用映射。此映射将严格定义允许负载的所有字段,甚至字段验证。每个 PayloadMap
中的字段都将是一个 Field
对象。Field
对象将具有以下属性
还有以下方法
export()
将导出字段值;validate()
将返回一个boolean
,表示验证字段值;assert()
如果无法验证字段值,将抛出InvalidDataException
;props()
一次性设置所有属性;back()
用于导航目的,将返回到PayloadMap
对象,因为Field
在其中。
创建 PayloadMap
的方式与创建 PayloadArray
相同,但需要 _map()
方法,该方法将包含字段的映射
namespace Piggly\Dev\Payload; use Piggly\Payload\Exceptions\InvalidDataException; use Piggly\Payload\PayloadMap; use Respect\Validation\Validator as v; class PersonMap extends PayloadMap { /** * This method is called at constructor. * You should use it to setup fields map * with add method. * * @since 1.0.5 * @return void */ protected function _map () { $this ->add('name') ->required() ->back() ->add('email') ->validator(v::email()) ->required() ->back() ->add('phone') ->validator(v::phone()) ->back() ->add('address') ->back(); } /** * Import $input data to payload. * * @param array $input * @param bool $ignoreInvalid Should ignore invalid data. * @since 1.0.0 * @return self * @throws InvalidDataException */ public function import ( $input, $ignoreInvalid = true ) { $input = is_array( $input ) ? $input : json_decode($input, true); return $this->_importArray($input, $ignoreInvalid); } /** * Mutator for address. * * @param AddressMap|array $address Address. * @since 1.0.0 * @return AddressMap */ protected function setterAddress ( $address ) : AddressMap { if ( !($address instanceof AddressMap) ) { $address = (new AddressMap())->import($address); } return $address; } }
您可以使用 setter{key}()
和 getter{key}()
方法在设置和获取之前修改字段值。转换器,无论是设置器还是获取器,都应该始终返回已修改的值。
变更日志
有关所有代码更改的信息,请参阅 CHANGELOG 文件。
测试代码
此库使用 PHPUnit。我们对应用程序的所有主要类进行了测试。
vendor/bin/phpunit
贡献
在提交您的贡献之前,请参阅 CONTRIBUTING 文件。
致谢
支持项目
Piggly Studio 是一家位于巴西里约热内卢的代理机构。如果您喜欢这个库并想支持这项工作,请随意向 BTC 钱包 3DNssbspq7dURaVQH6yBoYwW3PhsNs8dnK
捐款 ❤。
许可证
MIT 许可证 (MIT)。请参阅 LICENSE。