piggly/php-payload

一个简单的负载数据管理器。

1.1.0 2021-05-17 17:16 UTC

This package is auto-updated.

Last update: 2024-09-18 00:31:20 UTC


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