CodeIgniter3 CLI利用時の引数の挙動

PHPのフレームワークの1つであるCodeIgniter3、今年はPHPでバッチ処理を作る際にCLI機能を利用しました。その時のTIPSです。時は過ぎた気がしますが空いていたので CodeIgniter Advent Calendar 2017 22日目記事に登録しました。

CodeIgniter CLI 機能

CLIとはcommand-line interfaceの略で、ターミナルからCodeIgniterの機能を呼び出します。

実装は簡単で、Controllerを書いて、index.php をConsoleから起動します。

<?php
defined( 'BASEPATH' ) OR exit('No direct script access allowed');

class Tools extends CI_Controller {

public function echoparam($param1='',$param2='')
{
echo "param1={$param1}".PHP_EOL;
echo "param2={$param2}".PHP_EOL;
}
}
$ php index.php tools echoparam apple orange
param1=apple
param2=orange

これでTools コントローラーのメソッド message が起動されます。 
あとは動作させたい処理をCodeIgniterの機能を利用して記述できます。便利です。

引数の挙動の注意点

しかし、この引数には少しクセがあります。例えばURLを渡すと

$ php index.php tools echoparam https://google.com/
param1=https:
param2=google.com

引数に渡したURLが分割されてしまいました

どうしてこうなるのか

CodeIgniterはWebで利用されるときにURLでルーティング処理しています。

例えば、このURLを起動すると、productsコントローラーのshoesメソッドにsandals 123のパラメータが渡ります。

example.com/index.php/products/shoes/sandals/123
<?php
class Products extends CI_Controller {

public function shoes($sandals, $id)
{
echo $sandals;
echo $id;
}
}

CLIで動く場合にもこの挙動のため、 URI中の/でパラメータを分割してしまいます。

CLIでURL引数を渡す方法

ではURLのような文字列を引数に指定するにはどうすればよいでしょうか。

  • 方法1 引数URLエンコードして渡す
$ php index.php tools echoparam https%3a%2f%2fgoogle%2ecom%2f
param1=https%3a%2f%2fgoogle%2ecom%2f
param2=

このように分割されずに値が渡ります。
あとはURLデコードして利用すれば良いです。しかし、いちいち引数をURLエンコードして指定するのは大変です。

・方法2 コントローラーで $_SERVER["argv"] を使う

class Tools extends CI_Controller {

public function echoparam()
{
$argv = $_SERVER["argv"];
$param1 =$argv[3];

echo "param1={$param1}".PHP_EOL;
}
$ php index.php tools echoparam https://google.com/
param1=https://google.com/

PHPの$_SERVER にはCLI実行時にはargc 、argvがセットされるのでそれを利用します。

$_SERVER["argv"]には次の情報が入っていて、$argv[3]以降に引数が入っています。

Array
(
[0] => index.php
[1] => tools
[2] => echoparam
[3] => https://google.com/
)
‘argv’
スクリプトに渡された引数の配列です。スクリプトがコマンドラインから 実行された場合、C 言語スタイルでコマンドライン引数に アクセスすることができます。GET メソッドを通してコールされた場合には 検索引数が格納されます。
‘argc’
スクリプトに渡されたコマンドライン引数の数 (コマンドラインから実行した場合) です。
PHP: $_SERVER — Manual

気がつけば最初からそうすればよかったという内容ですが...しばらく気が付きませんでした。

来年もよいCodeIgniterライフをどうぞ。