Last active
April 24, 2016 06:41
-
-
Save Leko/6665a57aab9a5d3ae5cb to your computer and use it in GitHub Desktop.
PHPでの便利なスニペット、関数、クラス
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 | |
// 欲しいメソッドのインタフェースだけ書いていく | |
// isset + デフォルト値 | |
// 階層は.で潜るFuel式が手軽そう | |
// http://fuelphp.com/docs/classes/arr.html#/method_get | |
Array::get(array $source, $key, $default = null) | |
// Lodashのconcat | |
// https://lodash.com/docs#concat | |
Array::concat(array $source, $merge_arrays...) | |
// Lodashのfind | |
// https://lodash.com/docs#find | |
// @param array|callable $predicate 関数もしくは$key = $valueと見なすための連想配列 | |
Array::find(array $source, $predicate) | |
// Lodashのreject | |
// https://lodash.com/docs#reject | |
// @param array|callable $predicate 関数もしくは$key = $valueと見なすための連想配列 | |
Array::reject(array $source, $predicate) | |
// > エントリを一つだけ取得する場合、 array_rand() はランダムなエントリのキーを返します。 | |
// > http://php.net/manual/ja/function.array-rand.php | |
// の糞仕様を解消して配列内の値をランダムに1つ返す | |
Array::rand(array $source) | |
// 対象の配列が連想配列か否かを返す。添字配列ならfalse | |
Array::isAssoc(array $source) | |
// LodashのgroupBy | |
// https://lodash.com/docs#groupBy | |
// @param array|callable $predicate 関数もしくは$key = $valueと見なすための連想配列 | |
Array::groupBy(array $source, $predicate) | |
// in_arrayの第三引数が常時trueになってる版 | |
Array::includes(array $source, $value) | |
// FuelのArr::pluck | |
Array::pluck(array $source, $key) | |
// Underscore.jsのpickメソッド | |
// http://underscorejs.org/#pick | |
Array::pick(array $source, array $pick_keys) | |
// 連想配列から指定されたキーを除外した値を返却する | |
Array::omit(array $source, array $omit_keys) | |
// issetの代わり | |
Array::has(array $source, $key) | |
// issetの代わり + 複数キーを一気に調べる | |
Array::hasAll(array $source, array $keys) | |
// Ruby2.3のdigメソッド | |
Array::dig(array $source, $keys...) | |
// RubyのEnumerable#grep | |
// http://ref.xaio.jp/ruby/classes/enumerable/grep | |
Array::grep(array $source, $value) | |
// ↑のキーを対象にした版(連想配列を想定) | |
Array::grepKeys(array $source, $value) | |
// 暇があったら実装もする | |
// newしても使える、継承しても使える、staticでも使えるの3タイプを一気に提供する | |
class Array extends \ArrayObject { | |
private $source; | |
// ただのarray, ArrayObject, ArrayAccessインタフェースを考慮しタイプヒント無し | |
public function __construct(array $source) { | |
$this->source = $source; | |
} | |
public static function __callStatic($name, array $args) { | |
$source = $args[0]; | |
$args = array_slice($args, 1); | |
$instance = new static(array $source); | |
return call_user_func_array(array($instance, $name), $args); | |
} | |
} |
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 | |
class CallCounter { | |
private $target; | |
private $counts = array(); | |
public static function stub(&$target) | |
{ | |
new self($target); | |
} | |
public function __construct(&$target) | |
{ | |
$this->target = $target; | |
$target = $this; | |
} | |
public function __call($method, $args) | |
{ | |
if(!isset($this->counts[$method])) { | |
$this->counts[$method] = 0; | |
} | |
$this->counts[$method]++; | |
return call_user_func_array(array($this->target, $method), $args); | |
} | |
public function calledOnce($method) | |
{ | |
return ($this->counts[$method] === 1); | |
} | |
} | |
// class A { | |
// public function hoge() | |
// { | |
// return 1; | |
// } | |
// } | |
// $a = new A(); | |
// $c = new CallCounter($a); | |
// var_dump($a->hoge()); | |
// var_dump($c->calledOnce('hoge')); |
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 | |
/** | |
* PHPの配列をOOPぽく扱えるクラス | |
*/ | |
class Collection extends ArrayObject | |
{ | |
private $raw; | |
public function __construct(array $list) | |
{ | |
$this->raw = $list; | |
} | |
public function getIterator() | |
{ | |
$class = $this->getIteratorClass(); | |
return new $class($this->raw); | |
} | |
// 自前で実装すればそれを使う | |
public function sort($sort_flags = SORT_REGULAR) | |
{ | |
sort($this->raw, $sort_flags); | |
return new static($this->raw); | |
} | |
// でなければ標準関数を探しに行く | |
public function __call($method, array $args) | |
{ | |
if (method_exists($this->raw, $method)) { | |
$method = [$this->raw, $method]; | |
} elseif (!function_exists($method)) { | |
$method = 'array_'.self::toSnakeCase($method); | |
array_unshift($args, $this->raw); | |
if (!function_exists($method)) { | |
throw new InvalidArgumentException("Undefined method {$method}"); | |
} | |
} | |
if (in_array($method, self::$referenceExpects)) { | |
call_user_func_array($method, $args); | |
return new static($this->raw); | |
} else { | |
return new static(call_user_func_array($method, $args)); | |
} | |
} | |
private function toSnakeCase($str) | |
{ | |
$result = ''; | |
for ($i = 0; $i < strlen($str); $i++) { | |
if (ctype_upper($str[$i])) { | |
$str[$i] = '_'.strtolower($str[$i]); | |
} | |
$result .= $str[$i]; | |
} | |
return $result; | |
} | |
} | |
// Usage | |
// $list = new Collection([3, 2, 1, 1, 2, 3]); | |
// echo "count:{$list->count()}\n"; | |
// echo "uniqued count:{$list->unique()->count()}\n"; | |
// echo "\n"; | |
// foreach ($list->unique()->sort() as $i => $num) { | |
// echo "{$i} => {$num}(unique + sort)\n"; | |
// } | |
// echo "\n"; | |
// foreach ($list->unique()->sort()->reverse() as $i => $num) { | |
// echo "{$i} => {$num}(unique + sort + reverse)\n"; | |
// } |
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 | |
// (PHP 4 >= 4.1.0, PHP 5, PHP 7) | |
// cal_days_in_month — 指定した年とカレンダーについて、月の日数を返す | |
// http://php.net/manual/ja/function.cal-days-in-month.php | |
// | |
// > 年と月の順序に注意 | |
// 年と月の順序に注意 | |
cal_days_in_month(CAL_GREGORIAN, $month, $year); | |
// カレンダー定数 | |
// http://php.net/manual/ja/calendar.constants.php | |
// MySQLのタイムゾーンの設定を確認する | |
// SELECT @@global.system_time_zone, @@global.time_zone, @@session.time_zone; | |
// (PHP 5 >= 5.2.0, PHP 7) | |
// DateTimeZone::listIdentifiers -- timezone_identifiers_list — すべてのタイムゾーン識別子を含む配列を返す | |
// http://php.net/manual/ja/datetimezone.listidentifiers.php | |
$timezones = DateTimeZone::listIdentifiers(); | |
// UTC時刻をJST時刻へ変換する | |
// php.iniのdate.timezoneを変えてしまうとシステム全体の時刻に影響してしまう。 | |
// そうではなくDB上はUTCにしておき、取り出して表示するときにオフセットを噛ませたい。 | |
// | |
// (PHP 5 >= 5.2.0, PHP 7) | |
// DateTimeZone::__construct -- timezone_open — 新しい DateTimeZone オブジェクトを作成する | |
// http://php.net/manual/ja/datetimezone.construct.php | |
// 指定したタイムゾーンが無効な形式だった場合に Exception をスローします。 | |
$zone = new DateTimeZone('Asia/Tokyo'); // この名前なりIDなりをDBに持っておいて渡す | |
// (PHP 5 >= 5.2.0, PHP 7) | |
// DateTime::__construct -- date_create — 新しい DateTime オブジェクトを返す | |
// http://php.net/manual/ja/datetime.construct.php | |
$datetime = new DateTime('now', $zone); | |
// (PHP 5 >= 5.3.0, PHP 7) | |
// DateTimeZone::getLocation -- timezone_location_get — タイムゾーンの位置情報を返す | |
// http://php.net/manual/ja/datetimezone.getlocation.php | |
// > Array | |
// > ( | |
// > [country_code] => JP | |
// > [latitude] => 35.65444 | |
// > [longitude] => 139.74472 | |
// > [comments] => | |
// > ) | |
$zone->getLocation(); | |
// (PHP 4, PHP 5, PHP 7) | |
// checkdate — グレゴリオ暦の日付/時刻の妥当性を確認します | |
// http://php.net/manual/ja/function.checkdate.php | |
checkdate ( int $month , int $day , int $year ) |
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 | |
// ファイル操作の便利クラス | |
// PHP5.1でもSplFileInfoは存在するが、一部欠けているメソッドがある。 | |
// [#getLinkTarget](http://php.net/manual/ja/splfileinfo.getlinktarget.php)は必要性が無いので未実装。 | |
class File extends SplFileInfo { | |
/** | |
* @see http://php.net/manual/ja/function.file-exists.php | |
*/ | |
public static function exists($filename) | |
{ | |
return file_exists($filename); | |
} | |
/** | |
* @see http://php.net/manual/ja/function.glob.php | |
*/ | |
public static function glob($pattern, $flags = 0) | |
{ | |
return glob($pattern, $flags); | |
} | |
/** | |
* @see http://php.net/manual/ja/function.copy.php | |
*/ | |
public function copy($dest, $context = null) | |
{ | |
// デフォ値の記載がないためcontextが省略された場合引数を渡さないようにしている | |
if(is_resource($context)) { | |
return copy($this->getRealPath(), $dest, $context); | |
} else { | |
return copy($this->getRealPath(), $dest); | |
} | |
} | |
/** | |
* @see http://php.net/manual/ja/function.rename.php | |
*/ | |
public function rename($newname, $context = null) | |
{ | |
// デフォ値の記載がないためcontextが省略された場合引数を渡さないようにしている | |
if(is_resource($context)) { | |
return rename($this->getRealPath(), $newname, $context); | |
} else { | |
return rename($this->getRealPath(), $newname); | |
} | |
} | |
/** | |
* @see http://php.net/manual/ja/function.unlink.php | |
*/ | |
public function remove() | |
{ | |
return unlink($this->getRealPath()); | |
} | |
/** | |
* @see http://php.net/manual/ja/splfileinfo.getextension.php | |
*/ | |
public function getExtension() | |
{ | |
return pathinfo($this->getRealPath(), PATHINFO_EXTENSION); | |
} | |
/** | |
* @see http://php.net/manual/ja/splfileinfo.getrealpath.php | |
* @see http://php.net/manual/ja/function.realpath.php | |
*/ | |
public function getRealPath() | |
{ | |
return realpath($this->getPath().DIRECTORY_SEPARATOR.$this->getFilename()); | |
} | |
} |
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 | |
// こわくない関数型のスライドを思い出して | |
function picker($key) { | |
return function($item) use ($key) { | |
return is_array($item) ? $item[$key] : $item->{$key}; | |
}; | |
} | |
// メソッド名と引数を渡し、受け取ったオブジェクトのメソッドをコールする関数を返す関数 | |
function invoker($method, array $args = []) { | |
return function($obj) use ($method, $args) { | |
return call_user_func_array([$obj, $method], $args); | |
}; | |
} | |
// callableな配列を受け取り、各要素を用いてarray_reduceを実行する関数 | |
function reducer(array $funcs) { | |
return function(...$initial) use ($funcs) { | |
return array_reduce($funcs, function($current, callable $fn) { | |
return call_user_func_array($fn, is_array($current) ? $current : [$current]); | |
}, $initial); | |
}; | |
} |
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 | |
// マルチバイト、文字列操作関連の便利クラス | |
// マジックナンバーホイホイ。どうにかしたい | |
// http://php.net/manual/ja/function.mb-convert-kana.php |
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 | |
// 格子状の2次元配列を扱うためのクラス | |
// CSVなどのテーブル上のデータにも有用 | |
class Matrix implements Iterator { | |
private $y = 0; | |
private $matrix; | |
// Traversableインタフェースと共存するためarrayタイプヒントは付けない | |
public function __construct($matrix) | |
{ | |
$this->matrix = $matrix; | |
} | |
public function width() | |
{ | |
if($this->has(0, 0)) { | |
return count($this->matrix[0]); | |
} else { | |
return 0; | |
} | |
} | |
public function height() | |
{ | |
return count($this->matrix); | |
} | |
// x, yの順にしてしまうと実際の添字アクセスのときと逆になりイメージしにくいのでy, xの順にする | |
public function get($y, $x, $default = null) | |
{ | |
if($this->has($y, $x)) { | |
return $this->matrix[$y][$x]; | |
} else { | |
return $default; | |
} | |
} | |
public function set($y, $x, $value) | |
{ | |
if(!isset($this->matrix[$y])) { | |
$this->matrix[$y] = array(); | |
} | |
$this->matrix[$y][$x] = $value; | |
} | |
public function has($y, $x) | |
{ | |
return isset($this->matrix[$y][$x]); | |
} | |
public function toAssoc(array $mapping_keys) | |
{ | |
$results = array(); | |
foreach($this->matrix as $row) { | |
$results[] = array_combine($mapping_keys, $row); | |
} | |
return $results; | |
} | |
// -> mixed | |
public function current() | |
{ | |
return $this->matrix[$this->y]; | |
} | |
// -> scalar | |
public function key() | |
{ | |
return $this->y; | |
} | |
// -> void | |
public function next() | |
{ | |
$this->y++; | |
} | |
// -> void | |
public function rewind() | |
{ | |
$this->y = 0; | |
} | |
// -> boolean | |
public function valid() | |
{ | |
return ($this->y < $this->height()); | |
} | |
} | |
// ## Example | |
// ```php | |
// $m = new Matrix([ | |
// [1,2,3], | |
// [4,5,6], | |
// [7,8,9], | |
// ]); | |
// | |
// foreach($m as $row) { | |
// foreach($row as $cell) { | |
// var_dump($cell); | |
// } | |
// } | |
// ``` |
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 | |
/** | |
* mixin的なもの | |
* | |
* わざわざ各クラスにプロキシ用の__callメソッドを定義する必要がなくなる | |
*/ | |
class Proxy | |
{ | |
private $source; | |
private $targets; | |
public function __construct() | |
{ | |
$this->targets = func_get_args(); | |
} | |
public function __call($method, array $args = []) | |
{ | |
foreach ($this->targets as $target) | |
{ | |
if (!method_exists($target, $method)) continue; | |
return call_user_func_array([$target, $method], $args); | |
} | |
throw new InvalidArgumentException("Undefined method: {$method}"); | |
} | |
} | |
class B { | |
public function foo() { return __FUNCTION__; } | |
} | |
class A { | |
public function hoge() { return __FUNCTION__; } | |
} | |
// Usage | |
// $proxy = new Proxy(new A, new B); | |
// var_dump($proxy->hoge()); | |
// var_dump($proxy->foo()); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment