Last active
September 23, 2019 14:13
-
-
Save jakewtaylor/5eb186f7af596aa8731fe29d1ccf26d8 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
<?php | |
use Illuminate\Support\Str; | |
$method = 'whereBoardingType'; | |
// Currently, you need to do something like this in PHP | |
$method = 'whereBoardingType'; | |
$method = Str::substr($method, 5); | |
$method = Str::snake($method); | |
$method = Str::plural($method); | |
// but now, you can do this: | |
$key = take($method) | |
->scope(Str::class) // scopes all subsequent methods to this class | |
->pipe('substr', 5) | |
->pipe('snake') | |
->pipe('plural') | |
->complete(); | |
// $key === 'boarding_types' | |
/////////////////////////////// | |
$subdomain = take('https://www.example.com') | |
->pipe('parse_url', PHP_URL_HOST) // value is always passed as first parameter - parse_url($value, PHP_URL_HOST) | |
->pipe('explode', '.', '$$') // unless you pass a '$$' - explode('.', $value) | |
->pipe('reset') | |
->complete(); | |
// $subdomain === 'www' | |
/////////////////////////////// | |
// Thanks to __call you can just use method names if you want. | |
// You can also pass a scope as the 2nd parameter to take for slightly more terse code. | |
$key = take($method, Str::class) | |
->substr(5) | |
->snake() | |
->plural() | |
->complete(); |
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
<?php | |
if (!function_exists('take')) { | |
function take(...$args) | |
{ | |
return Piper::make(...$args); | |
} | |
} |
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
<?php | |
namespace App\Helpers; | |
use Illuminate\Support\Collection; | |
class Piper | |
{ | |
/** | |
* The symbol that will be replaced with the current value. | |
* | |
* @var string | |
*/ | |
const SYMBOL = '$$'; | |
/** | |
* The current value. | |
* | |
* @var mixed | |
*/ | |
protected $value; | |
/** | |
* Class to scope calls to. | |
* | |
* @var string | |
*/ | |
protected $scope; | |
/** | |
* Constructs the piper. | |
* | |
* @param mixed $value | |
*/ | |
public function __construct($value, $scope = null) | |
{ | |
$this->value = $value; | |
$this->scope = $scope; | |
} | |
/** | |
* Applies a pipe to the value. | |
* | |
* @param mixed $callable | |
* @param mixed ...$args | |
* @return self | |
*/ | |
public function pipe($callable, ...$args): self | |
{ | |
$callable = $this->getCallable($callable); | |
$args = $this->getArgs($args); | |
return $this->applyPipe($callable, $args); | |
} | |
/** | |
* Returns the final value. | |
* | |
* @return mixed | |
*/ | |
public function complete() | |
{ | |
return $this->value; | |
} | |
/** | |
* Scopes the piper to the specified class. | |
* | |
* @param string $scope | |
* @return self | |
*/ | |
public function scope(string $scope): self | |
{ | |
$this->scope = $scope; | |
return $this; | |
} | |
/** | |
* Builds the args array. | |
* | |
* @param array $args | |
* @return array | |
*/ | |
protected function getArgs(array $args): array | |
{ | |
$args = Collection::wrap($args); | |
if ($this->hasValueSymbol($args)) { | |
return $this->replaceValueSymbol($args)->toArray(); | |
} | |
return $args->prepend($this->value)->toArray(); | |
} | |
/** | |
* Gets a callable value from the provided value. | |
* | |
* @param mixed $callable | |
* @return callable | |
*/ | |
protected function getCallable($callable): callable | |
{ | |
if (is_string($callable) && $this->scope) { | |
return [$this->scope, $callable]; | |
} | |
return $callable; | |
} | |
/** | |
* Applies the specified pipes and updates the value. | |
* | |
* @param callable $callable | |
* @param array $args | |
* @return self | |
*/ | |
protected function applyPipe(callable $callable, array $args): self | |
{ | |
// We check for string global methods because | |
// sometimes some built in PHP methods raise | |
// an 'expected to be reference, value given' | |
// warning when used with call_user_func | |
if (is_string($callable)) { | |
$this->value = $callable(...$args); | |
} else { | |
$this->value = call_user_func($callable, ...$args); | |
} | |
return $this; | |
} | |
/** | |
* Determines if the value symbol is in the args collection. | |
* | |
* @param Collection $args | |
* @return boolean | |
*/ | |
protected function hasValueSymbol(Collection $args): bool | |
{ | |
return $args->contains(self::SYMBOL); | |
} | |
/** | |
* Replaces the value symbol in the args collection. | |
* | |
* @param Collection $args | |
* @return Collection | |
*/ | |
protected function replaceValueSymbol(Collection $args): Collection | |
{ | |
return $args->map(function ($arg) { | |
return $arg === self::SYMBOL | |
? $this->value | |
: $arg; | |
}); | |
} | |
/** | |
* Statically creates an instance of Piper. | |
* | |
* @param mixed ...$args | |
* @return self | |
*/ | |
public static function make(...$args): self | |
{ | |
return new static(...$args); | |
} | |
/** | |
* Allows dynamic calls as pipes. | |
* | |
* @param string $method | |
* @param array $args | |
* @return self | |
*/ | |
public function __call(string $method, array $args) | |
{ | |
return $this->pipe($method, ...$args); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment