Last active
February 14, 2020 13:58
-
-
Save recca0120/a15c7504dfb64ce3a0b08fe825f9876a to your computer and use it in GitHub Desktop.
php Array key 自動轉換 studly, camel, snake, kebab case
This file contains hidden or 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
<?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'); | |
} | |
} |
This file contains hidden or 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
<?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