※ パクレゼルヴではWeb開発エンジニアを大募集中!詳細はこちら

Archive

Archive for the ‘PHP’ Category

Google Analytics を携帯から使う

2009/4/28 火曜日 21:49:21

こんばんは。
のびーにょです。

GoogleAnalyticsをケータイから使う

ためのクラス書きました。
探してもfunctionでしかなかったので。
あと、fopen()のタイプしかなかったので。
fopenだと繋がらなかった場合エラー出るんですよね。
なのでfsockopen()でソケット通信を利用。
繋がらなかったらそこで終了。
もしくはimgタグにして画像を読み込ませる感じでも利用できます。
参考にさせていただいたソースはfopenでPHP5で追加されたパラメータ使っています。
別に弊社もPHP5なんでかまわないんですけど、どうせなら4でも動くようにという感じにしておきました。
後色々機能追加しています。

使用サンプル

//クラス読み込み
include_once 'GoogleAnalytics.class.inc';
include_once 'googleAnalytics.conf.inc';
//Google AnalyticsのID
$GAM_id = GOOGLE_ANALYTICS_ID;
//サーバ名(ドメイン)
$domain = $_SERVER['SERVER_NAME'];
//セッションID 携帯では独自に引き継がないとできないので注意
$sess = session_id();
//ユーザ側で通知したい値
$md5_subid = md5('ユーザID等');
//GAMセット
$GAM = new GoogleAnalyticsMobile($GAM_id,$domain,$sess);
$res=$GAM->sendGoogle($md5_subid);
//IMGタグを利用する場合は以下も必要
//echo $res;

以上
googleAnalytics.conf.incには定数の定義があります。
内容は以下

設定例

//GoogleAnalyticsのID
define('GOOGLE_ANALYTICS_ID','UA-XXXXXXX-X');
//imgタグで画像を読ませるかどうか
define('GOOGLE_ANALYTICS_READIMG',FALSE);
//define('GOOGLE_ANALYTICS_READIMG',TRUE);
//ソケット通信で通信する場合のタイムアウトするまでの時間
define('GOOGLE_ANALYTICS_TIMEOUT',5);
//通信ポート
define('GOOGLE_ANALYTICS_SEND_PORT',80);
//GoogleAnalyticsへ通知するURL(変わったら変えてね)
define('GOOGLE_ANALYTICS_HOST','www.google-analytics.com');

設定はお好みでどうぞ。
GoogleAnalytics.class.incの中身は以下です。

GoogleAnalyticsMobile

/**
 * GoogleAnalytics を携帯でも利用するためのクラス
 * @auther のびーにょ
 */
class GoogleAnalyticsMobile {
  var $utmac;   //Google AnalyticsのID
  var $utmhn;   //ドメイン
  var $session;  //クッキー(セッション)
  var $random;  //ランダムな値
  var $utmn;    //ランダムな値(上のパラメータとは別の値が必要)
  var $today;   //日付
  var $header;  //送信するヘッダ
  var $res;      //送信後に取得した内容(おそらく必要なし)
  /**
   * CONSTRACTER
   * @param utmac GoogleAnalyticsのID
   * @param utmhn 測定するドメイン
   * @param session セッションID(一意に識別できるものなら何でも可)
   */
  function GoogleAnalyticsMobile($utmac,$utmhn,$session)
  {
    $this->utmac = $utmac;
    $this->utmhn = $utmhn;
    $this->session= $session;
    //intの最大値を超える数字を指定した乱数(float型になるのかな?)
    $this->utmn = rand(1000000000, 9999999999);
    //intの最大値までの乱数
    $this->random= rand(1000000000,2147483647);
    $this->set('today',time());
    $this->set('header');
  }
  /**
   * データ作成とデータ送信
   * @param uservar ユーザー識別子(カスタマID)
   * @param referer リファラ
   * @param utmp リクエストURI
   * @param utmdt ページタイトル
   * @param utmsr ディスプレイサイズ(横*縦)
   * @param utmfl Flashのバージョン
   * @param utmsc 色
   * @param utmcs 文字コード
   * @return IMGタグ OR なし
   */
  function sendGoogle($uservar=NULL
                      ,$referer=NULL
                      ,$utmp=NULL
                      ,$utmdt='-'
                      ,$utmsr='-'
                      ,$utmfl='-'
                      ,$utmsc='-'
                      ,$utmcs='UTF-8')
  {
    if(!$referer){
      $referer = $this->getReferer();
    }
    if(!$utmp){
      $utmp = $this->getRequestUri();
    }
    $today = $this->get('today');
    $host = GOOGLE_ANALYTICS_HOST;
    $sendPrm ='/__utm.gif?';
    $sendPrm.='utmwv=1'
      .'&utmn='.$this->utmn
      .'&utmhn='.$this->utmhn
      .'&utmcs='.$utmcs
      .'&utmsr='.$utmsr
      .'&utmsc='.$utmsc
      .'&utmul=ja'
      .'&utmje=0'
      .'&utmfl='.$utmfl
      .'&utmdt='.urlencode($utmdt)
      .'&utmhid=-'
      .'&utmr='.urlencode($referer)
      .'&utmp='.urlencode($utmp)
      .'&utmac='.$this->utmac
      .'&utmcc='
        .'__utma%3D'.$this->session.'.'
    .$this->random.'.'
    .$today.'.'
    .$today.'.'
    .$today.'.2%3B'
        .'%2B__utmb%3D'.$this->session.'%3B'
        .'%2B__utmc%3D'.$this->session.'%3B'
        .'%2B__utmz%3D'.$this->session.'.'
          .$today.'.2.2.'
          .'utmccn%3D(direct)%7Cutmcsr%3D(direct)'
            .'%7Cutmcmd%3D(none)%3B'
        .'%2B__utmv%3D'.$this->session.'.'
    .$uservar.'%3B';
    //IMGタグで設置する場合
    if(GOOGLE_ANALYTICS_READIMG){
      //EZWebの端末のキャッシュ対策に末尾にtimestampを付与(ランダム数字とクッキーがあるので不要かも)
      return '<img src = "http://' . $host.$sendPrm.'&'.$today.'" width="0" height="0"/>';
    }else{
      $header = $this->get('header');
      if(!$header){
        $header = $this->makeHeader();
      }
      $this->sendData($host,$sendPrm,$header);
      return ;
    }
  }
  /**
   * データ送信
   * @param host ホスト名 (example.com)
   * @param sendPrm リクエストパラメータ (/index.php?aaa=bbb)
   * @param header HTTPヘッダ(クエリ、Host、Content-Type、Content-Lengthは自動的に付与される)
   */
  function sendData($host,$sendPrm,$header)
  {
    $header = "GET ".str_replace(array("r","n"),"",$sendPrm)." HTTP/1.1\\r\\n".$header;
    $header .= "Host: ".$host."\\r\\n";
    $header .= "Connection: Keep-Alive\\r\\n\\r\\n";
    $errno='';
    $errstr='';
    //WEBサーバへ接続
    $fp = fsockopen($host
                    ,GOOGLE_ANALYTICS_SEND_PORT
                    ,$errno
                    ,$errstr
                    ,GOOGLE_ANALYTICS_TIMEOUT);
    //接続に失敗した時の処理
    if (!$fp){
      return FALSE;
    }
    //要求データ送信
    fputs($fp,$header."GET ".$sendPrm." HTTP/1.1\\r\\n");
    //応答データ受信
    $response = "";
    while (!feof($fp)){
      $response .= fgets($fp,4096);
    }
    $this->set('res',$response);
    //接続を終了
    fclose($fp);
  }
  /**
   * ヘッダ作成
   * @param lang 文字種別
   * @param ua ユーザエイジェント
   * @return header
   */
  function makeHeader($lang=null,$ua=null)
  {
    if($lang){
      $header = 'Accept-language: '.$lang."\\r\\n";
    }elseif (isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) && $_SERVER['HTTP_ACCEPT_LANGUAGE']) {
      $header = 'Accept-language: '.$_SERVER['HTTP_ACCEPT_LANGUAGE']."\\r\\n";
    }else{
      $header = 'Accept-language: ja'."\\r\\n";
    }
    if($ua){
      $header .= 'User-Agent: '.$ua."\\r\\n";
    }elseif (isset($_SERVER['HTTP_USER_AGENT']) && $_SERVER['HTTP_USER_AGENT']) {
      $header .= 'User-Agent: '.$_SERVER['HTTP_USER_AGENT']."\\r\\n";
    }else{
      $header .= 'User-Agent: Unknown'."\\r\\n";
    }
    return $header;
  }
  /**
   * リファラーがあれば返す。
   * @return リファラー(あれば)
   */
  function getReferer()
  {
    if(isset($_SERVER['HTTP_REFERER']) && $_SERVER['HTTP_REFERER']){
      return $_SERVER['HTTP_REFERER']; //referer url
    }else{
      return '-';
    }
  }
  /**
   * REQUEST_URIがあれば返す
   * @param  delPrmArr 削除するパラメータ配列
   * @return リクエストURI(あれば)
   * <pre>
   * 値までわかっている場合は配列で指定
   * EX: パラメータprmで値がvalとパラメータがprm2で値が分からない場合
   * ?prm=val&prm2=xxxxx のリクエストURI
   *   => array('prm'->'val','prm2'=>'')
   * </pre>
   */
  function getRequestUri($delPrmArr = array())
  {
    if(isset($_SERVER['REQUEST_URI']) && $_SERVER['REQUEST_URI'] && ($_SERVER['REQUEST_URI'] != '/')){
      $backData = $_SERVER['REQUEST_URI'];
      $flg = FALSE;
      //削除する
      foreach($delPrmArr as $key => $val){
        if($val){
          $backData = str_replace($key.'='.$val,'',$backData);
        }else{
          $backData = preg_replace("/".$key."=[^&]*&/",'&',$backData);
        }
        $flg = TRUE;
      }
      if($flg){
        $backData=str_replace('&&','&',$backData);
        $backData=str_replace('?&','?',$backData);
      }
      return $backData;
    }else{
      return '';
    }
  }
  /**
   * 自由にアクセスできるGETTER/SETTER
   * @param arg アクセスしたいパラメータ名
   * @return パラメータが保持している値
   */
  function get($arg = null)
  {
    if(!$arg){
      return null;
    }
    if(isset($this->$arg)){
      return $this->$arg;
    }else{
      return null;
    }
  }
  /**
   * SETTER
   * @param arg アクセスしたいメンバ変数名
   * @param val 格納したい値
   */
  function set($arg=null,$val=null)
  {
    $this->$arg = $val;
  }
}

携帯電話利用する場合、素直にREQUEST_URI送ってしまうと、セッションIDも送信されてしまい、正確なページ単位の集計ができません。
さらに、DoCoMoの端末のみ”guid=on”のパラメータが付いているサイトなどもあるでしょう。
また、広告コードが付与されて送信されてくるパターンもあります。
そういう場合にはgetRequestUri()メソッドを利用してREQUEST_URIを改変してセットします。
また、sendGoogle()メソッドには上記見てもわかるように色々引数を追加できます。
それも追加してみましょう。
また、makeHeader()メソッドでHTTP_USER_AGENTやHTTP_ACCEPT_LANGUAGEも変更できます。
しない場合はコールしなくても、勝手にコールされます。

以下サンプル

//クラス読み込み
include_once 'GoogleAnalytics.class.inc';
include_once 'googleAnalytics.conf.inc';
//Google AnalyticsのID
$GAM_id = GOOGLE_ANALYTICS_ID;
//サーバ名(ドメイン)
$domain = $_SERVER['SERVER_NAME'];
//セッションID 携帯では独自に引き継がないとできないので注意
$sess = session_id();
//ユーザ側で通知したい値
$md5_subid = md5('ユーザID等');

//GAMセット
$GAM = new GoogleAnalyticsMobile($GAM_id,$domain,$sess);
//リファラ取得
$ref = $GAM->getReferer();
//REQUEST_URI取得(guid,ses_id,ad_idを削除)
$reqi = $GAM->getRequestUri(array('guid'=>'ON'
                                 ,'ses_id'=>$ses_id
                                 ,'ad_id'=>''));
//ページタイトルを設定
$title = 'タイトル';
//画面幅(横*縦)
$bSize = '240*320';
//Flashのバージョン
$flash = '-';
//表示可能色数
$color=$LIB_ARR_MP['color'];
//送信データ生成&送信
$res=$GAM->sendGoogle($md5_subid
                        ,$ref
                        ,$reqi
                        ,$title
                        ,$bSize
                        ,$flash
                        ,$color);
//IMGタグを利用する場合は以下も必要
//echo $res;

これでOK
サイトの共通ファイルや、コントローラ、もしくは共通ヘッダ、共通フッタ等にセットすれば、GoogleAnalyticsがケータイでも利用できます。
ただ、注意点としては画像読み込みで利用される場合(GOOGLE_ANALYTICS_READIMG定数がTRUE)、
画像をフッターに表示させようとすると、ページ全体を読み込むまで通知されない可能性があるので、
極力ヘッダに記述した方がいいと思います。

ですが、HTMLが開始される前に表示するのは厳禁ですよ!

ただ、こちらも難点としてはDoCoMoの端末は画像が表示されるまで次の行を表示しようとしないのです。(データは取得している模様)
あまりにGoogleへの通知に時間がかかる場合等はユーザが戻る操作等を行う可能性があります。

ソケットで通知する際は定数にて接続を切る時間が設定できるので(GOOGLE_ANALYTICS_TIMEOUT定数)、ユーザーがせっかちな場合等はここを1秒等に設定すればましかもしれません。

のびーにょ PHP, システム, 携帯電話

PHPでBOM付きUTF-8

2009/2/25 水曜日 12:36:06

お久しぶりです
のびーにょです
ちょっとはまったのでTips的に

ZIPをダウンロードさせるプログラムを書いてました。
右クリックして保存。とかじゃなくてアクセスしたらダウンロードするような奴です。

で、サーバ側でZIP生成してそれをダウンロードさせようとしてたんですがファイルサイズはサーバに保存した内容と同じぐらいなのに解凍すると中身が少ない・・・

解凍ソフトはLhaplus使ってたんですがWINRARとか使って解凍すると中身が全部ある という現象が発生。

色々調べてたんですけど結局わからず・・・
みたいになってバイナリエディタで比較してみると・・・

先頭に何やらついてますね・・・
EF BB BF
ってのが3つぐらい

これBOMのエンディアンじゃないですか・・・

ソース調べてみるとBOM付きUTF-8で保存されてるファイルが3つ・・・

まさにこれじゃないですか・・・

BOM無しUTF-8で保存しなおして実行すると何事もなかったかのように解凍できる

PHPでBOM付きUTF-8は使わないに越したことはないというお話でした

http://bugs.php.net/bug.php?id=22108

まだバグなおってないみたいだしね・・・

のびーにょ PHP, Tips, その他

PHP HACKS

2009/2/5 木曜日 12:44:00

お久しぶりです
のびーにょです

PHP HACKS

買いました。

日本語版が出てるのさっぱり知らなくて、英語版だけだと思ってました。
2006年に発売されてたんですね・・・

まだ全然読めてないですけど、時間見つけて読んでみようと思います。

のびーにょ PHP

今日は何の日?

2009/1/30 金曜日 14:54:35

X年、Y月のZ週目月曜日が知りたいー。
ってときに使ったプログラム。

$yearに知りたい年
$monthに知りたい月
$weekに知りたい週(0~)

// 最初のX曜日を算出
for ($i = 1; $i > 8; $i++){
	if(date("w", mktime(0,0,0, $month ,$i ,$year)) == 1){
		break;
	}
}
$ret = $i + ($week * 7);

// チェック
$last_day = date("t", mktime(0,0,0, $month, $ret, $year));
if ($ret < $last_day){
	return;
}else{
	return $ret;
}

日本の祝日とかで、第二月曜日が祝日だとかよくあるのでそのためだけに。

下音タヌキ PHP

日付整形手術

2008/12/29 月曜日 12:55:26

・フォームから送信された日付をDBにINSERT、UPDATEできる形にするための整形
・DBからSELECTで引っ張ってきたDATETIME型の日付の整形

上記を例として日付の整形ってよく出食わします。
sprintf、substr、explode、正規表現を使う等、いろんなやり方があると思いますが…
自分が使っている方法をまとめてみます。

※例 DATETIME型の文字列を整形して表示

$time = '2008-07-10 21:02:23';
$data = sscanf($time, '%d-%d-%d %d:%d:%d');

sscanf()はprintf()の入力版で、文字列を指定したフォーマットに基づいて配列で抜き出します。
(フォーマットについてはprintf()のマニュアル参照)

$dataは下記のようになります

Array
(
    [0] => 2008
    [1] => 7
    [2] => 10
    [3] => 21
    [4] => 2
    [5] => 23
)

一発で変数に入れたい場合はlist()関数を使いましょう。

list($year, $month, $day, $hour, $minute, $second) =
	sscanf($time, '%d-%d-%d %d:%d:%d');
echo $year.'年'.$month.'月'.$day.'日 '.$hour.'時'.$minute.'分'.$second.'秒';

//【結果】2008年7月10日 21時2分23秒

こんな感じにすれば取り敢えず整形して表示できますが、一桁の月、日はゼロで穴埋めしたかったりする場合もあったりするので、ここは関数sprintf()を使って整形します。

echo sprintf('%d年%02d月%02d日 %02d時%02d分%02d秒',
	$year, $month, $day, $hour, $minute, $second);

//【結果】2008年07月10日 21時02分23秒

sprintf()の引数では配列を指定できませんが、vsprintf()を使うと配列を指定でき、

list($year, $month, $day, $hour, $minute, $second) =
	sscanf($time, '%d-%d-%d %d:%d:%d');
echo sprintf('%d年%02d月%02d日 %02d時%02d分%02d秒',
	$year, $month, $day, $hour, $minute, $second);

の二行を一行でやっつけちゃえます。

echo vsprintf('%d年%02d月%02d日 %02d時%02d分%02d秒',
	sscanf($time, '%d-%d-%d %d:%d:%d'));

関数やメソッドで用意しておくと使い回しできて良いかと思われます。

チョコボール MySQL, PHP, Tips, データベース

春分/秋分の日を打開する

2008/12/29 月曜日 12:17:56

カレンダーを作る際、春分/秋分の日が変動して計算が面倒です。
そんな春分/秋分の求め方は以下。

function getSpringHolyday($year){
	if ($year <= 1947){
		$ret = false;
	}elseif ($year <= 1979){
		$ret = floor(20.8357 + (0.242194 * ($year - 1980)) -
			floor(($year - 1980) / 4));
	}elseif ($year <= 2099){
		$ret = floor(20.8431 + (0.242194 * ($year - 1980)) -
			floor(($year - 1980) / 4));
	}elseif ($year <= 2150){
		$ret = floor(21.851 + (0.242194 * ($year - 1980)) -
			floor(($year - 1980) / 4));
	}else{
		$ret = false;
	}
	return $ret;
}

function getAutumHolyday($year){
	if ($year <= 1947){
		$ret = 99;
	}elseif ($year <= 1979){
		$ret = floor(23.2588 + (0.242194 * ($year - 1980)) -
			floor(($year - 1980) / 4));
	}elseif ($year <= 2099){
		$ret = floor(23.2488 + (0.242194 * ($year - 1980)) -
			floor(($year - 1980) / 4));
	}elseif ($year <= 2150){
		$ret = floor(24.2488 + (0.242194 * ($year - 1980)) -
			floor(($year - 1980) / 4));
	}else{
		$ret = 99;
	}
	return $ret;
}

20.8357とか、23.2588とか、0.242194とか、意味不明な数値が出てますが、
20.8357は、1980年の春分の日が、20日の20時14分4秒と発表されているので、そこから計算しているというわけです。23.2588も同様の考え方で・・。
0.242194は、1年365.242194日で扱われていたことから、差分として年数分計算してあげてます。
最後に、floor(($year - 1980) / 4)としているのは、閏年を考慮してます。
何分古いお話で、そんな感じで計算されてます。

下音タヌキ PHP

CASE式で値を変えて引っ張ってくる![MySQL]

2008/12/16 火曜日 16:45:41

チョコボールです。
MySQLにてSELECT時に値の形を変えて引っ張ってくる方法。
僕はステータスが数字で管理されているようなDB(※例: 男性が「1」、女性が「2」等)をfetchしてきて表示する時等に使ってます。

取り敢えずSELECTで引っ張ってきてプログラム側で加工してやればいいんですが、CASE式を使えば加工の必要が無いので結構楽です。

下記のようなmemberテーブルがあったとします。

+----+------+--------+
| id | name | status |
+----+------+--------+
|  1 | 田中 |      0 |
|  2 | 辻川 |      1 |
|  3 | 鈴木 |      0 |
|  4 | 山本 |      1 |
|  5 | 西田 |      0 |
|  6 | 上村 |      2 |
|  7 | 星野 |      0 |
|  8 | 宮村 |      3 |
|  9 | 川田 |      1 |
| 10 | 山田 |      1 |
+----+------+--------+
ステータス
0 → 通常会員
1 → 有料会員
2 → 退会済会員

そのまま

SELECT * FROM member

としてfetchすると

Arrray
(
	[0] => Array
		(
			[id] => 1
			[name] => 田中
			[type] => 0
		)

	[1] => Array
		(
			[id] => 2
			[name] => 辻川
			[type] => 1
		)

	[2] => Array
		(
			[id] => 3
			[name] => 鈴木
			[type] => 0
		)
			・
			・
			・

のような感じで取得できますが、下記のようなSQLを組むことでプログラム側で加工無しに一発で引っ張ってくることが出来ます。

SELECT id, name,
	CASE
		WHEN type = '0' THEN '通常会員'
		WHEN type = '1' THEN '有料会員'
		WHEN type = '2' THEN '退会済会員'
		ELSE '不明'
	END type
FROM member
 Array
(
	[0] => Array
		(
			[id] => 1
			[name] => 田中
			[type] => 通常会員
		)

	[1] => Array
		(
			[id] => 2
			[name] => 辻川
			[type] => 有料会員
		)

	[2] => Array
		(
			[id] => 3
			[name] => 鈴木
			[type] => 通常会員
		)
			・
			・
			・

CASE式は他にもいろいろ使えるのでまた紹介します!

チョコボール MySQL, PHP

波ダッシュ(にょろ、波線)に気をつけましょう

2008/12/4 木曜日 18:07:00

さて
文字コード周りで思いついたのでちょっと書いときます

波ダッシュ”〜”っていうのがあります。
にょろ とか 波線 とか言われてます。
Windowsだと普通に打つと”~”ですよね。
と、言ってもXPとそれより前では違うようですが・・・

色々問題があるようでSjisとUnicodeで変換かけると変わるとかあります。
と、いうか特定のエディタだと開けなかったりするみたいですね。
Shift_JISとUnicodeのマッピングが違うのが原因らしいですが、詳しいことはWikipedia見るといいと思います

で、PHP上で変換かける場合は

mb_convert_encoding('~', 'utf8', 'sjis-win');
mb_convert_encoding('〜','sjis-win','utf8');

ってな感じで”sjis-win”っていう拡張文字コード指定してあげれば求めている変換をしてくれると思います。
でもですね
特定のエディタで開けない(シェアのエディタ含む)場合があるので、複数人で触るようなソースに書くのはあんまりよろしくないのですよ

ってことで”〜”から”~”に変換するときは下の書き方の方がいいのかも

str_replace("xE3x80x9C",'~',$data);

たまーにMac使ってる人からデータもらうとそうなっている場合があるので、Macの方は注意した方がいいかもしれません。
携帯もSJISがメインなので。。。

“~”から”〜”に変換することはそうそうないと思いますので割愛

のびーにょ PHP, Tips, 携帯電話

表示で長い文字列を丸める!

2008/11/28 金曜日 14:45:33

本日投稿2個目、チョコボールです。

DBから引っ張ってきた文字列をセレクトボックスで表示させる箇所で、
長ったらしい文字列があるせいでデザインが崩れてしまっている!という指摘を受けました。

指定した幅以上は「…」で表示するという、よくある表示方法で対処しようと思い、
substr関数等であれこれ試していましたが、mb_strimwidthという関数を使うといい感じでした。

mb_strimwidth(【文字列】,【開始位置のオフセット(最初の文字は0)】,【幅】,
【丸めた後にその文字列の最後に追加される文字列】,【文字エンコーディング】)

表示部分で『この横幅以下に抑えたい』という時に使えます。

文字コードに依存せず、第3引数の数値は半角を幅1、全角を幅2とします。
文字数ではありません。
また、第4引数も含めた数値になります。

$str = "あいうえおかきくけこ";
$str2 = "This is a pen.";

echo mb_strimwidth($str, 0, 10, '…', 'UTF-8');
echo '&lt;br /&gt;';
echo mb_strimwidth($str2, 0, 10, '…', 'UTF-8');

上記の結果は下記のようになります。

あいうえ…
This is a…

全角の文字の場合でも半角の文字の場合でもだいたい横幅が揃うはずです。

smarty側で書く場合はこんな感じです。

{$str|mb_strimwidth:0:10:'…':'UTF-8'|escape}

チョコボール PHP

文字コードの変換

2008/11/28 金曜日 11:42:02

チョコボールです。

PHP言語での文字コードの変換といえば『mb_convert_encoding』関数。

mb_convert_encoding(【文字列】,【変換後の文字コード】,【変換前の文字コード】);

返り値は変換後の文字列です。

以前書いた記事、CSVファイル出力関数の時にも使いましたが、出力する直前に、

$str = mb_convert_encoding($str, 'SJIS', 'UTF-8');

のように使って文字列の文字コードを変換したりするわけです。

上記の場合、UTF-8からShift JISに変換です。

第3引数→第2引数

第3引数を指定しなかった場合は、内部文字エンコーディング
(php.ini の mbstring.internal_encoding の値)を使用することになります。

配列中の文字列の文字コードを一気に変換したい時、
foreach等でループさせてmb_convert_encodingかけて…
とかしなくてもmb_convert_variables関数で一行でいけます。

mb_convert_variables(【変換後の文字コード】,【変換前の文字コード】, 【文字列、配列、オブジェクト】);

変数はカンマで区切って複数指定できます。

第2引数→第1引数

mb_convert_encodingと違い、返り値は変換前の文字エンコーディングを返します。
失敗した場合はFALSEを返します。

$ret = mb_convert_variables('SJIS', 'UTF-8', $array);

上記の場合、返り値$retはSJISになります。

単に変換を掛けたいだけの場合は

mb_convert_variables('SJIS', 'UTF-8', $array);

の一行で。

一見似ている関数ですが、引数の順番の違い、返り値の違いに注意が必要です。

チョコボール PHP