HOME > blog

お久し振りです、松岡です。
過去からのしがらみもあって UCWD-Studio. としてのお仕事も今なお若干残っているのですが、普段のお仕事について でもご紹介させていただいてます通り、最近は一年半ほど前に設立しました 合同会社ブリューア・リンクス での仕事が中心になるようシフトしております。

それに伴って、せっかくなので本サイトも営業用のサイトという位置づけ(ではあったものの単に仕事中に調べたりした技術系Tipsのブログと化してましたがw)から、会社やそこでの業務から一歩離れたところからでもっと色々とアウトプットできるサイトへ趣旨替えをしようかな、と思ったのが今回のリニューアルのきっかけでした。

(さらに…)

今年の春辺りにようやくPHP5.3がバージョン別シェアの首位に踊りでたそうで、そろそろPHP5.3移行で導入された機能も本格的に取り入れ頃かな?と考えてる人も多いはず。ということで名前空間。

名前空間についてはphp.netのオンラインマニュアルで結構分かりやすくまとめられているのですが、分量がそれなりに多いのでそれを整理・要約してみます。

(さらに…)

タグ:

相変わらず需要が読めないんですが macports ネタ。記憶の限りでは随分昔のバージョンでは所定の手順で launchctlload すれば macports でインストールした apache2 もOS起動時に自動起動できたはずなのですが、いつの間にかそういう設定にはならなくなったようで。

ただ、実際には OS 起動時にちゃんと load はされてるようで、

sudo launchctl load -w /Library/LaunchDaemons/org.macports.apache2.plist
org.macports.apache2: Already loaded

と返ってきます。ps で確認すると

ps aux | grep httpd
_www             133   0.0  0.0  2436172    704   ??  S    火08PM   0:00.00 /usr/sbin/httpd -D FOREGROUND
root              25   0.0  0.0  2436172   4324   ??  Ss   火08PM   0:07.01 /usr/sbin/httpd -D FOREGROUND

MacOS X 標準の apache2 は立ち上がってるみたいですが macports でインストールした apache2 は動いてない……。macports を利用されてる場合、このケースで悩んでる方がそれなりにいるんじゃないかなぁ?と想像してます。僕自身がしばらくそうだったので。

ということで結構今更感あるのですが、macports 経由で apache2 をインストールして自動起動の設定を施すまでをおさらいしてみようと思います。

(さらに…)

タグ: ,

WordPressで(現在)日時を取得しようとして date() を利用すると UTC で返ってきていつも「えぇ?」となるので備忘録として残しときます。

WordPress の wp-load.php が存在するディレクトリ上に次のコードを置いて実行してみると以下のように返ってきます。

<?php
echo date_default_timezone_get() ."\n";
echo date("Y-m-d H:i:s") ."\n";

require "wp-load.php";
echo date_default_timezone_get() ."\n";
echo date("Y-m-d H:i:s") ."\n";
Asia/Tokyo
2013-06-04 11:53:28
UTC
2013-06-04 02:53:28

wp-load.php を通すと wp-config.php を経由してインクルードされる wp-settings.php にて、

// WordPress calculates offsets from UTC.
date_default_timezone_set( 'UTC' );

と定義されている都合から、time()date() といったPHP標準の日時関連の関数は UTC で値を返してきます。

(さらに…)

タグ:

WordPressのプラグイン作成時などでwpdbクラスを利用する際、MySQLのDATE_FORMAT()関数などの日時フォーマット用書式指定子とwpdbクラスのprepareメソッドのプレースホルダーが競合するので、

<?php
// wp-load.phpと同じディレクトリにこのサンプルコードが有る場合
require_once 'wp-load.php';

global $wpdb;
echo $wpdb->get_var( $wpdb->prepare(
    "SELECT DATE_FORMAT(%s, %s)",
    date('Y-m-d H:i:s', current_time('timestamp')),
    '%Y年%m月%d日'
) );

// "SELECT DATE_FORMAT(%s, '%Y年%m月%d日')" とかやっちゃうとハマる

といった具合にしておけば動くんですけど、wpdbクラスってSQLの文法エラーが発生してもエラーメッセージを表示する記述を追記しておかないとそこで止まって終わり、Webサーバのエラーログにも何も落ちない、サーバステータスは200 OKを返してくれるで「え?」となりがち。

タグ:

以前、jQuery.ready()とloadイベントって具体的にはタイミングがどう変わるんだろね?という話になってちょっと調べ……たのも以前の話、なのですが……。

ぐぐってみると ページ読み込み時に実行するjavascriptについてのTips | Tips Note というページが見つかって、そのページでは

■処理を実行するタイミングの違い
onloadイベントとjQueryのreadyメソッドは
処理を実行するタイミングが異なります。

jQueryのready()メソッド
DOMツリーの構築が完了した時点で処理を実行する。
onloadイベント
DOMツリーの構築だけでなく、画像などの関連データの読み込みが完了しないと処理を実行しない。

と書かれています。

では、実際に試してみましょう。まずベースとなるHTML+JavaScriptを以下のように準備します。

<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8" />
<title>jQuery.ready()とloadイベント&#064;UCWD-Studio.</title>
<script src="http://ucwd.jp/wp-includes/js/jquery/jquery.js"></script>
<script>
jQuery( function () {
    jQuery(window).load( function () {
        jQuery("#report").append('<p>load: ' + now() +'</p>');
    });

    jQuery("#report").append('<p>ready: ' + now() + '</p>');
});

function now () {
    var dt = new Date();
    return dt.toLocaleString();
}
</script>
</head>
<body>
<h1>Event Test</h1>
<div id="just_a_minute"><iframe src="./just_a_minute.php"></iframe></div>
<div id="report"></div>
</body>
</html>

で、iframe内に表示するファイルをPHPで以下のように準備します。

<?php
sleep(10);
header('Content-type: text/plain; charset=utf-8');
echo 'iframe loaded.';
?>

ポイントは sleep() を使ってわざとレスポンスを遅らせてる点です。すると、$.ready() の方はさっと表示されるのに対し、loadイベントの方は iframe 内が読み込まれるまで表示されないのが実際に確認できます。

サンプルを用意してるので実際に確認してみてください。

タグ:

前回のTengのリファレンスに続き、今度はAmon2Tengを利用するケース。これは amon2-setup.pl を実行する際に flavor に Teng を指定するとすぐに利用できるようになります。以下、一応手順。

  1. Amon2, Teng, Amon2::Setup::Flavor::Teng が入ってない場合はインストール
    $ cpanm Amon2 Teng Amon2::Setup::Flavor::Teng
  2. 任意の場所で Amon2 のスケルトンを作成。この際 flavor に Teng を指定
    $ amon2-setup.pl --flavor=Basic,Teng MyApp

amon2-setup.pl を実行すると指定したプロジェクト名(上の例では MyApp)のディレクトリとともにスケルトンが作成されます。

use File::Spec;
use File::Basename qw(dirname);
my $basedir = File::Spec->rel2abs(File::Spec->catdir(dirname(__FILE__), '..'));
my $dbpath = File::Spec->catfile($basedir, 'db', 'development.db');
+{
    'DBI' => [
        'dbi:mysql:DB_NAME', 'DB_USER', 'DB_PASSWORD',
        +{
            'mysql_enable_utf8' => 1,
        }
    ],
};

で、MyApp/config/development.pl に接続したいDBの設定を追記すると、

package MyApp::Web::Dispatcher;
use strict;
use warnings;
use utf8;
use Amon2::Web::Dispatcher::Lite;

any '/' => sub {
    my ($c) = @_;

    my $row = $c->db->single({'id' => 1});

    return $c->render('index.tt', {
        'test' => $row->name,
    });
};

といった具合(ここで触ってるのは MyApp/lib/MyApp/Web/Dispatcher.pm)に Teng を利用してDB接続できるようになります。

(さらに…)

タグ: , , ,

今回は Perl の O/Rマッパー Teng を触ってみます。特に触れない限りMySQLを利用しているということにして、コードのサンプルは DB名 teng_test / 利用するテーブルは users / そのテーブルレイアウトは

mysql> SHOW FIELDS FROM users;
+---------------+------------------+------+-----+---------+----------------+
| Field         | Type             | Null | Key | Default | Extra          |
+---------------+------------------+------+-----+---------+----------------+
| id            | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| name          | varchar(50)      | NO   |     | NULL    |                |
| birth_date    | date             | NO   |     | NULL    |                |
| created_date  | datetime         | YES  |     | NULL    |                |
| modified_date | datetime         | YES  |     | NULL    |                |
+---------------+------------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)

に接続する例、ということにしておきます。

まず最初に、インストールは他の CPANモジュール同様 cpanm で。(入ってなければ) 合わせて DBD::mysql (ここは利用するDBに合わせて任意で)も入れます。cpanm を利用している場合は

$ cpanm Teng DBD::mysql

でインストールが完了します。

次に簡単な使い方を。以下は id が1 のレコードを1件取得して name の値を出力する例。

use strict;
use warnings;
use utf8;
use Teng;
use Teng::Schema::Loader;

my $dsn    = 'dbi:mysql:teng_test';
my $user   = 'db_user';
my $passwd = 'db_password';

