Posts tagged PHP

WordPress に「はてなスター」を導入してみました

0

はてなスターを導入してみました。

このブログは WordPress でやっています。
はてなスターはじめてガイド – Hatena Starに対応ブログサービスに入っていたので早速 JavaScritp コードを header.php の の前に入れてみました。
ところが、サイドメニューの「Category」などの横に表示されてしまいました。
どうも h3タグの中のaタグに☆ボタンを入れているようです。

再度、はてなスターはじめてガイド を見ると

技術的な詳細については、HatenaStar.js下部のドキュメント(英語)をご覧ください。

とあります。早速ソースを見てみると最後の方に色々とドキュメントが書かれています。

// This is the optional script for WordPress blogs
<script src=”http://s.hatena.com/js/Hatena/Star/EntryLoader/WordPress.js” type=”text/javascript”></script>

とありました。

で、

<script src="http://s.hatena.ne.jp/js/HatenaStar.js" type="text/javascript"></script>
<script src="http://s.hatena.com/js/Hatena/Star/EntryLoader/WordPress.js" type="text/javascript"></script>

と書くことにより、うまく行きました^^

さらにコメントをつけられるように、自分のブログを登録します。登録すると新たにコメントを付けられる JavaScript が発行されるので、それを追加すると。。。また、h3タグの後ろに☆ボタンが。。。

よくみるとブログ登録後に発行された JavaScritp の1行目は HatenaStar.js を読み込むもので、一番最初に貼り付けたコードと同じでした orz
で、結局ブログ登録後に発行された JavaScript と WordPress.js を読み込む JavaScript を貼り付けることにより、うまく行きました。

ブログ登録後に表示されるコードはトークンが追加されたということですね。

CakePHP アソシエーションのまとめ(2)

0

アソシエーションのまとめ(1) で書いた

< ?php
class User extends AppModel
{
    var $name = 'User';
    var $hasOne = array('Profile' =>
                    array('className' => 'Profile',
                          'conditions' => '',
                          'order' => '',
                          'dependent' => true,
                          'foreignKey' => 'user_id'
                    )
                  );
}
?>

この部分の補足です。
それぞれの意味するところは

var $hasOne = array('関連先のモデル名'=>
                array('className'  => '関連先のモデルのクラス名',
                      'conditions' => '関連を定義するSQL条件の一部',
                      'order'      => '関連先のデータの並び順',
                      'dependent'  => '関連先データの同時削除',
                      'foreignKey' => '関連先テーブル側の外部キー'
                )
              );

conditions は条件を付けて関連付けるモデルのデータを制限するときに指定する。
dependent は関連元のデータが削除されたときに、一緒に関連先のデータも削除するかどうか。
関連先のモデルで関連元のモデルの主キーを定義しているカラム名です。

dependent などはかなり便利に使えそうですね。
アソシエーションのまとめ(1) に書いたように、 foreignKey は CakePHP の命名規則に従っていれば省略可能です。

CakePHP アソシエーションのまとめ(1)

1

CakePHP のアソシエーションのまとめです。
タイトルに (1) とつけたので多分何回か続けます。

アソシエーションとはモデル間のつながりのことです。

例えば、下記のような2つのテーブルがあると

CREATE TABLE users(
    id int unsigned auto_increment primary key,
    nickname varchar(30) NOT NULL,
    created datetime default NULL,
    modified datetime default NULL
);

CREATE TABLE profiles(
    id int unsigned auto_increment primary key,
    user_id int unsigned unique,
    blog_url varchar(256),
    hobby varchar(256),
    created datetime default NULL,
    modified datetime default NULL
);

CakePHP では2つのモデルになります。
User モデルと Profile モデルです。
この2つのモデルは1対1の関係になります。
「一人のユーザは1つのプロファイルを持つ」とういことです。

この2つのモデルの関係を CakePHP に指示するには次のようになります。

< ?php
class User extends AppModel
{
    var $name = 'User';
    var $hasOne = array('Profile' =>
                    array('className' => 'Profile',
                          'conditions' => '',
                          'order' => '',
                          'dependent' => true,
                          'foreignKey' => 'user_id'
                    )
                  );
}
?>

これで、
$this->User->findById($id);とすることにより、

Array
(
    [User] => Array
        (
            [id] => 1
            [nickname] => boze
        )
    [Profile] => Array
        (
            [id] => 1
            [blog_url] => http://www.syuhari.jp/blog
            [hobby] => 読書
        )
);

のようにUser モデルだけでなく、Profileモデルの情報も同時に取得することができます。

CakePHP の命名規則を守っていれば、
var $hasOne = array('Profile');だけでもいけるようです。
※外部キーはモデル名+_id

CakePHP 日本語マニュアル
6.4. アソシエーション

PHPフレームワークのベンチマーク

0

PHPベンチマーク: Zend Framework vs Symfony vs CakePHP vs CodeIgniter vs PHP on TRAX – 徒然なるままにBlog

  • Zend-Framework
  • Symfony
  • CakePHP
  • Codelgniter
  • PHP on TRAX

のベンチマーク結果が載っています。

ただ、

モデル作成を行わないはずなのにCakePHPだけモデルが生成されるようになっていました。
PHPベンチマーク CakePHPでモデルを使用しない | Shin x blog

なので、是非CakePHP もモデル使用しないソースで実行した結果を見てみたいですね。

実行環境が元エントリとは異なるので絶対的な数値にはあまり意味が無いですが、両者を比べるとモデル生成なしの方が20%ほど速いようです。
PHPベンチマーク CakePHPでモデルを使用しない | Shin x blog

モデル使用しないと20% ほど早いそうです。

CakePHP HtmlHelper::tagValue のHTMLエスケープ処理

1

view でモデルの値などを出力する際に
$html->tagValue("Model/hoge");
とすれと、HTMLエスケープ処理をしてくれるので便利です。

ただ、
CakePHP 1.1.15.5144以降はHtmlHelper#tagValueに注意 | Shin x blog
に書かれているように、CakePHP のバージョン1.1.15.5144 からエスケープするかのフラグが追加されたようです。

以前はエスケープしないを選択できなかったので、それはそれで不便な点もありました。
MOONGIFT ブログ ? CakePHP覚書(HTML Helpler)

しかし今回の変更で注意しなければいけないのは、デフォルトでエスケープされていたのがデフォルトでエスケープ処理されなくなったことです。

cake/libs/view/helpers/html.php
function tagValue($fieldName, $escape = false)

以前のようにエスケープ処理させるには
$html->tagValue("Model/hoge", true);
とする必要があります。

また、

ちなみに1.2.0.5147ではtagValueがdeprecatedになっており、代わりにvalueメソッドを使うようになるようです。

ということになるようです。

CakePHP flash メソッドでレイアウトを指定する

2

コントローラ毎にレイアウトを変えていていると flash メソッドは使えないなあと思っていたのですが、下記のようにすることによりレイアウトをコントローラで指定できますね。

/app/app_controller.php に下記の flash メソッドを追加

function flash($message, $url, $pause = 1) {
    $this->autoRender = false;
    $this->autoLayout = false;
    $this->set('url', $this->base . $url);
    $this->set('message', $message);
    $this->set('pause', $pause);
    $this->set('page_title', $message);

    if (file_exists(VIEWS . 'layouts' . DS . $this->layout.'_flash.thtml')) {
        $flash = VIEWS . 'layouts' . DS . $this->layout.'_flash.thtml';
    } elseif ($flash = fileExistsInPath(LIBS . 'view' . DS . 'templates' . DS . "layouts" . DS . 'flash.thtml')) {
    }
    $this->render(null, false, $flash);
}

これで、
/app/views/layouts/指定したレイアウト名_flash.thtml
というレイアウトファイルがあれば、それを使用して
なければ、デフォルトの flash.thtml を使用します。

やっていることはすごく単純でコントローラクラスの flash メソッドをオーバライドして、使用するレイアウトファイルを選択するところで

if (file_exists(VIEWS . 'layouts' . DS . 'flash.thtml')) {
    $flash = VIEWS . 'layouts' . DS . 'flash.thtml';
}

となっていたところを

if (file_exists(VIEWS . 'layouts' . DS . $this->layout.'_flash.thtml')) {
    $flash = VIEWS . 'layouts' . DS . $this->layout.'_flash.thtml';
}

に変更しただけです。

他にいい方法があれば教えてください。

CakePHP コントローラのflash メソッド

2

データを更新した後などに「更新しました」などのメッセージを簡単に出せるのがコントローラのflash メソッド。
コントローラで、
$this->flash('更新しました', '/users');
などとすることにより、メッセージを簡単に出せる。
2つ目の引数は飛び先URL を指定できる。

ちなみにこの flash メソッドは下記のようになっています。
/cake/libs/controller/controller.php

function flash($message, $url, $pause = 1) {
    $this->autoRender = false;
    $this->autoLayout = false;
    $this->set('url', $this->base . $url);
    $this->set('message', $message);
    $this->set('pause', $pause);
    $this->set('page_title', $message);

    if (file_exists(VIEWS . 'layouts' . DS . 'flash.thtml')) {
        $flash = VIEWS . 'layouts' . DS . 'flash.thtml';
    } elseif ($flash = fileExistsInPath(LIBS . 'view' . DS . 'templates' . DS . "layouts" . DS . 'flash.thtml')) {
    }
    $this->render(null, false, $flash);
}

上のソースを見ると分かるように、この flash メソッドのレイアウトは
$layout = "hoge";
とか指定しても指定したレイアウトでは表示されません。

flash メソッドでは flash.thtml というレイアウトを使用することしかできません。
/app/views/layouts/flash.thtml
を探してなければ、
/cake/libs/view/templates/layouts/flash.thtml
のデフォルトのレイアウトを使用します。

また、デフォルトの flash.thtml は

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title><?php echo $page_title?></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<?php if(Configure::read() == 0) { ?>
<meta http-equiv="Refresh" content="<?php echo $pause?>;url=<?php echo $url?>"/>
<?php } ?>
<style><!--
P { text-align:center; font:bold 1.1em sans-serif }
A { color:#444; text-decoration:none }
A:HOVER { text-decoration: underline; color:#44E }
--></style>
</head>
<body>
<p><a href="<?php echo $url?>"><?php echo $message?></a></p>
</body>
</html>

のようになっていて、
DEBUG モードで DEBUG = 0 を指定していると meta タグを利用して勝手に画面遷移します。DEBUG モードが 0 以外の場合はメッセージをクリックすると指定したURLに画面遷移します。

非常にシンプルなレイアウトですので、使用するときは、
/app/views/layouts/flash.thtml
にコピーしてカスタマイズした方がよいでしょう。

CakePHP ヘルパーからコンポーネントへのアクセス方法

1

ヘルパーからコンポーネントへのアクセス方法が分からず
教えていただいたのでメモ。

例えば HogeComponent にアクセスしたいヘルパーに
$this->view->controller->HogeComponent->method();というように書けば、HogeComponent の method にアクセスできる。

これで、ヘルパーがかなり使いやすくなりました。

PHP で大きいJPEGやPNGファイルをPHPで扱うときのメモリエラー回避方法

0

GD でメモリエラー
に書かれているように GD で JPEG や PNG の大きな画像を扱うときに
Fatal error: Allowed memory size of 16777216 bytes exhausted (tried to allocate 11648 bytes) in ...というようなエラーが出てしまいます。

上のエラーがは私が EOS5D で撮影した 2912×4368とかなり大きな画像です。

大きさで制限するのも一つの方法ですが、どうしても大きな画像を取り込みリサイズしなければいけないときなどのために以下の方法もあります。

PHP: imagecreatefromjpeg – Manual
PHP に割り当てられているメモリの範囲で必要なメモリを計算して
ini_set('memory_limit', 'xxM')と設定しれくれます。

function setMemoryForImage( $filename ){
    $imageInfo = getimagesize($filename);
    $MB = 1048576;  // number of bytes in 1M
    $K64 = 65536;    // number of bytes in 64K
    $TWEAKFACTOR = 1.5;  // Or whatever works for you
    $memoryNeeded = round( ( $imageInfo[0] * $imageInfo[1]
                                           * $imageInfo['bits']
                                           * $imageInfo['channels'] / 8
                             + $K64
                           ) * $TWEAKFACTOR
                         );
    //ini_get('memory_limit') only works if compiled with "--enable-memory-limit" also
    //Default memory limit is 8MB so well stick with that.
    //To find out what yours is, view your php.ini file.
    $memoryLimit = 8 * $MB;
    if (function_exists('memory_get_usage') &&
        memory_get_usage() + $memoryNeeded > $memoryLimit)
    {
        $newLimit = $memoryLimitMB + ceil( ( memory_get_usage()
                                            + $memoryNeeded
                                            - $memoryLimit
                                            ) / $MB
                                        );
        ini_set( 'memory_limit', $newLimit . 'M' );
        return true;
    }else
        return false;
    }
}

CakePHP デバッグモード

1

デバッグモードのメモ

/app/config/core.php の52行目に
define('DEBUG', 0);と定義されているのがデバッグモード

この値を変更することにより、本番環境、開発環境と切り替えることができる。

DEBUG の値は
0: プロダクションモード。エラーは出力されず、デバッグメッセージも表示されません。
1: 開発モード。 Warnings とエラー、デバッグメッセージを表示します。
2: 開発モード。実行されたSQL 文が表示されます。
3: 開発モード。2に加えて、現在のオブジェクト(通常はコントローラ)のフルダンプも表示されます。

DEBUG=1 で開発を行い、データ取得などの挙動が考えているのと違うときに、
DEBUG=2 にするという感じでやっています。
あまり、 DEBUG=3 を使用していないなあ。コントローラのダンプなので量が多すぎてかえって見づらいので、
debug($hoge);などで必要なときに個別にダンプを出してしまいます。

もちろん本番環境では DEBUG=0 です。

Go to Top