【PHP】scalar_object を使って値からメソッドを使えるようにする。phpenv環境、Laravelで使えるようにした。
Ruby だと組み込み型を拡張してメソッド追加できるんだけど、PHPでもそんなことがしたかった。調べてみたら下記があった。
PHP の「文字列」や「配列」などの基本的な値型にメソッドを生やして使えるようにするという試み。
以下が手順です、phpenv に導入しました。
$ cd ~/.phpenv/src/
$ git clone https://github.com/nikic/scalar_objects.git
$ cd scalar_objects
$ phpize && ./configure && make && make install
$ vi ~/path/to/各バージョン/php.ini
+ extension=scalar_objects.so
終了。
早速試した。ちなみにphp7 です。
<?php class ArrayExtension { public function specifiedNextKey($self, $key) { $tmp=false; foreach($self as $k => $v){ if($k == $key){ $tmp=$k; }elseif($tmp !== false){ return $k; } } return false; } public function hoge($self) { var_dump($self); } public function getFirstKey($self){ reset($self); return key($self); } public function sortArrayByKey($self, $sortKey, $sortType = SORT_ASC ) { $tmpArray = []; foreach ( $self as $key => $row ) { $tmpArray[$key] = $row[$sortKey]; } array_multisort( $tmpArray, $sortType, $self ); return $self; } } register_primitive_type_handler('array', 'ArrayExtension'); $a = ['hello' => 'val1', 'fuga' => 'val2']->specifiedNextKey('hello'); var_dump($a); $a = ['hello' => 'val', 'Hoge' => 'val2', 'aiueo' => 'val3']->getFirstKey(); var_dump($a); $tajigen = [ ['seiseki' => 50, 'syukketu' => 1], ['seiseki' => 30, 'syukketu' => 3], ['seiseki' => 20, 'syukketu' => 5], ['seiseki' => 10, 'syukketu' => 19], ['seiseki' => 70, 'syukketu' => 1], ]; $a = $tajigen->sortArrayByKey('syukketu'); var_dump($a);
/home/vagrant/php/scalar_objects/mytest.php:45: string(4) "fuga" /home/vagrant/php/scalar_objects/mytest.php:49: string(5) "hello" /home/vagrant/php/scalar_objects/mytest.php:61: array(5) { [0] => array(2) { 'seiseki' => int(50) 'syukketu' => int(1) } [1] => array(2) { 'seiseki' => int(70) 'syukketu' => int(1) } [2] => array(2) { 'seiseki' => int(30) 'syukketu' => int(3) } [3] => array(2) { 'seiseki' => int(20) 'syukketu' => int(5) } [4] => array(2) { 'seiseki' => int(10) 'syukketu' => int(19) } }
いいね。。。
さっそくグローバル関数になってる関数を各値のメソッドに移植してみた。
Laravel 5 で使えるようにしたかったので、app
のしたに Extensions
ディレクトリを作って
<?php namespace App\Extensions; class StringExtension { public function mbTrim($self) { static $chars = "[\\x0-\x20\x7f\xc2\xa0\xe3\x80\x80]"; return preg_replace("/\A{$chars}++|{$chars}++\z/u", '', $self); } public function removeHttpProto($self) { return preg_replace('/http[s]*:\/\/(.*?)\//', '', $self); } public function underscore($self) { return ltrim(strtolower(preg_replace('/[A-Z]/', '_\0', $self)) , '_'); } public function camelize($self) { return lcfirst(strtr(ucwords(strtr($self, ['_' => ' '])) , [' ' => ''])); } }
を作った。
それで app/Providers/AppServiceProvider.php
に
public function boot() { // register_primitive_type_handler('string', 'App\Extensions\StringExtension'); }
とした。
Command を適当に作ってみて試してみる。
public function handle()
{
//
dd('HogeClass'->underscore());
}
$ php artisan hogehoge
"hoge_class"
いい感じです。