my $dbh = DBI->connect($dsn, $user, $passwd, {
    'mysql_enable_utf8' => 1,
});

my $teng = Teng::Schema::Loader->load(
    'dbh'       => $dbh,
    'namespace' => 'MyApp::DB',
);

my $row = $teng->single('users', {'id' => 1});
print $row->name;

1;

Tengクラスのインスタンスを作る部分を分離して書くこともできます。

次のコードを teng_instance.pl として……

use strict;
use warnings;
use utf8;
use Teng;
use Teng::Schema::Loader;

my $dsn    = 'dbi:mysql:teng_test';
my $user   = 'db_user';
my $passwd = 'db_password';

my $dbh = DBI->connect($dsn, $user, $passwd, {
    'mysql_enable_utf8' => 1,
});

my $teng = Teng::Schema::Loader->load(
    'dbh'       => $dbh,
    'namespace' => 'MyApp::DB',
);
1;

以下のように、インクルードすることもできるらしいです。

use strict;
use warnings;
use utf8;

my $teng = do('teng_instance.pl') or die $@;

my $row = $teng->single('users', {'id' => 1});
print $row->name;

1;

(さらに…)

タグ: ,

今回は ubuntu12.04 に node.js の開発環境を整えてみます。一応、aptitude からインストールすることもできますけど、この記事を書いてる段階では v0.6.12 と結構古いバージョンが入っちゃいます。また、http://nodejs.org/download/ からバイナリーパッケージをダウンロードしてインストールすることもできますけど、node.js は開発速度が早いので creationix/nvm · GitHub などのマネージャからインストールした方が良さげです。

前に挙げた nvm のページにもインストール方法が掲載されてますが、git が入っていれば

$ git clone git://github.com/creationix/nvm.git ~/nvm
$ . ~/nvm/nvm.sh

nvm コマンドが使えるようになります。node.js のインストールは nvm install [バージョン]で実行します。

$ nvm install v0.8.20
######################################################################## 100.0%
Now using node v0.8.20

インストールが成功すると自動的にそのバージョンの node use も合わせて実行してくれるので、そのまま利用できます。

その時点でインストール可能な node.js のバージョンを確認したい場合、nvm ls-remote で確認できます。以下のように結果が返ってきます。

$ nvm ls-remote
   v0.1.14          v0.3.5         v0.6.19
   v0.1.15          v0.3.6         v0.6.20
   v0.1.16          v0.3.7         v0.6.21
   v0.1.17          v0.3.8          v0.7.0
   v0.1.18          v0.4.0          v0.7.1
   v0.1.19          v0.4.1          v0.7.2
   v0.1.20          v0.4.2          v0.7.3
   v0.1.21          v0.4.3          v0.7.4
   v0.1.22          v0.4.4          v0.7.5
   v0.1.23          v0.4.5          v0.7.6
   v0.1.24          v0.4.6          v0.7.7
   v0.1.25          v0.4.7          v0.7.8
   v0.1.26          v0.4.8          v0.7.9
   v0.1.27          v0.4.9         v0.7.10
   v0.1.28         v0.4.10         v0.7.11
   v0.1.29         v0.4.11         v0.7.12
   v0.1.30         v0.4.12          v0.8.0
   v0.1.31          v0.5.0          v0.8.1
   v0.1.32          v0.5.1          v0.8.2
   v0.1.33          v0.5.2          v0.8.3
   v0.1.90          v0.5.3          v0.8.4
   v0.1.91          v0.5.4          v0.8.5
   v0.1.92          v0.5.5          v0.8.6
   v0.1.93          v0.5.6          v0.8.7
   v0.1.94          v0.5.7          v0.8.8
   v0.1.95          v0.5.8          v0.8.9
   v0.1.96          v0.5.9         v0.8.10
   v0.1.97         v0.5.10         v0.8.11
   v0.1.98          v0.6.0         v0.8.12
   v0.1.99          v0.6.1         v0.8.13
  v0.1.100          v0.6.2         v0.8.14
  v0.1.101          v0.6.3         v0.8.15
  v0.1.102          v0.6.4         v0.8.16
  v0.1.103          v0.6.5         v0.8.17
  v0.1.104          v0.6.6         v0.8.18
    v0.2.0          v0.6.7         v0.8.19
    v0.2.1          v0.6.8         v0.8.20
    v0.2.2          v0.6.9          v0.9.0
    v0.2.3         v0.6.10          v0.9.1
    v0.2.4         v0.6.11          v0.9.2
    v0.2.5         v0.6.12          v0.9.3
    v0.2.6         v0.6.13          v0.9.4
    v0.3.0         v0.6.14          v0.9.5
    v0.3.1         v0.6.15          v0.9.6
    v0.3.2         v0.6.16          v0.9.7
    v0.3.3         v0.6.17          v0.9.8
    v0.3.4         v0.6.18          v0.9.9

実際はインストール済みのバージョンは青色など色を変えて表示してくれます。

ちなみにこのままだとサーバへ繋ぐ度に . ~/nvm/nvm.shnvm use [バージョン] を実行する必要が出てくるので、.bashrcに

source $HOME/nvm/nvm.sh
nvm use 0.8.20 >/dev/null

を追記しておくと良いでしょう。この場合、使用する node.js のバージョンは 0.8.20 に固定されますが、

source $HOME/nvm/nvm.sh
nvm use 0.8 >/dev/null

とすると0.8系で最新のバージョンが利用でき、

source $HOME/nvm/nvm.sh
nvm alias default 0.8.18 >/dev/null

としておくと 0.8.18 が利用できるようになった上で、 0.8.18 には “default” でエイリアスが指定されるようになるので、以降 node.js のバージョンを切り替えても

$ nvm use default
Now using node v0.8.18

と、nvm use default でエイリアス指定した 0.8.18 を呼び戻せるようになります。とりあえず、

var http = require('http');

http.createServer(function (req, res) {
    res.writeHead(200, {'Content-type': 'text/plain'});
    res.end('Hello World.\n');

}).listen(8124, '0.0.0.0');

console.log('Server running at http://localhost');

と記述したファイルを

  1. test.js などと命名した上で保存
  2. そのファイルを作成したディレクトリから node test を実行
  3. ブラウザで http://localhost:8124/ へアクセス(node.js の環境構築先が localhost の場合)

これでブラウザに “Hello World.” と表示されれば無事 node.js のインストールは完了です。

次は node.js で開発し始めると何かとお世話になる npm について。npm は node.js をインストールするとセットで自動的にインストールされます。なので、node -v でバージョンが返ってくる状態なら通常 npm コマンドも有効になってるはずです。試しに npm -v を実行すると

$ npm -v
1.2.11

と npm のバージョンが返ってきます。

npm は Node Packaged Modules の略でその名の通り node.js のパッケージ管理ツールです。npm help を確認してみると npm には色々なコマンドの存在を確認できますが、よく利用するのは

npm install パッケージ名

指定したパッケージをインストールします。パッケージ名に続けて @バージョン を追記して実行すると指定のバージョンでインストールできます。なお、指定したパッケージが依存するパッケージも自動的にインストールされます。

また、-g オプションを付加するとグローバルインストールとなり、npm が存在する場所へインストールされます。例えば express という node.js のWebアプリケーションフレームワークがありますが、これを npm install -g express でグローバルインストールすると、express が入った mode_modules ディレクトリにパスが通ってない場所からも express のスケルトン作成のためのコマンドが実行できるようになります。

npm list
実行したディレクトリから見てパスの通っているパッケージの一覧を返します。node.jsインストールの際に合わせてインストールされるパッケージや -g オプション付きでインストールしたパッケージは含みません。それらのリストを見たい場合は npm list -g を実行します。
npm update <パッケージ名>
インストール済みのパッケージを最新バージョンへアップデートします。パッケージ名は半角スペース区切りで複数指定可能で、npm update outdated とすることで最新バージョンでない全てのパッケージを一括アップデートすることもできます。
npm uninstall パッケージ名
指定したパッケージをアンインストールします。
npm search 検索したい文字列
パッケージレジストリから”検索したい文字列”を検索します。パッケージ名を検索しようとしてもパッケージ名だけにヒットするとは限らないので、ちょっと使いにくいかも。

といったところになるんでしょうか。

タグ:

少々前の話になるのですが、このサイトをレスポンシブWebにしてみました。実際の作業を通してPCサイトをレスポンシブWeb化する際に注意しておくべき点などについて整理しておきたいと思います。

CSS3にほとんど馴染みがない場合、どうしても知識のベースがCSS2に基づく事になると思うので、どことなくややこしそうな印象も抱えがちになりますが実装すること自体はとても簡単で、

  • CSS3で拡張された media queries で任意の条件を指定した上でその条件に当てはまる場合のCSSを記述する

大雑把にこれだけです。スマートフォン対応を想定する場合、スマホの画面領域に最適化させるためviewportの指定など、ほかにも手を加える箇所は出てきますが、レスポンシブWebに限ればこれだけで実現可能です。ただ、これだけでは意外と手順は少ないらしい以上の情報が含まれてないので、簡単な例を挙げてみましょう。

(さらに…)

タグ: ,