Home

Shin x blog

Twitter 検索

この記事の所要時間: 040

先日はじめたTwitterですが、なかなか楽しいです。

Twitterの仕組み自体ももちろん面白い良いのですが、日々ユーザが増えていき、システムが改良され(今日は日本語入力が改善されたもよう)、どんどん完成度が高まっていくさまが何だか楽しいです。

で、ちょうどCakePHPで何か作ろうと思っていたので、こんなの作ってみました。

Twitter 検索

Twitter 検索 : PHPで検索

Twitterの検索では、既にtwittersearchがあるのですが、それとは違いこちらは日本語ユーザのみの検索ができます。

興味のあるキーワードを入れて、Friends探しに使って貰えたら良いかと。

# 超見切り発車気味な公開なので、突然消える可能性もありますが。;-)

Twitterで一人言

この記事の所要時間: 059

ちまたで話題のTwitterはじめてみました。

http://twitter.com/shin1x1

当初IMのようなサービスだと思っていたので、登録はしたものの身近でやっている人もいないので2,3日放置していました。

で、今日何気に眺めているとIMとは違うものだと何となく気づきました。(遅)

IMというよりはどちらかというとblogの方が近いのかな。

ようは相手がいて初めて成り立つものではなく、基本は自分から発信するだけで、あとはそれを見た誰かが反応を返すものだと。

blogのような情報発信 + IMのような手軽さ + SNSのような繋がり / 3 といった感じですかね。(SBMのコメントを書く感覚にも近いような)

「Twitter」は「さえずり」だそうです。自分で使った感触では「さえずり」というより、ぼそぼそ言う「一人言」という感じでした。

一人言でも何気に面白いので、「相手がいない」と躊躇している方も一度始められてはいかがでしょうか。

# やってみようかな、という人には「第1回 Twitterキホンのキホン|gihyo.jp」が参考になりますよ。

CakePHP SQLをログに記録

この記事の所要時間: 227

CakePHPで発行したSQLをログに記録する方法です。

DEBUG>=2にすれば画面下に表示されるSQL文ですが、DB処理後にリダイレクト等で遷移すると消えてしまいます。さらに本番稼働時は画面に表示するわけにはいかないのでやはりログに出力したいところです。

フレームワークに手を入れるのが一番簡単なのですが、バージョンが上がると面倒なので既存のDboSourceを継承したクラスにログ記録を追加します。

1. DboSourceを継承

dboはフレームワークで用意されているものだけでなく、app/model/dboにあるものもフレームワークで利用する事ができます。

ここではPostgreSQLを使うとしてDboPostgresを継承したDboPostgresLogを作ります。

ログ出力をON/OFFする定数LOG_SQLは後でcore.phpで定義します。

[app/model/dbo/dbo_postgres_log.php]

<?php
uses ('model' . DS . 'dbo' . DS . 'dbo_postgres');

class DboPostgresLog extends DboPostgres {
  /**
   * @var integer
   */
  var $queryNo = 1;

	function execute($sql) {
    $ret = parent::execute($sql);

    if (defined('LOG_SQL') && LOG_SQL) {
      $this->log(sprintf("%d. %s", $this->queryNo, $sql), LOG_DEBUG);
      $this->queryNo++;
    }

    return $ret;
	}
}
?>

2. 作成したDboPostgresLogを使用する

DATABASE_CONFIGのDB設定でdriverを’postgres_log’を指定します。

[app/config/database.php]

class DATABASE_CONFIG
{
  var $default = array('driver' => 'postgres_log',
                       'connect' => 'pg_connect',
                       'host' => 'localhost',
                       'login' => 'user',
                       'password' => 'pass',
                       'database' => 'foo',
                       'prefix' => '');
}

3. core.phpでLOG_SQLを定義

SQLをログに出力するか否かを設定するLOG_SQLをcore.phpで定義します。

LOG_SQLがtrueならSQL出力し、LOG_SQLが未定義もしくはfalseの場合は出力しません。

[app/config/core.php]

<?php
/**
 * If set to true, logging sql queries
 */
	define('LOG_SQL', true);
?>

これで実行されたSQL文が[app/tmp/logs/debug.log]に出力されます。

この方法はDEBUGの値に関係無くログ出力ができるのは良いのですが、DboSourcesを継承するのがイマイチです。フレームワーク(DboSources自身)で対応して貰えれば一番良いですけどね。;-)

Firecakeのコメントにcakeinfoが

この記事の所要時間: 027

FirecakeはCakePHPのデバッグ情報をFirebugに表示する便利なHelperです。

Bakeryでソースを見ているとコメントにこんな記述が。

Looking for more ideas, I also used cakeinfo.php, * a script released under MIT license by Masashi Shinbara.

cakeinfoを参考にして頂いているようです。嬉しい事です。

PostgreSQL 誤って削除したデータを復元する

この記事の所要時間: 037

PostgreSQLの仕組みを考えれば「なるほど」な内容なのですが、実際にできるんですね。

VACUUM していなければ、データベースファイル内に残っている可能性があります。 トランザクションIDをDELETE 文を発行した時点よりも昔に「巻き戻す」ことで、 削除したデータが再び見えるようにできるかもしれません。

[pgsql-jp: 38276] Re: データの復旧について

トランザクションIDを戻せばOKなのか。うーんスゴイ。

CVSやSubversionでリビジョンを指定する感覚に似ているかも。(そこまで柔軟じゃないか)

間違ってDELETE/UPDATEした時は慌てず騒がず、この方法を思いだそ。

CakePHP Model#save()内でvalidates()を呼ばない

この記事の所要時間: 11

ref: CakePHPの何か-CakePHPのModelを使う

お馴染みyandoさんのプレゼン資料で気になったソースがあったので勝手に添削w。

35p:Validation設定例

<?php
class UsersController extends AppController {
  function fuga(){
    $data&#91;'User'&#93; = array(
      'login_id' => '+*+*+*+*',
      'password' => 'abcde',
      'name' => ''
      );
      if ($this->User->validates($data)) {
        $this->User->save($data);
      } else {
        $this->validateErrors($this->User);
      }
   }
}
?>

User#save()の部分ですが、Model#save()メソッド内ではModel#validates()が呼ばれるので、このままだとUser#validates()が2度実行されることになります。

このソースのようにsave()の前にvalidates()を実行するならsave()の第2引数にfalseを渡します。これならsave()内でvalidates()は実行されません。

<?php
      if ($this->User->validates($data)) {
        // validates()はsave()内では呼ばれない
        $this->User->save($data, false);
      }
?>

あとこの例のようにController#validationErrorsを参照しないのなら、Controller#validateErrors()は呼ばなくても良いです。

なので↓のようにシンプルに書けたりします。

<?php
class UsersController extends AppController {
  function fuga(){
    $data&#91;'User'&#93; = array(
      'login_id' => '+*+*+*+*',
      'password' => 'abcde',
      'name' => ''
      );
      $this->User->save($data);
   }
}
?>

まあ実際は登録完了後はリダイレクトしたりビューテンプレートを変えたりするので結局上のソースのようになるのですが。;-)

URLをリンクにするSmartyプラグイン

  • 2007-03-30 (金)
  • PHP
この記事の所要時間: 041

テキスト中にURLが含まれている場合にそれをaタグで囲むSmartyプラグインです。

既にありそうなのですが見つけられなかったので作りました。よろしければどうぞ。

modifier.url_link.php

<?php
/*
 * Smarty plugin
 * URL to link
 *
 * @param  string $value
 * @param  string $target
 * @return string
 */
function smarty_modifier_url_link($value, $target = null) 
{
    $options = "";
    if (!empty($target)) {
      $options = sprintf(" target=\"%s\"", $target);
    }

    $value = ereg_replace("&#91;&#91;:alpha:&#93;&#93;+://&#91;^<>[:space:]]+[[:alnum:]/]",
                         "<a href=\"\\0\"" . $options . ">\\0</a>", $value); 
    return $value; 
}
?>

plugins/ディレクトリに設置すれば↓のように使えます。

{$text|escape|url_link}

aタグにtarget属性を付加する場合は設定する値を渡します。

{$text|escape|url_link:"_blank"}

Smartyはビューテンプレートでちょっとした加工ができるので便利です。SmartyテンプレートがPHP以外の言語でも使えたら良いのに。

svn log –xml

この記事の所要時間: 131

Yesterday I was struggling trying to get svn log to display the results for a certain user and this was very annoying.. then I jumped on #svn on freenode, and someone mentionned svn log –xml

SVN log-per-user parser using SimpleXML – David Coallier

svn logをXMLで出力できるんですね。知りませんでした。。。

試しにCakePHP1.1.xリポジトリのログを出力してみました。

$ svn log --verbose --limit 10 --xml 
<?xml version="1.0"?>
<log>
<logentry
   revision="4693">
<author>phpnut</author>
<date>2007-03-27T04:32:47.490451Z</date>
<paths>
<path
   action="M">/branches/1.1.x.x/cake/config/config.php</path>
<path
   action="M">/trunk/cake/1.1.x.x/cake/config/config.php</path>
<path
   action="M">/branches/1.1.x.x/cake/VERSION.txt</path>
<path
   action="M">/trunk/cake/1.1.x.x/cake/libs/session.php</path>
<path
   action="M">/trunk/cake/1.1.x.x/cake/VERSION.txt</path>
</paths>
<msg>Merging fixes into the trunk

Revision: [4692]
Merging fix for Ticket #2295</msg>
</logentry>
</log>

SimpleXmlElementなんかでパースすればすぐに使えそうです。さて何に使おうかなー。

SmartyでSJISテンプレートを使う

  • 2007-03-27 (火)
  • PHP
この記事の所要時間: 032

SmartyテンプレートをSJISで書いていた時に「本」等の文字でSmartyパースエラーが発生していました。

「本」はSJISで[0x967B]なので、[0x7B]がSmartyのデリミタ[{]として評価されパースエラーになります。

これは{literal}{/literal}で該当文字を囲めば回避することができます。

{literal}本文{/literal}

またSmaryのデリミタを変える事もできるので、この方法で回避することもできそうです。

ref:Smartyの構文解析を回避

PHPからPostgreSQLに大量のデータを登録する

  • 2007-03-16 (金)
  • PHP
この記事の所要時間: 18

PostgreSQLに大量のデータを登録する際はINSERTを使って一件づつ処理するより、COPYを使って一気に登録した方が実行速度が(かなり)速いです。

そこでPHPでもCOPY文を使ってみましょう。

pg_copy_fromを使う

登録するデータが配列に入っているならpg_copy_fromだけで一気に処理できます。

配列の1要素が1レコードに対応しています。1要素内では各カラムをデリミタ(デフォルトは”\t”)で連結します。

<?php
$values = array();
$values&#91;&#93; = "1\tname1";
$values&#91;&#93; = "2\tname2";
$values&#91;&#93; = "3\tname3";

$db = pg_connect("dbname=hogedb");
pg_copy_from($db, 'table', $values);
?>

単純なCSVならデリミタを[,]に変えればokです。

<?php
$values = array();
$values&#91;&#93; = "1,name1";
$values&#91;&#93; = "2,name2";
$values&#91;&#93; = "3,name3";

$db = pg_connect("dbname=hogedb");
pg_copy_from($db, 'table', $values, ',');
?>

pg_put_lineを使う

登録するデータを一件ずつ処理したいならpg_put_lineで1レコードずつ出力する方法します。

はじめにCOPY文を発行しているので、デリミタの指定などSQL内で変更できます。

登録データ出力後に[\.]を発行してから、最後にpg_end_copyを呼ぶ必要がありますのでご注意を。

<?php
$db = pg_connect("dbname=hogedb");
pg_query($db, "copy table from stdin");
for ($i = 1 ; $i <= 10 ; $i++) {
  $line = sprintf("%d\tname%d\n", $i, $i);
  pg_put_line($db, $line);
}
pg_put_line($db, "\.\n");
pg_end_copy($db);
?>

ちなみにPostgreSQLではCOPY文もトランザクション内に含める事ができます。当然ROLLBACKも可能です。

数万件レベルのデータでも体感できる程パフォーマンスが違うので、もし知らない方は一度お試しあれ。

Home

検索
フィード
メタ情報

Return to page top