[PHP]googleanalytics.class.phpは10個しかメトリクスを指定できない

さて、Google Analytics APIのクラスライブラリとしてgoogleanalytics.class.phpがあります。

まとめてデータを取得できるところが非常に便利なのですが
データ取得時に下記のようなエラーメッセージが出ることがあります。

エラーメッセージ
「Error: Bad request – Requested 11 metrics; only 10 are allowed.」

なんと、取得するときにメトリクスは10個までしか受け付けてもらえません。
たくさんコンバージョン(目的)の設定をしている場合は注意が必要です。

エラーが起こる記述

require_once 'googleanalytics.class.php';
$ga_id = 'AAA';	//Google Analytics ID
$ga_pass = 'BBB';	//Google Analytics パスワード
$ga_profile_id = 'ga:XXXXXXXX';	//プロファイルID
$metrics = '';
$metrics .= 'ga:visitors,';
$metrics .= 'ga:exits,';
$metrics .= 'ga:goal1Completions,';
$metrics .= 'ga:goal2Completions,';
$metrics .= 'ga:goal3Completions,';
$metrics .= 'ga:goal4Completions,';
$metrics .= 'ga:goal5Completions,';
$metrics .= 'ga:goal6Completions,';
$metrics .= 'ga:goal7Completions,';
$metrics .= 'ga:goal8Completions,';
$metrics .= 'ga:goalCompletionsAll';
try{
$ga = new GoogleAnalytics($ga_id , $ga_pass);
$ga->setProfile($ga_profile_id);
$ga->setDateRange('2012-06-01' , '2012-06-30');
$report = $ga->getReport(
array(
'dimensions' => urlencode('ga:date'),
'metrics'    => urlencode($metrics),
'sort'       => 'ga:date'
)
);
print_r($report);
} catch (Exception $e) {
print 'Error: ' . $e->getMessage();
}

とは言え、必要なデータはやはり取らないといけません。
こうなったら2回getReportを投げて戻り値の配列をマージしてみます。

require_once 'googleanalytics.class.php';
$$ga_id = '<Google Analytics ID>';
$ga_pass = '<Google Analytics パスワード>';
$ga_profile_id = 'ga:XXXXXXXX';	//プロファイルID
$metrics = '';
$metrics .= 'ga:visitors,';
$metrics .= 'ga:exits,';
$metrics .= 'ga:goal1Completions,';
$metrics .= 'ga:goal2Completions,';
$metrics .= 'ga:goal3Completions,';
$metrics .= 'ga:goal4Completions,';
$metrics .= 'ga:goal5Completions,';
$metrics .= 'ga:goal6Completions,';
$metrics .= 'ga:goal7Completions,';
$metrics .= 'ga:goal8Completions,';
$metrics .= 'ga:goalCompletionsAll';
try{
$ga = new GoogleAnalytics($ga_id , $ga_pass);
$ga->setProfile($ga_profile_id);
$ga->setDateRange('2012-06-01' , '2012-06-30');
$metrics_arr = explode(',', $metrics);	//メトリクスを配列化
$step_total = ceil(count($metrics_arr) / 10);
for($step = 0; $step < $step_total; $step++){
//10個ずつmetricsを抽出
$report_metrics = implode(',', array_slice($metrics_arr, $step * 10, 10));
$report_wrk = $ga->getReport(
array(
'dimensions' => urlencode('ga:date'),
'metrics'    => urlencode($report_metrics),
'sort'       => 'ga:date'
)
);
//初回は代入のみ
if($step == 0){
$report = $report_wrk;
continue;
}
//2回目移行は配列をマージ
foreach ($report_wrk as $wrk_idx => $ga_ret) {
$report[$wrk_idx] = array_merge($report[$wrk_idx], $report_wrk[$wrk_idx]);
}
}
print_r($report);
} catch (Exception $e) {
print 'Error: ' . $e->getMessage();
}

なんだか、カッコ悪い感じもしますが、GoogleAnalyticsのオブジェクト化を
1回だけにしておくのがポイントです。
このオブジェクトを作成するだけで僕の環境では2~3秒かかってました;

※ご注意
掲載している内容についてはご自身の責任で参考にされてください。

[PHP]バッチ処理 後編[バッチファイル作成&設置]

さて、バッチ開発後編です。
まずは、ファイルの絶対パスを一応確認しましょう。
PHPファイルを作成し、batchディレクトリにアップロードします。
batch_test.php 新規作成

print(__FILE__).PHP_EOL;

