PHP雑記帳 ITかあさん

ITかあさん

PHPでパラメータの『?』以降を取得する方法

PHPでパラメータの『?』以降を取得する方法

Javascriptで?以降のパラメータ情報を取得するなら

location.search

ですが、PHPでは直接このように受け取る方法はありません。

strstrで指定文字以降の文字列を取得

strstrを使うと、指定文字列以降の文字を取得することが出来るので、これを利用してPHPでパラメータの『?』以降を取得したいと思います。

$param = strstr($_SERVER["REQUEST_URI"], '?');
$_SERVER["REQUEST_URI"] で自URLを取得し、?以降の文字列を取得しています

最新PHPmyadmin3.5.1の明らかな間違いを発見した

PHPmyadmin3.5.1のCSVエクスポートがちょっと変

記事にすることのほどでもなかったかもしれませんが、最新PHPmyadmin3.5.1でちょっとした間違いを発見しました。
テーブルデータのSQLエクスポートではなく、CSVエクスポートを使う機会が仕事であったのですが、PHPmyadmin3.5.1にしたところ、エクスポートCSVをうまくインポート出来なくなってしまいました。
冷静にエラーを見ながら、問題の行を確認したところすぐ原因が分かりました。

phpmyadmin3.5.1のCSVエクスポートのオプションが何か変だ!

こちらはCSVエクスポートの詳細設定。

カラムの囲い記号とエスケープの記号が明らかに一緒!インポート時エラー確実!

この場合、エスケープの記号をバックスラッシュなど他の記号にしてあげます。
なお、3.4.0ではこのようになっています。

phpmyadmin3.4.0だとエスケープ記号に問題はないようです。
何だろう、間違えたのかな?

PHP Session有効期限を延ばす方法

タイトルの通りなのですが、Sessionの有効期限を延ばす方法です。

php.ini gc_maxlifetimeの値を変更する

Sessionの有効期限についてはphp.iniのgc_maxlifetimeにて管理されています。
ですが、共有サーバーでは設定を変更できませんし、特定のディレクトリのみSessionの有効期限を延ばす方法は

.heaccess

php_value session.gc_maxlifetime 3600

PHP

session_save_path(“/tmp”);
ini_set(‘session.gc_maxlifetime’, 1800);

こんなカンジで。個人的には.heaccessのほうがお手軽でよいと思っています。
PHPのファイルに記入する場合は必ずSessionのスタート前に記入してください。

WordPressなどのCMSの管理画面にも使えそうですね。

ディレクトリは一体何キロバイト?が一発で分かるPHP

ファイルサイズはFTPツールでバイト表示がされていますが、ディレクトリのトータル何キロバイトかは分かりません。
ましてやサイト全体のディレクトリが何キロバイトかなんて・・・
そんな時にはこちらが使えそうです。

ftp.php

こちらでは/home/example/public_htmlのディレクトリサイズが分かります。

function dir_size($dir)
{
  $handle = opendir($dir);
  while ($file = readdir($handle)) {
    if ($file != '..' && $file != '.' && !is_dir($dir.'/'.$file)) {
      $mas += filesize($dir.'/'.$file);
    } else if (is_dir($dir.'/'.$file) && $file != '..' && $file != '.') {
      $mas += dir_size($dir.'/'.$file);
    }
  }
  return $mas;
}
echo dir_size('/home/example/public_html');

閲覧可能ディレクトリにこちらのスクリプトを閲覧可能ディレクトリに設置し、ブラウジングします。
dir_sizeの括弧の中はディレクトリの絶対パスを記入してください。
自分のディレクトリの絶対パスが分からない場合はこちらを記入してください。
絶対パスが分かります。

echo dirname(__FILE__);

情報の単位

ディレクトリのトータルサイズはキロバイトで表示されますので、1MBは一体何キロバイトなんだ!という疑問はこちらの表を参考にして下さい。

キロバイト 1KB = 1,000B
メガバイト 1MB = 1,000KB
ギガバイト 1GB = 1,000MB
テラバイト 1TB = 1,000GB

サーバー移転時など自分のサイトのHDDはどれくらいだから、このプランにしようとかの参考になるのでは?
後は単純にそういえば自分のサイトは容量どれくらい使っているのかな?とか、そんなちょっとした興味がわいたときに使ってみてくださいね。
ちなみにITかあさんのサイトのサイズは65270983バイト。65MBってとこですか?あれ?計算あってる?

今日のコレ欲しい!

義理の弟さんが『HTML』って書いてあるキャップをかぶってました。トラック運転手なのに。そんなわけでアタシもHTMLファッションアイテムが欲しいです。
いかにも!なカンジじゃなくて、改行連発とか、思わず『おい!』って突っ込みたくなるマークアップTシャツが欲しい。

誰でもスクレイピング!DOM要素を引っこ抜くSimple HTML Dom

誰でもスクレイピング!DOM要素を引っこ抜くSimple HTML Dom

Linuxエンジニアの方と一緒に主催している勉強会で『スクレイピング』についてリクエストを頂いたことがきっかけで『WEBサイト上で表示されているテキストやリンクなどのDOM要素をスクレイピングで簡単に引っこ抜いてしまおう!』ということになりました。
人生初のスクレイピング体験となりましたが非常に簡単!ではいってみよ~

1分で分かるスクレイピング

そもそもスクレイピングとは

・ウェブサイトのデータを必要な部分だけ抽出して利用すること

DOM要素として必要な部分だけを抽出して、ほとんどの場合自分のデータベースに登録して実際には運用したりします。

スクレイピング注意点

・著作権問題

WEBサイトは著作権で守られています。許可無く勝手に人様のサイトから情報だけ抜き出して自分のサイト上に公開することは出来ません。この著作権の問題には十分注意してください。

スクレイピング便利クラス Simple HTML Dom

スクレイピングの方法はいくつか存在するのがですが、私はSimple HTML Domを好んで使っています。色々調べた結果、個人的にはこれが一番使い易いと思いました。
サイトからダウンロードし、simplehtmldom_1_5フォルダをスクレイピングを実行したいサーバーにアップして、simple_html_dom.phpを呼び出すだけで準備は完了します。

引っこ抜きの指定が実はCSSそっくり!だからWEBデザイナーにも!

簡単ですが、データの引っこ抜き方です。『ここを引っこ抜きたい!』という部分を指定します。

下記の赤字部分に注目。引っこ抜きたい(スクレイピングしたい)DOMの指定。

$html = file_get_html( ‘http://から始まるURLで指定’ );//何のURLからスクレイピングするか
foreach($html->find(‘a’) as $element)

id=”contents”の中のulを引っ張りたいなら

foreach( $html->find( ‘#content ul’ ) as $ul )

DOMの指定が#contentで、#を使えて入れ子にするあたりが全くCSSの指定と一緒なのでWEBデザイナーにも優しい設計です!

1分でスクレイピング実行!

ITかあさんのブログ内をスクレイピング実行して、どのように抜き出せるのか実際にやってみましょう。

例えば、ITかあさんのブログのトップページ中のリンク(hrefの中身)を引っ張るとしたらこうなります。

// simple_html_dom.phpファイルの読み込み
include_once('simplehtmldom_1_5/simple_html_dom.php');
//スクレイピングしたいURLを指定
$html = file_get_html( 'http://www.kaasan.info/' );
//リンク
foreach($html->find('a') as $element)
echo $element->href . '<br>';

これだけでは何のリンクなのか分かりません。引っ張るaタグの範囲を右カラムのリンクに絞ります。

// simple_html_dom.phpファイルの読み込み
include_once('simplehtmldom_1_5/simple_html_dom.php');
//スクレイピングしたいURLを指定
$html = file_get_html( 'http://www.kaasan.info/' );

//○○の中のある特定の要素もCSSと同じように指定できます。
foreach($html->find('#rightcol .category_list a') as $element)
echo $element->href . '<br>';
もちろん画像のみの抽出も可能でして
// simple_html_dom.phpファイルの読み込み
  include_once('simplehtmldom_1_5/simple_html_dom.php');
//スクレイピングしたいURLを指定
  $html = file_get_html( 'http://www.kaasan.info/' );
//画像URL保存用の空の配列を用意
  $src = array();
  //リンク
  foreach($html->find('img') as $key => $element){ 
  $src[$key] = $element->src;
  }

foreach($src as $img){
echo '<img src="'.$img.'">';
}

もっと細かく要素を指定したい場合はこちらが参考になります。

おまけ:Wordpress × Simple HTML Domでスクレイピング

スクレイピングしたDOMをforeachのループ中にINSERT文を実行すれば簡単に自分のwordpressに記事として登録することが出来ます。
以下はさくらvps設定マニュアルの投稿記事一覧を抽出してWordpressをインストールしたデータベースに、記事としてINSERTする方法です。

MDB2.phpは大手レンタルサーバーなら大抵インストールされているかと。(私mysql関数って使ったことないんですよ・・)

require_once 'MDB2.php';//ライブラリのロード
//DSN
  $db = "mysql://ユーザー名:パスワード@localhost/データベース名?charset=utf8";
//接続
  $mdb2 =& MDB2::factory($db);
//フェッチモード設定
  $mdb2->setFetchMode(MDB2_FETCHMODE_ASSOC);
  
  // simple_html_dom.phpファイルの読み込み
  include_once('simple_html_dom.php');
  
  // UTF-8で処理 他の文字コード処理するかもしれないからdefineしておく。
  define("CHAR_SET","UTF-8");
  
  // 文字化け対策のおまじない的(?)なもの。
  mb_language("Japanese");
  
  $html = file_get_html( 'http://www.kaasan.info/archives/category/さくらvps設定マニュアル' );
//wordpress上の投稿日時
  $wordpress['date'] = '2012-02-12 10:00:00';
foreach( $html->find( '#content ul' ) as $ul )
  foreach( $ul->find( 'li' ) as $li )
  $mdb2->exec("INSERT INTO `wp_posts` (`post_author`, `post_date`, `post_date_gmt`, `post_content`, `post_title`, `post_excerpt`, `post_status`, `comment_status`, `ping_status`, `post_password`, `post_name`, `to_ping`, `pinged`, `post_modified`, `post_modified_gmt`, `post_content_filtered`, `post_parent`, `menu_order`, `post_type`, `post_mime_type`, `comment_count`) VALUES
  (1, '{$wordpress['date']}', '{$wordpress['date']}', '$li', 'test', '', 'publish', 'open', 'open', '', 'test', '', '', '{$wordpress['date']}', '{$wordpress['date']}', '', 0, 0, 'post', '', 0)");

サンプルは以上です。
どこをどのように引っ張るのか、アイディア次第でいろんなサイトやサービスがお手軽に作れそうですが、著作権などの問題には十分注意してください。

mysql2json.classでわずか3分でmysqlをjsonに変換そして保存!

PHP×Mysql×jsonそして保存をわずか3分で!

Ajaxベースで検索を行うならjson。変換して、保存してしまえばデータベースへのクエリが減り、高速サクサクサイトが作れてしまいます。
そんなわけでPHP×Mysql×jsonそして保存をわずか3分で実装したいと思います。

mysql2json.class

PHPからmysqlのデータをjson化するわけですが、とっても便利なクラスがあるので紹介します。

mysql2json.class – PHP Classes
※会員登録が必要です。(無料) 
今回紹介する以外にもたくさんのPHPのクラスやプラグインが公開されているので、オススメのサイトです。

mysql2json.classを使ってMysqlをjsonに変換!

以下は文字コードがutf-8であることを想定して行っています。
mysql2json.class.phpを先に呼び出し、Mysqlの接続設定を書いて、json変換したい内容をSQLで記述、JSONに変換を行うのが一連の流れです。

include("mysql2json.class.php");

//データベース関係 ここではutf-8 を想定
mb_language('Japanese');
ini_set('mbstring.detect_order', 'auto');
ini_set('mbstring.http_input'  , 'auto');
ini_set('mbstring.http_output' , 'pass');
ini_set('mbstring.internal_encoding', 'UTF-8');
ini_set('mbstring.script_encoding'  , 'UTF-8');
ini_set('mbstring.substitute_character', 'none');
mb_regex_encoding('UTF-8');
//MySQL接続設定
define("DBHOST", "localhost");
define("DBNAME", "");
define("DBUSER", "");
define("DBPASS", "");

//接続
$conn = mysql_connect(DBHOST, DBUSER, DBPASS) or die();
mysql_select_db(DBNAME, $conn);
mysql_set_charset('utf8');

//SQL実行
$num = 0;
$sql = "SELECT * FROM table";
$result = mysql_query($sql, $conn);
$num = mysql_affected_rows();

// JSONに変換
$objJSON = new mysql2json();

JSONデータをテキストとして保存する

$objJSON = new mysql2json(); と記述してあげると、jsonとして呼び出すには

$string = trim($objJSON->getJSON($result,$num));
echo $string; 

でもせっかくJSON作ったので、これを保存してあげます。あらかじめJSONがあれば、Mysqlに接続すらしないで、JSONからデータの呼び出しが出来ますもんね。AJAXベースで検索システムを作る時には最適です。
$objJSON = new mysql2json(); からの続きです。

$filepath = "json.txt"; // json保存用。パーミッションは666
$string = trim($objJSON->getJSON($result,$num)); // 書き込みたい文字列を変数に格納
$fp = fopen($filepath, "w"); // 新規書き込みモードで開く
@fwrite( $fp, $string, strlen($string) ); // ファイルへの書き込み
fclose($fp);

isset() は複数の引数が入れられる

isset() は複数の引数が入れられる

if(isset($a) && isset($b) && isset($c)){
echo "It is ALL setting!"
}

issetはこんな風にカンマで区切って複数チェックすることが出来ます。

if(isset($a, $b, $c)){
echo "It is ALL setting!"
}

知らなかった~。便利ね。

半角と全角の混じる文字列から文字化けせずに切り取る

半角と全角の混じる文字列から文字化けせずに切り取る

下記のような形だと、1バイトと2バイトが混じるため、最後の文字が文字化けしてしまうことがあります。

substr関数

$str = 'あいssえおsssかfきsくsけsこ';
echo substr($str, 0, 7);

mb_substr関数

このように第4引数に文字コードを指定してあげると、1バイトと2バイトが混じった文字列でも文字化けすることなく自在に切り取ることが出来ます。
mb_substr関数は、1バイトだろうが、マルチバイトだろうが各一文字をカウントして、指定された長さにして返すのが特徴です。
日本語を含む文字列操作はこちらを使ったほうが良さそうです。メモメモ。

$str = 'あいssえおsssかfきsくsけsこ';
echo mb_substr($str, 0, 7,'UTF-8');

ロリポップ WordPress移転メモ

簡単インストール付いていると、けっこう失敗する・・・

知り合いに、お名前.comでサーバーで運用していたWordpressを移転してほしい旨頼まれました。簡単インストールのため けっこう失敗してしまったので そのメモ。

まずはサーバーの管理画面より簡単インストールを実行

ロリポの場合、Wordpressの簡単インストール機能がついています。
ロリポプランを利用しているとDBは一つしか使えないので、簡単インストールにより インストールしたほうが設置そのものは失敗しにくいです。また、最新のWordpressが簡単にインストールできるのです。

一度ロリポのphpMyadminにログイン

一度ロリポのphpMyadminに入って、インストールしたwordpressのtableの接頭詞が何になっているかを確認します。
初めてロリポにWordpressをインストしたならwp1_○○ となっているはずです。

旧サーバーよりエクスポートしたSQLを慎重に実行

エクスポートしなければならないのが、

wp_commentmeta…コメントメタ
wp_comments…コメント
wp_links…リンク
wp_postmeta…投稿した記事のメタ
wp_posts…投稿した記事
wp_terms…ブログのカテゴリー
wp_term_relationships…よく分からないけカテゴリに関係ありそう
wp_term_taxonomy…カテゴリの詳細情報

簡単インストールをしたときに、移転後のブログのDBテーブルは既につくられているので、インサート部分のみ実行していきます。
Dreamweverの置き換え機能をつかって、
wp_→wp1_
として、移転後のサーバーにインサートが全て出来るようにします。

ユーザー情報は簡単インストール、Wordpress管理画面より

wp_options
wp_usermeta
wp_users

このあたりのデータの移動については、簡単インストール実行中に聞かれたりします。その他のusermetaやオプション設定についてもWordpressの管理画面からやったほうがたぶん失敗しないです。

テーマとアップロードデータの移動

DB関連の設定が終わったら、最後にtemaフォルダと、uploadデータを移動して終了です。

まとめ

ロリポはDBサーバーは別に分かれているので localhostとかやってもWordpressがてDBに接続できなかったりします。

簡単インストールがあるレンタルサーバーの場合、Wordpressのインストールそのものはレンタルサーバーの機能にまかせて、エクスポートしたデータについては インサート文だけ慎重に実行していくのが一番簡単そうです。
逆にWordpressをそっくりそのままフォルダごと移動させたほうが返って手間になってしまいましたw

Twitpic×Twitter×WordPressで作る写真ブログ

1Tweetを1ページにする、お手軽ブログ

前々から『Twitterでの投稿をWordpressに反映させたい!』と思っていました。
もっと手軽に、もっと簡単なブログの更新方法は無いかと考えた結果、
『1Tweetを1ページにする、お手軽ブログ』を作りました。
また、どうせならTwitpicで投稿された内容も表示して、絵日記のような、写真日記を作りたかったのですが、ついに完成しました。

必要なもの

・wrodpress
・Mysql
・PHP
・Twitterアカウント
・Pear:MDB2

特徴と動作方法

あらかじめWordpressのインストールを完了させておく必要があります。
以下のスクリプトを設置したURLにアクセスされると、15件分のツイートをWordpressに1ツイート1記事にしてくれます。
重複登録回避で、最後に登録したデータと、新しいデータを比べて、最後に登録されたデータより日時が新しければ登録します。そうでなければ登録しません。
xmlが17件くらいしかツイートデータを拾ってくれなかったので、それ以上だと拾いきれないと思います。
Twitterでは短縮URL化されたものは、URLは元の短縮前のものに置き換わります。
写真の表示はTwitpicしか対応していません。
以下のスクリプトをどこかのWEBページにおいて、アクセスすると、書き込みを開始します。
正規表現でハッシュタグは削除されます。
ブログのタイトルはツイートのテキストの部分だけ。URL、ハッシュ、RTタグは正規表現で削除されます。
(けっこう重たいです)
なので、どこかのWEB環境において、Cronで定期実行してあげることで 自働で書き込みされるようにしてあげてください。
なお、Noticeエラー出ちゃってますが、書き込みには支障ないです。
何はともあれ最大の特徴は1ツイートを1ブログでTwitpicを表示できること。これで写真ブログになります。
あと、URLは元のURLに置き換えられているので、自分のブログのURL付きでツイートすれば、SEO効果も見込めると思います。

個人的に作ったものなので、動作の保障はしません。あくまで自己責任でお願いします。

require_once 'MDB2.php';//ライブラリのロード
//DSN
  $db = "mysql://ユーザー名:パスワード@localhost/データベース名?charset=utf8";
//接続
  $mdb2 =& MDB2::factory($db);
//フェッチモード設定
  $mdb2->setFetchMode(MDB2_FETCHMODE_ASSOC);
//SQL文発行
  $sqlStr = "select * from wp_posts order by post_date desc limit 1";
  $res = $mdb2->queryAll($sqlStr); 
$update = $res[0]['post_date'];//最終投稿の日付取得
//URL置き換えフォーマット
  function square($short_url){
  $h = get_headers($short_url,true);
  if(isset($h['Location'])){
  $long_url = $h['Location'];
  if(is_array($long_url)){
  $long_url = end($long_url);
  }
  }
  return $long_url;
  }
$contents = file_get_contents('http://twitter.com/statuses/user_timeline.xml?id=自分のTwitterアカウント');
//XMLをオブジェクトに変換
  $xml = simplexml_load_string($contents);
  //XMLオブジェクトを扱いやすいよう、通常の配列に一度変換を行う
  $arrayA = array();
for ($i = 0; $i <= 15; $i++) {
  $arrayA[$i]['title'] = (string)$xml->status->$i->text;
  $arrayA[$i]['updated'] = (string)$xml->status->$i->created_at;
  }
$twitter_array = array();
  foreach($arrayA as $val => $twitter){
  preg_match_all("/http:\/\/[a-z0-9\/\-_\.]+/i",$twitter['title'],$match);

foreach($match[0] as $match_url){
$URL = square($short_url = $match_url);//短縮化されたURLに一度アクセスをし、正規のURLを取得する処理
  $twitter_array[$val]['url'][] = $URL;
  }
$twitter['title'] = preg_replace("/http:\/\/[a-z0-9\/\-_\.]+/i","",$twitter['title']);
//RTタグを削除
  $twitter['title'] = preg_replace("/[QR]T ?@[a-z0-9_]+:?/i","",$twitter['title']);
//返信を削除
  $twitter['title'] = preg_replace("/@[a-z0-9_]+:?/i","",$twitter['title']);
//ハッシュタグを削除 日本語対応
  $twitter['title'] = preg_replace("/(?:^|[^ー゛゜々ヾヽぁ-ヶ一-龠a-zA-Z0-9a-zA-Z0-9&_\/]+)[##]([ー゛゜々ヾヽぁ-ヶ一-龠a-zA-Z0-9a-zA-Z0-9_]*[ー゛゜々ヾヽぁ-ヶ一-龠a-zA-Z0-9a-zA-Z]+[ー゛゜々ヾヽぁ-ヶ一-龠a-zA-Z0-9a-zA-Z0-9_]*)/","",$twitter['title'], -1);
//ハッシュタグを削除 数字のみのハッシュタグを削除
  $twitter['title'] = preg_replace("/[##]([0-9_])+:?/i","",$twitter['title']);
//ハッシュタグを削除 半角英字のみ
  $twitter['title'] = preg_replace("/[##]([a-zA-Z0-9])+:?/i","",$twitter['title']);
$twitter_array[$val]['title'] = $twitter['title'];//Twitterのテキスト
$twitter_array[$val]['updated'] = date('Y-m-d H:i:s', strtotime($twitter['updated']));
//もしURLがセットされていたら
  if(isset($twitter_array[$val]['url'])){
  //画像出力用のURL
  foreach($twitter_array[$val]['url'] as $url){
  
  if(strstr($url,"twitpic") == false){
  //ツイート内容にhrefでリンクを付ける
  $twitter_array[$val]['text'] .= '<a href="'.$url.'">'.$twitter['title']."</a>";
  }else{
  $str = substr($url, -6);
$twitter_array[$val]['text'] .= '<a href="'.$url.'"><img src="http://twitpic.com/show/full/'.$str.'.jpg"/></a>';
}
}
}else{
  //Tweet中にURLが特に含まれていなかったら
  $twitter_array[$val]['text'] = $twitter['title']; 
  }
  }

//Twitter投稿をWordpressに登録する
  foreach($twitter_array as $view){
//最終投稿より、日時が新しければ登録実行
  if($res[0]['post_date'] < $view['updated']){

$mdb2->exec("INSERT INTO `wp_posts` (`post_author`, `post_date`, `post_date_gmt`, `post_content`, `post_title`, `post_excerpt`, `post_status`, `comment_status`, `ping_status`, `post_password`, `post_name`, `to_ping`, `pinged`, `post_modified`, `post_modified_gmt`, `post_content_filtered`, `post_parent`, `menu_order`, `post_type`, `post_mime_type`, `comment_count`) VALUES
  (1, '{$view['updated']}', '{$view['updated']}', '{$view['text']}', '{$view['title']}', '', 'publish', 'open', 'open', '', 'test', '', '', '{$view['updated']}', '{$view['updated']}', '', 0, 0, 'post', '', 0)");
}
}