Skip to content

Instantly share code, notes, and snippets.

@recca0120
Last active February 14, 2020 13:58
Show Gist options
  • Save recca0120/a15c7504dfb64ce3a0b08fe825f9876a to your computer and use it in GitHub Desktop.
Save recca0120/a15c7504dfb64ce3a0b08fe825f9876a to your computer and use it in GitHub Desktop.
php Array key 自動轉換 studly, camel, snake, kebab case
<?php
use ArrayAccess;
class Parameter implements ArrayAccess
{
const STUDLY = 1;
const CAMEL = 2;
const SNAKE = 3;
const KEBAB = 4;
/**
* @var array
*/
protected static $studlyCache = [];
/**
* @var array
*/
protected static $camelCache = [];
/**
* @var array
*/
protected static $snakeCache = [];
/**
* @var array
*/
private $attributes = [];
/**
* @var string
*/
private $defaultCaseMethod;
/**
* @var array
*/
private $customCase = [];
/**
* Option constructor.
*
* @param array $parameters
* @param int $defaultCase
* @param array $customCase
*/
public function __construct(array $parameters = [], $defaultCase = self::CAMEL, $customCase = [])
{
$this->from($parameters);
$this->defaultCase($defaultCase);
$this->customCase($customCase);
}
/**
* @param $offset
* @return mixed
*/
public function __get($offset)
{
return $this->offsetGet($offset);
}
/**
* @param $offset
* @param $value
* @return mixed|void
*/
public function __set($offset, $value)
{
return $this->offsetSet($offset, $value);
}
/**
* @param array $parameters
* @return $this
*/
public function from($parameters = [])
{
foreach ($parameters as $key => $value) {
$this->{$key} = $value;
}
return $this;
}
/**
* @param string|null $defaultCase
* @return $this
*/
public function defaultCase(string $defaultCase = null)
{
$this->defaultCaseMethod = static::toCaseMethod($defaultCase);
return $this;
}
/**
* @param array $customCase
* @return $this
*/
public function customCase(array $customCase)
{
$this->customCase = [];
foreach ($customCase as $key => $value) {
$this->customCase[static::studly($key)] = $value;
}
return $this;
}
/**
* @return array
*/
public function toArray()
{
$result = [];
foreach ($this->attributes as $key => $value) {
$result[$this->changeCase($key)] = $value;
}
return $result;
}
/**
* {@inheritdoc}
*/
public function offsetExists($offset)
{
return array_key_exists(static::studly($offset), $this->attributes);
}
/**
* {@inheritdoc}
*/
public function offsetGet($offset)
{
return $this->attributes[static::studly($offset)];
}
/**
* {@inheritdoc}
*/
public function offsetSet($offset, $value)
{
return $this->attributes[static::studly($offset)] = $value;
}
/**
* {@inheritdoc}
*/
public function offsetUnset($offset)
{
unset($this->attributes[static::studly($offset)]);
}
/**
* @param $value
* @return mixed
*/
private function changeCase($value)
{
if (is_numeric($value)) {
return $value;
}
if (! array_key_exists($value, $this->customCase)) {
return call_user_func($this->defaultCaseMethod, ($value));
}
$method = $this->customCase[$value];
$method = is_int($method) ? static::toCaseMethod($method) : $method;
return is_callable($method) ? $method($value) : $method;
}
/**
* @param $case
* @return string
*/
private static function toCaseMethod($case)
{
$lookup = [
static::STUDLY => __CLASS__.'::studly',
static::CAMEL => __CLASS__.'::camel',
static::SNAKE => __CLASS__.'::snake',
static::KEBAB => __CLASS__.'::kebab',
];
return $lookup[$case];
}
/**
* @param $value
* @return string
*/
private static function studly($value)
{
$key = $value;
if (isset(static::$studlyCache[$key])) {
return static::$studlyCache[$key];
}
$value = ucwords(str_replace(['-', '_'], ' ', $value));
return static::$studlyCache[$key] = str_replace(' ', '', $value);
}
/**
* @param $value
* @return string
*/
private static function camel($value)
{
if (isset(static::$camelCache[$value])) {
return static::$camelCache[$value];
}
return static::$camelCache[$value] = lcfirst(static::studly($value));
}
/**
* @param $value
* @param string $delimiter
* @return string
*/
private static function snake($value, $delimiter = '_')
{
$key = $value;
if (isset(static::$snakeCache[$key][$delimiter])) {
return static::$snakeCache[$key][$delimiter];
}
if (! ctype_lower($value)) {
$value = preg_replace('/\s+/u', '', ucwords($value));
$value = static::lower(preg_replace('/(.)(?=[A-Z])/u', '$1'.$delimiter, $value));
}
return static::$snakeCache[$key][$delimiter] = $value;
}
/**
* @param $value
* @return string
*/
private static function kebab($value)
{
return static::snake($value, '-');
}
/**
* @param $value
* @return string
*/
private static function lower($value)
{
return mb_strtolower($value, 'UTF-8');
}
}
<?php
namespace Tests\Unit\Gateway;
use PHPUnit\Framework\TestCase;
class ParameterTest extends TestCase
{
public function test_studly_case()
{
$parameter = new Parameter([
'test_one' => 'value',
'testTwo' => 'value',
'TestThree' => 'value',
'test-four' => 'value',
]);
$parameter->defaultCase(Parameter::STUDLY);
$this->assertEquals([
'TestOne' => 'value',
'TestTwo' => 'value',
'TestThree' => 'value',
'TestFour' => 'value',
], $parameter->toArray());
}
public function test_camel_case()
{
$option = new Parameter([
'test_one' => 'value',
'testTwo' => 'value',
'TestThree' => 'value',
'test-four' => 'value',
], Parameter::CAMEL);
$this->assertEquals([
'testOne' => 'value',
'testTwo' => 'value',
'testThree' => 'value',
'testFour' => 'value',
], $option->toArray());
}
public function test_snake_case()
{
$option = new Parameter([
'test_one' => 'value',
'testTwo' => 'value',
'TestThree' => 'value',
'test-four' => 'value',
], Parameter::SNAKE);
$this->assertEquals([
'test_one' => 'value',
'test_two' => 'value',
'test_three' => 'value',
'test_four' => 'value',
], $option->toArray());
}
public function test_kebab_case()
{
$option = new Parameter([
'test_one' => 'value',
'testTwo' => 'value',
'TestThree' => 'value',
'test-four' => 'value',
], Parameter::KEBAB);
$this->assertEquals([
'test-one' => 'value',
'test-two' => 'value',
'test-three' => 'value',
'test-four' => 'value',
], $option->toArray());
}
public function test_extra()
{
$option = new Parameter();
$arr = [
'test_one' => 'value',
'testTwo' => 'value',
'TestThree' => 'value',
'test-four' => 'value',
1 => 'value',
2 => 'value',
];
foreach ($arr as $key => $value) {
$option[$key] = $value;
}
$this->assertEquals([
'testOne' => 'value',
'testTwo' => 'value',
'testThree' => 'value',
'testFour' => 'value',
1 => 'value',
2 => 'value',
], $option->toArray());
$this->assertEquals('value', $option['testOne']);
$this->assertEquals('value', $option->testOne);
$this->assertEquals('value', $option->TestOne);
}
public function test_custom_case()
{
$option = new Parameter([
'test_one' => 'value',
'testTwo' => 'value',
'TestThree' => 'value',
'test-four' => 'value',
'test-five' => 'value',
'test-six' => 'value',
]);
$option->customCase([
'test_one' => Parameter::STUDLY,
'testTwo' => Parameter::KEBAB,
'TestThree' => Parameter::SNAKE,
'test-four' => Parameter::CAMEL,
'test-five' => function () {
return 'foo';
},
'test-six' => 'bar',
]);
$this->assertEquals([
'TestOne' => 'value',
'test-two' => 'value',
'test_three' => 'value',
'testFour' => 'value',
'foo' => 'value',
'bar' => 'value',
], $option->toArray());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment