忍者ブログ

STEP UP BLOG

Home > ブログ > php

[PR]

×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

既存PHPに後から拡張モジュールをインストールする

既にインストールされているPHPに後から拡張モジュールを追加しないといけない場合があると思います。
そのようなときの拡張モジュールのインストール手順です。
今回は例としてzipモジュールをインストールします。
PHPを新しくインストールするときならば--enable-zipをconfigureオプションとして指定すればいいのですが、この場合既にPHPはインストールされているのでそうもいきません。
尚、PHPをソースコードからコンパイル、インストールした場合で、HTTPサーバはApacheです。
$ cd /usr/local/src/php-5.x.xx/ext/zip

PHPソースコードのディレクトリにはextという拡張モジュールのソースコードが入っているディレクトリがあるので、extの中の該当するモジュールのディレクトリに移動します。
$ sudo /usr/local/bin/phpize
$ sudo ./configure --with-php-config=/usr/local/bin/php-config
$ sudo make
$ sudo make test
$ sudo make install
$ sudo vi /usr/local/lib/php.ini
+ extension=zip.so
$ sudo service httpd restart
$ php -i | grep zip
Registered PHP Streams => compress.zlib, php, file, glob, data, http, ftp, zip, phar  
gzip compression => enabled
bzip2 compression => disabled (install pecl/bz2)
zip
Libzip version => 0.10.1

以上となります。
configureでphp-configのエラーが出る場合は--with-php-configでphp-configのパスを指定してあげます。
簡単ですね。
という感じで気軽にモジュールは追加していったらいいと思います(外す場合はphp.iniのextension記述を削除すればいいので)。
PR

PsySHでPHPのREPL

RubyやPythonなどと同様にPHPにもREPLがあります。
それがPshSHです。
REPLとは"Read Eval Print Loop"の略で対話型の実行環境を指します。

http://psysh.org/

ありがたいことに最新のLaravel5.3では自動でインストールされます。
入ってなくてもcomposerを使えば簡単にインストールできます。
$ composer require psy/psysh:@stable

まずは起動してみます。
$ ./vendor/psy/psysh/bin/psysh 
Psy Shell v0.8.0 (PHP 7.1.0 — cli) by Justin Hileman
>>> help
  help       Show a list of commands. Type `help [foo]` for information about [foo].      Aliases: ?                     
  ls         List local, instance or class variables, methods and constants.              Aliases: list, dir             
  dump       Dump an object or primitive.                                                                                
  doc        Read the documentation for an object, class, constant, method or property.   Aliases: rtfm, man             
  show       Show the code for an object, class, constant, method or property.                                           
  wtf        Show the backtrace of the most recent exception.                             Aliases: last-exception, wtf?  
  whereami   Show where you are in the code.                                                                             
  throw-up   Throw an exception out of the Psy Shell.                                                                    
  trace      Show the current call stack.                                                                                
  buffer     Show (or clear) the contents of the code input buffer.                       Aliases: buf                   
  clear      Clear the Psy Shell screen.                                                                                 
  history    Show the Psy Shell history.                                                  Aliases: hist                  
  exit       End the current session and return to caller.                                Aliases: quit, q               
>>> 

>> $arr = [1,2,3];
=> [
     1,
     2,
     3,
   ]
>>> 1 + 2;
=> 3
>>> function square($x) {
... return $x*$x*$x;
... }
=> null
>>> square(4);
=> 64

というようにインタラクティブにPHPを実行できます。
試してみてはいかがでしょうか。
それではよいお年を。

privateの罠

最近ハマった挙動について書きます。
コードを見たほうが早いので以下にコード。
<?php

class ClassA
{
    private $member_variable = 'A';

    public function getMemberVariable()
    {
        return $this->member_variable;
    }
}

class ClassB extends ClassA
{
    private $member_variable = 'B';

    public function getMemberVariable()
    {
        return $this->member_variable;
    }
}

class ClassC extends ClassA
{
    private $member_variable = 'C';
}

$a = new ClassA();
$b = new ClassB();
$c = new ClassC();

echo $a->getMemberVariable()."\n";
echo $b->getMemberVariable()."\n";
echo $c->getMemberVariable()."\n";

$ php test.php 
A
B
A

$c->getMemberVariable()で"C"が返ってくると思ったら"A"でした。。
"C"を返すには以下のようにprivateをprotectedに変えるとできます。
<?php

class ClassA
{
    protected $member_variable = 'A';

    public function getMemberVariable()
    {
        return $this->member_variable;
    }
}

class ClassB extends ClassA
{
    protected $member_variable = 'B';

    public function getMemberVariable()
    {
        return $this->member_variable;
    }
}

class ClassC extends ClassA
{
    protected $member_variable = 'C';
}

$a = new ClassA();
$b = new ClassB();
$c = new ClassC();

echo $a->getMemberVariable()."\n";
echo $b->getMemberVariable()."\n";
echo $c->getMemberVariable()."\n";

$ php test.php 
A
B
C

子クラスから親クラスのメソッドを呼んで、そのメソッド内でprivate変数を呼ぶと親のprivate変数になるんですね。
理屈がわかればなるほどなんですが、どこがおかしいのか見つけるのが意外と難しかったです。。

PHPに日付処理における来月の挙動

このバグを直すためにはどうしたらよいかなーと検索をかけて、
出てきた検索結果一覧に既にアクセス済みのリンクがあったら凹みますよね…
あれ? 私昔も同じ間違いしてた??
全然学習してないじゃない…
そんな過去の失敗をまた繰り返すがっかり事案が今日もあったのでここで書かせていただきます。


PHPで来月を取得する必要があったのですが、そのときの処理をわかりやすく書き直したのが以下です。
$ php -r "echo date('m', strtotime('+1 month'));"
05

今日3月31日だよ? 来月4月だよ?
4月31日がないから5月1日になってしまうようです。
同様に1月や5月,8月,10月でも31日だと正しい来月が取得できません。
これは致命的ですよねと思いながらCarbonでも同じ処理を試してみたら、
$dt = new Carbon('next month');
echo $dt->format('m');  // 05

Carbonおまえもか…
PHPどうしようもないなと泣きながら調べて出てきた修正案は、
$dt = date('m', strtotime(date('Y-m-1').' +1 month'));
echo $dt;  // 04

$dt = new Carbon('first day of next month');
echo $dt->format('m');  // 04

$dt = new DateTime('first day of next month');
echo $dt->format('m');  // 04

"first day of"というのが肝要です。
日付処理は難しいですね…

マルチバイト文字対応のwordwrap()

PHPの文字列関数にはかゆいところに手が届く便利な関数が多々あります。
しかし!!
そういう便利な関数(言いようによっては使い道が限定される関数)に限ってマルチバイト文字対応していない。。。
ということで、結局自作しなければならないわけですが、
先日初めて知った関数にwordwrap()という関数がありました。

http://php.net/manual/ja/function.wordwrap.php

指定した文字数で、指定した文字を用いて文字列を分割します。

その通りなのですが、具体例を挙げると、
改行の入っていない長文を100文字ずつに分割して、それぞれに改行文字を追加するというようなことが可能なわけです。
さらに、そもそものPHPがHTMLを出力するための言語として生まれた性質からか、
分割する際に、単語を分割するかどうかも設定できます。
その辺りはマニュアルを参照していただくとわかると思います。

で、こちらのwordwrap()はご想像通り、マルチバイト文字に対応していない。
で、いろんな人が自作mb_wordwrap()を作っていたので、
私も便乗して作ってみました。
しかし、単語を分割するかしないかの判別まで含めると途端に難易度がエベレスト並になるのでそこは含めません。
function mb_wordwrap($string, $width, $break)
{
    $result = [];
    $tmp_str = '';
    $i = 0;
    while (mb_strlen($tmp_str) < mb_strlen($string)) {
        $str = mb_substr($string, $i*$width, $width);
        $result[] = $str;
        $tmp_str .= $str;
        $i++;
    }

    return implode($break, $result);
}

改良余地というか、wordwrap()の仕様漏れがありそうで不安ですが。。。

PAGE TOP