次に、TeraTermとかでバッチを置くディレクトリに移動
cd batch
実行
php batch_test.php
実行結果
/var/www/vhosts/<ドメイン名>/batch/batch_test.php
これが今回製作したバッチファイルの絶対パスになります。
次にbatch_test.phpを書き換えます。
適当なテーブル(t_batch_test)を一個DBに作成し、
INSERTするようにします。
batch_test.php 書き換え

$host = '<ホスト名>';
$user = '';
$pass = '';
$dbname = '';
try {
$dbh = new PDO('mysql:host='.$host.';dbname='.$dbname, $user, $pass);
$sql = "insert into t_batch_test (test) values ('from batch')";
$stmt = $dbh->prepare($sql);
$flag = $stmt->execute();
if ($flag){
print('success').PHP_EOL;
}else{
print('failed').PHP_EOL;
}
$dbh = null;
} catch (PDOException $e) {
print($e->getMessage());
die('error!!!').PHP_EOL;
}

再度、アップロードしてファイルを上書きした後
コマンドから実行
実行
php batch_test.php
表示結果で「success」と出れば、PHPの記述は問題ありません。
次はcronの設定です。
cronについて僕はレンタルサーバの業者から提供されている
管理者パネルで設定しましたが、そういうツールがない場合は
viあたりのエディタでcron設定ファイルを編集できます。
詳細な設定方法についてはここでは割愛します。
設定時にコマンドを下記のように設定します
コマンド
php /var/www/vhosts/<ドメイン名>/batch/batch_test.php
cronで指定した時刻に追加がされていれば完了です。
実行方法は他にPHPのsystem関数を使う手もあります。

※ご注意
掲載している内容についてはご自身の責任で参考にされてください。

[PHP]バッチ処理 前編[設置ディレクトリの準備]

windowsのシステムでバッチ処理をする場合、batファイルや
VBなんかで作ったexeなどをタスクマネージャみたいな
スケジューラでキックするのは常套手段だと思う。
じゃあ、linuxでPHPやらが動いている環境がある場合
どういう方法があるのかということでチャレンジしてみた。
今回は手持ちのレンタルLinuxサーバでバッチ処理をする方法を考える。
言語はPHPで、このPHPを起動するのはcron(クーロン)を使う。
なぜPHPかというと、既にWEBアプリで既に作った部品を流用できるから。
特にDBまわりのモジュールをもう一回Javaとかで作る気にならなかった。。。
cronはwindowsで言うところのタスクマネージャみたいなもの。
サーバ側で提供されていたコントロールパネルから設定できた。
対応しているかはレンタルサーバの会社とサービス内容にもよる。
バッチの場所は僕のサーバの環境では特に用意されていなかったので
ルートの(httpdocsと同じ)階層に新しくディレクトリを作成して
パーミッションを700で設定した。
※httpのルートに置くとブラウザでアクセスされる危険性があるので、もちろんやらない。
○手順
・httpdocsと同じ階層にいるか確認
・バッチ用ディレクトリ作成
 mkdir <ディレクトリ名>
 mkdir batch
・パーミッション変更
 chmod <属性値> <ディレクトリ名>
 chmod 700 batch
・所有者とアクセス権を確認
 ls -l
 表示結果:
 drwx—— 2 root root 4096 Jun 25 14:11 batch
アップロードを考慮してユーザ名(左から一番最初のrootの位置)がftpのユーザと
違った場合はユーザ名を合わせる。
・所有者の変更
 chown <ユーザ名> batch
次回はバッチファイル作成と設置です。

※注意
掲載している内容についてはご自身の責任で参考にされてください。

[FFFTP]mkdirで作ったディレクトリにアクセスできない

FFFTPを使ってコンテンツをアップロードする際に
「no such file or directory」となる。
と、こんな問い合わせがあった。
こういった場合、権限の問題を考える必要がある。
要は、このディレクトリを誰が作ったか、どんな人にアクセスを許しているか
ということ。
よくあるのが、TeraTermみたいなターミナルエミュレーターでログイン後、
suコマンドからroot権限でディレクトリを作って、そこにFFFTPでアクセスする場合。
その時は、ディレクトリの所有者とFFFTPでつなぐユーザ名を合わせる必要がある。
○所有者とアクセス権を確認
ls -l
○所有者の変更
chown <ユーザ名> <ディレクトリ名>
とりあえず、解決。

※注意
ご自身の責任でご参考にされてください。
ところどころ端折っているので、コマンドの実行にはリファレンス等を確認してください。

[XAMPP]php.iniでextensionを有効にしても反映されない場合の意外な可能性

ある学生からXAMPPでPHPを使ってて下記エラーがどうしても消えないと
いうことで質問をされました。
Fatal error: Call to undefined function curl_init()
まず、php.iniファイルの下記項目のコメント「;」を外して上書き
extension=php_curl.dll
その後、apacheを再起動するように指示しました。
瞬殺だろうと思ったのですが、うまくいかないらしいです。
おかしいなと思って、libeay32.dll、ssleay32.dll
の存在確認や環境変数Pathが通っているかも確認するも
すべて正常。。。
おかしいなと思っていたのですが、ふと
phpinfo()を使ってConfiguration File (php.ini) Path を確認
してもらって、納得しました。
phpinfoには「xampp\apache\bin」がphp.iniのパスとして
表示されてましたが、彼はこれまで「xampp\php」にあるphp.iniを
編集していたらしいです。
ああ、なるほどねぇ。。。
結構ひっかかる人いるかもね、これ。

[XAMPP]Apacheが停止、再起動できない

掲題の件で困っている人がいたので確認してみました。
とりあえず、XAMPPコントロールパネルを一度終了したのち
「管理者として実行」から起動すると動きました。
XPにどっぷりだとVistaや7で、こんな問題にぶちあたったりしますね。。。

[MySQL]トランザクションが効かない?

掲題の件で困っている人がいたので、見てみたら
フィールドタイプが「MyISAM」になってました。
とりあえず、「InnoDB」に変更して解決。
○MyISAM
・readが早い
○InnoDB
・トランザクションや外部キー制約可
とりあえず、一長一短ありますが、用途に合わせてどちらかを選ぶ感じですな。
更新が多くあって、読みこみスピードが気にならなければとりあえずInnoDBにしとく感じかな。

[PHP]PDO: bindParamで日付型(datetime)をバインドするとき

bindParamは型を自動で判定をしないから、第3引数に定義済み定数で型指定をしないといけない。
・PDO定義済み定数
http://php.net/manual/ja/pdo.constants.php
でも、定数の中にdatetime型など日付型に関する定数が見つかりません。
とりあえず、PDO::PARAM_STRをしていした上で、STR_TO_DATE関数をSQLに与えてみました。

$fld_date = date("Y/m/d H:i:s");
$sql = "";
$sql .= " SELECT * FROM t_track ";
//$sql .= " WHERE fld_date = :fld_date ";
$sql .= " WHERE fld_date = STR_TO_DATE(:fld_date ,'%Y/%m/%d %H:%i:%s') ";
$sth = $dbh->prepare($sql);
$sth->bindParam(':fld_date', $fld_date, PDO::PARAM_STR);
$sth->execute();

※注意
掲載している内容についてはご自身の責任で参考にされてください。

[PHP]PDO:windowsからlinuxにアップロードすると、bindParamでうまくバインドされない場合

掲題の問い合わせがあったので、調査してみました。
○症状
・windowsからlinuxにアップロードすると、bindParamがうまくバインドされてない
・windows環境では動いていた
・bindParamはtrueを返している
・bindParamを使わずにSQL文を直書きすると動く。
○環境
開発言語:PHP 5.1
DB:MySQL 5.0
・windowsでxamppを使用して開発
・PDO使用
・アップロードするサーバはlinux
○対処
bindParamの型指定(第3引数)をする。
例)

$age = 30;
$name = 'tanaka';
$sql = '';
$sql .= 'SELECT * FROM test';
$sql .= ' WHERE age < :age AND name = :name ';
$sth = $dbh->prepare($sql);
$sth->bindParam(':age', $age, PDO::PARAM_INT);
$sth->bindParam(':name', $name, PDO::PARAM_STR, 12);
$sth->execute();

そもそも、PDOStatement::bindParamは自動的に型を判定してはくれないので
プログラマ側が明示的に記す必要があります。
bindParamについて型指定までしないサンプルが初心者向けに多いので、
気づかずにここで悩む方結構いるのかも知れません。
PDO::PARAM_STRの場合、これだけを指定しても動いたりしますが
長さ(第4引数)も一応付けた方がいいでしょう。
bindParamは第3引数のデフォルトはPDO::PARAM_STRになってます。
windowsでなぜ動くのかは不明ですが、多分どこかの設定なのかなぁ。
その他の定数については下記を参照してください。
・PDO定義済み定数
http://php.net/manual/ja/pdo.constants.php
日付型に関しては、また次の機会に
○参考
・PHP: PDOStatement::bindParam – Manual
http://php.net/manual/ja/pdostatement.bindparam.php
※注意
掲載している内容についてはご自身の責任で参考にされてください。