Last active
June 1, 2021 00:34
-
-
Save basherr/4f5d5fef9213587120a96988162d29bb to your computer and use it in GitHub Desktop.
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
/// PRODUCT Data type | |
<?php | |
namespace App\DataTypes; | |
/** | |
* class Product | |
* | |
* Represent the Product type for the shopbot | |
* | |
* @package App\DataTypes | |
*/ | |
class Product extends PropertyAccessor | |
{ | |
/** | |
* @var string | |
*/ | |
protected $sku; | |
/** | |
* @var string | |
*/ | |
protected $title; | |
/** | |
* @var string | |
*/ | |
protected $image; | |
/** | |
* @var string | |
*/ | |
protected $link; | |
} | |
/// Default Property Accessor class | |
namespace App\DataTypes; | |
/** | |
* class PropertyAccessor | |
* | |
* Retrieve/changes any property of the class dynmically without the need for | |
* setters & getters | |
* | |
* To set `foo` property for a class, just call `setFoo` method on object instance | |
* where `Foo` first character will be converted to lowercase | |
* | |
* @package App\DataTypes | |
*/ | |
abstract class PropertyAccessor | |
{ | |
/** | |
* Set any property for the class dynamically | |
* | |
* @param string $name | |
* @param mixed $value | |
* @return $this | |
*/ | |
public function __call(string $name, $value) | |
{ | |
if (substr($name, 0, 3) === 'set') { | |
return $this->setProperty($name, $value); | |
} else if (substr($name, 0, 3) === 'get') { | |
return $this->getProperty($name); | |
} | |
} | |
/** | |
* Set any property for the class | |
* | |
* @param string $name | |
* @param mixed $value | |
* @return $this | |
* @throws \App\Exception\InvalidSetterException | |
*/ | |
protected function setProperty(string $name, $value) | |
{ | |
$property = lcfirst(str_replace('set', '', $name)); | |
if (property_exists($this, $property)) { | |
$this->$property = array_shift($value); | |
return $this; | |
} | |
throw new \Exception('Invalid Property Setter'); | |
} | |
/** | |
* Retrieve any property for the class dynamically | |
* | |
* @param string $name | |
* @return mixed | |
* @throws \App\Exception\InvalidGetterException | |
*/ | |
public function getProperty(string $name) | |
{ | |
$property = lcfirst(str_replace('get', '', $key)); | |
if (property_exists($this, $property)) { | |
return $this->$property; | |
} | |
throw new \Exception('Invalid Property Getter'); | |
} | |
} | |
Because Zest
isn't going to be the only Connector
we have long term. It should be App\ApiModels\AbstractProduct
which defines 90% of the class, but then there needs to be a connector implementation for Zest which tells it how to hydrate from a API result.
So \App\Connectors\Zest\ApiModels\Product
extends App\ApiModels\AbstractProduct
& probably has 1 method:
hydrate($productData)
- this receives a raw API product data & hydrates the properties defined inAbstractProduct
.
Then in future when we want to connect to e.g. Shopify
, we will have a \App\Connectors\Shopify\Product
which will extend AbstractProduct
, and its hydrate
method will take a Shopify product API result & translate it to hydrate the AbstractProduct
properties.
@brentkelly Perfect, thanks.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@brentkelly Why
Product
should be abstract? How we will instantiate anabstract class Product
? What I believe it should implement a contract tohydrate
orextend
a base abstract class that containshydrate
method asabstract
.