12 月 29


<VirtualHost *:80>
ServerAdmin root@example.com
DocumentRoot /var/www/example.com
ServerName example.com
ErrorLog logs/example.com-error_log
CustomLog logs/example.com-access_log common
</VirtualHost>

/etc/httpd/conf/httpd.confに
以下のような設定を追加して、VirtualHostを使おうとしましたが、
いままで動いていたドメインまでVirtualHostに指定した
ディレクトリに飛んでしまうトラブルが発生・・・。

httpd.confを見て行くと・・・
発見!
NameVirtualHost *:80
がコメントアウトされていました。
ここを外すと、無事VirtualHostが動くようになりました!

6 月 29

PHPでエクセルファイルを読み取る必要があったので、調べてみた。

Excel 2007にも対応している「PHPExcel」がよさそうな感じ。

まずは、PHPExcelをダウンロード

解凍したらサーバにアップ。
app/vendors/以下にPHPExcel.phpとPHPExcelフォルダを置く。

importしようとしたらエラー発生。
App::import('Vendor', 'PHPExcel');
App::import('Vendor', 'IOFactory', array('file'=>'PHPExcel'.DS.'IOFactory.php'));

Fatal error: require_once(): Failed opening required ‘PHPExcel.php’ (include_path=’.:/usr/share/pear:/usr/share/php’) in /サーバ上の場所/app/vendors/PHPExcel/IOFactory.php on line 30

サンプルにあるように、includeで読み込みさせてみる。
set_include_path(APP.’vendors/’);
include ‘PHPExcel.php’;
include ‘PHPExcel/IOFactory.php’;

※set_include_pathの「APP」は、「アプリケーションディレクトリのパス」です。
 参考:11.3. CakePHP パスの定数

以下のソースを実装してみました。(参考サイト:マイコミジャーナル

//(1) Excel2007形式のファイルを読み込み
$reader = PHPExcel_IOFactory::createReader('Excel2007');
$xl = $reader->load("/サーバ上の場所/app/webroot/files/excel/template.xlsx");

// セルの値を設定
$xl->getActiveSheet()->setCellValue('C5', '田中 太郎 様');
$xl->getActiveSheet()->setCellValue('C6', 'A0501');

// Excel2007形式で出力
$writer = PHPExcel_IOFactory::createWriter($xl, 'Excel2007');
$writer->save('/サーバ上の場所/app/webroot/files/excel/output2.xlsx');

しかし、エラー発生。
Fatal error: Class 'XMLWriter' not found in /サーバ上の場所/app/vendors/PHPExcel/Shared/XMLWriter.php on line 66

「XMLWriter」というClassが読めないそうな。
とりあえず、Excel5形式に変更してみてテスト。
//(1) Excel5形式のファイルを読み込み
$reader = PHPExcel_IOFactory::createReader('Excel5');
$xl = $reader->load("/サーバ上の場所/app/webroot/files/excel/template.xls");

// セルの値を設定
$xl->getActiveSheet()->setCellValue('C5', '田中 太郎 様');
$xl->getActiveSheet()->setCellValue('C6', 'A0501');

// Excel5形式で出力
$writer = PHPExcel_IOFactory::createWriter($xl, 'Excel5');
$writer->save('/サーバ上の場所/app/webroot/files/excel/output2.xls');

今度はうまくいきました。

Excel2007は、php-xmlが入っていないためと予想。
php-xmlをインストールしてみた。

yum install php-xml

再度、Excel 2007形式で実行してみるとできました!
2007形式を扱うにはphp-excelが必要なんですね。

※他には、以下のライブラリも必要です(ネタ元)。
・PHPバージョン5.2以上
・PHP拡張モジュール「php_zip」

PHPExcelは、Excel2003は扱えないというサイトがいくつかありましたが、
v1.6.1からPHPExcel_Reader_Excel5の対応が入っているようです。
実際、xlsファイルの読み込みと書き出しできました。
(ローカル環境がExcel2007なので、Excel2007を使っての確認ですが・・・)

4 月 02

app/config/core.php の変更

Configure::write('Session.save', 'cake');
Configure::write('Security.level', 'medium');
Configure::write('Session.cookie', 'session');
Configure::write('Session.timeout', '20');

cake/lib/session.php の変更(438行目から)

switch (Configure::read('Session.save')) {
case 'cake':
if (empty($_SESSION)) {
if ($iniSet) {
ini_set('session.use_trans_sid', 0);
ini_set('url_rewriter.tags', '');
ini_set('session.serialize_handler', 'php');
ini_set('session.use_cookies', 1);
ini_set('session.name', Configure::read('Session.cookie'));
ini_set('session.cookie_lifetime', $this->cookieLifeTime);
ini_set('session.cookie_path', $this->path);
ini_set('session.auto_start', 0);
ini_set('session.save_path', TMP . 'sessions');
}
}
break;

参考サイト
http://blog.livedoor.jp/loopus/archives/50212018.html

3 月 31

CakePHPのFormヘルパーを使用して、日付入力項目を日本っぽく表示するには

CakePHPでdate型の入力項目は、デフォルトでは「月-日-年」となる。
しかも月は英語表記で、「31-March-2009」などとなる。

これを日本にあわせた形で表示する方法。
まず、月を数字で表示するには、Formヘルパーファイルを書き変える。
cakeディレクトリにあるソースを直接変更したくないので、
cake/libs/view/helpers/form.phpファイルをコピーして
app/views/helpers/以下に置く。

コピーしたファイルの「function __generateOptions」を変更する。
1760行目付近の以下の箇所を次のように変更
************ 変更前 ここから ************
$data['01'] = __(’January’, true);
$data['02'] = __(’February’, true);
$data['03'] = __(’March’, true);
$data['04'] = __(’April’, true);
$data['05'] = __(’May’, true);
$data['06'] = __(’June’, true);
$data['07'] = __(’July’, true);
$data['08'] = __(’August’, true);
$data['09'] = __(’September’, true);
$data['10'] = __(’October’, true);
$data['11'] = __(’November’, true);
$data['12'] = __(’December’, true);
************ 変更前 ここまで ************
************ 変更後 ここから ************
$data['01'] = __(’1′, true);
$data['02'] = __(’2′, true);
$data['03'] = __(’3′, true);
$data['04'] = __(’4′, true);
$data['05'] = __(’5′, true);
$data['06'] = __(’6′, true);
$data['07'] = __(’7′, true);
$data['08'] = __(’8′, true);
$data['09'] = __(’9′, true);
$data['10'] = __(’10′, true);
$data['11'] = __(’11′, true);
$data['12'] = __(’12′, true);
************ 変更後 ここまで ************

あとは、タグのパラメータで設定できる。
dateTime(’birthday’, ‘YMD’, ‘NONE’,null, array(’minYear’=>1900, ‘maxYear’=>date(’Y')), false); ?>

1つ目の引数は、項目名
2つ目の引数は、年月日の並び(”DMY”、”MDY”、”YMD”)。年月日の表示が不要の場合は、”NONE”
3つ目の引数は、時間の表示方法(”12″、”24″)。時間の表示が不要の場合は、”NONE”
4つ目の引数は、初期選択値(selected)
5つ目の引数は、要素の属性。(minYear、maxYear、separator、intervalなどを指定できる)
6つ目の引数は、空のoption要素を出力するかの真偽値(falseだと表示しない)

3 月 30

UsersとGroupsテーブルを作成する

CREATE TABLE users (
id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(255) NOT NULL UNIQUE,
password CHAR(40) NOT NULL,
group_id INT(11) NOT NULL,
created DATETIME,
modified DATETIME
);

CREATE TABLE groups (
id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
created DATETIME,
modified DATETIME
);

Usersコントローラーにloginとlogoutのアクションを追加する

AppControllerに対して、AuthとACLのセットアップを行う
var $components = array('Auth', 'Acl', 'Session', 'Security');

function beforeFilter() {
parent::beforeFilter();

$this->Auth->authorize = 'actions';
$this->Auth->logoutRedirect = array('controller' => 'users', 'action' => 'login');
$this->Auth->loginRedirect = array('controller' => 'companies', 'action' => 'view');
$this->Auth->loginError = 'UIDかパスワードが違います';
$this->Auth->authError = 'アクセス権限がありません';
}

GroupsController と UsersControllerにアクセスできるように下記を追加する(一時的な設定)
function beforeFilter() {
parent::beforeFilter();
$this->Auth->allowedActions = array('*');
}

ACLのデータベースを初期化する
コンソールから以下を実行する
cake schema run create DbAcl

リクエスタとしてふるまう
User モデルに下記を追加
var $actsAs = array('Acl' => array('requester'));

function parentNode() {
if (!$this->id && empty($this->data)) {
return null;
}
$data = $this->data;
if (empty($this->data)) {
$data = $this->read();
}
if (!$data['User']['group_id']) {
return null;
} else {
return array(’Group’ => array(’id’ => $data['User']['group_id']));
}
}

Group モデルに下記を追加
var $actsAs = array('Acl' => array('requester'));

function parentNode() {
return null;
}

ここで、グループデータ、ユーザデータを登録してみる。
⇒arosテーブルにデータが作成されているのを確認

ACOを作成する
コンソールから下記を実行する
cake acl create aco root controllers

AppControllerに下記を追加する
※場所は、beforeFilter()の一番最後に追加した
$this->Auth->actionPath = 'controllers/';

AppControllerクラスに、buildAcl()メソッドを作成し、beforeFilter()メソッドの最後にbuildAcl()を呼び出すコードを記述する
function buildAcl() {
$log = array();
$aco =& $this->Acl->Aco;
$root = $aco->node('controllers');
if (!$root) {
$aco->create(array('parent_id' => null, 'model' => null, 'alias' => 'controllers'));
$root = $aco->save();
$root['Aco']['id'] = $aco->id;
$log[] = ‘Created Aco node for controllers’;
} else {
$root = $root[0];
}

App::import(’Core’, ‘File’);
$Controllers = Configure::listObjects(’controller’);
$appIndex = array_search(’App’, $Controllers);
if ($appIndex !== false ) {
unset($Controllers[$appIndex]);
}
$baseMethods = get_class_methods(’Controller’);
$baseMethods[] = ‘buildAcl’;
// app/controllers 中の、どのコントローラか調べる
foreach ($Controllers as $ctrlName) {
App::import(’Controller’, $ctrlName);
$ctrlclass = $ctrlName . ‘Controller’;
$methods = get_class_methods($ctrlclass);
// コントローラノードを探し、作成する
$controllerNode = $aco->node(’controllers/’.$ctrlName);
if (!$controllerNode) {
$aco->create(array(’parent_id’ => $root['Aco']['id'], ‘model’ => null, ‘alias’ => $ctrlName));
$controllerNode = $aco->save();
$controllerNode['Aco']['id'] = $aco->id;
$log[] = ‘Created Aco node for ‘.$ctrlName;
} else {
$controllerNode = $controllerNode[0];
}
// 親コントローラとプライベートのアクションを削除する
foreach ($methods as $k => $method) {
if (strpos($method, ‘_’, 0) === 0) {
unset($methods[$k]);
continue;
}
if (in_array($method, $baseMethods)) {
unset($methods[$k]);
continue;
}
$methodNode = $aco->node(’controllers/’.$ctrlName.’/’.$method);
if (!$methodNode) {
$aco->create(array(’parent_id’ => $controllerNode['Aco']['id'], ‘model’ => null, ‘alias’ => $method));
$methodNode = $aco->save();
$log[] = ‘Created Aco node for ‘. $method;
}
}
}
debug($log);
}

パーミッションの設定
UsersControllerに以下のinitDB()を追加して、beforeFilter()から呼び出す。
function initDB() {
//$group =& $this->User->Group;
App::import('Model', 'Group');
$group = new Group();

// 管理者グループには全てを許可する
$group->id = 1;
$this->Acl->allow($group, 'controllers');

// マネージャグループには posts と widgets に対するアクセスを許可する
$group->id = 2;
$this->Acl->deny($group, 'controllers');
$this->Acl->allow($group, 'controllers/Posts');
$this->Acl->allow($group, 'controllers/Widgets');
$this->Acl->allow($group, 'controllers/Users/logout');

// ユーザグループには posts と widgets に対する追加と編集を許可する
$group->id = 3;
$this->Acl->deny($group, 'controllers');
$this->Acl->allow($group, 'controllers/Posts/add');
$this->Acl->allow($group, 'controllers/Posts/edit');
$this->Acl->allow($group, 'controllers/Widgets/add');
$this->Acl->allow($group, 'controllers/Widgets/edit');
$this->Acl->allow($group, 'controllers/Users/logout');
}

ブラウザで、
http://(アプリケーションURL)/users
等に一回アクセスしパーミッションの作成が確認できたら、UsersControllerクラスからinitDB()メソッドと、beforeFilter()メソッド内のinitDB()の呼び出し行を削除する。
あわせて、GroupsController、UsersControllerクラスのbeforeFilter()メソッドから
$this->Auth->allowedActions = array(’*’);
の行を削除する。

参考サイト
CakePHPマニュアル
CakePHP 10.2 ACL 開発例の補足

3 月 18

リンク付き画像を表示する方法

$html->linkの第1引数に$html->imageを、第5引数にfalseを指定するとよい

link($html->image(”test.png”), ‘/’,null,null,false);?>

3 月 16

ファビコンを作ってみたので、そのときのメモ

基本的に、以下のサイトの通りにやっただけ。
2xup.org Photoshop で背景透過の美しい favicon (ファビコン) を作成する

Photoshop CS4を購入したので、Photoshopでファビコンを作れるようになるというプラグインを入れてみた。
Photoshop icoformatICO (Windows Icon) Format Plugin

このサイトで、「ICO (WINDOWS ICON) FORMAT」の「Free download:Windows」からダウンロード⇒解凍してできる「ICOFormat.8bi」ファイルを「C:\Program Files\Adobe Photoshop CS4\Plug-ins\File Formats」以下に配置。
すると、保存する際に「ICO (Windows Icon)」形式を選べるようになります。

画像ファイルは、Photoshopで64px 四方で作成して、『イメージ > 画像解像度』のバイキュービック法(シャープ)で
32px 四方に解像度を落としました。

表示させるには、以下のようにlinkタグをXHTMLのheadに埋め込みましょう。

3 月 12

CakePHPのフォームヘルパーを使ってradioボタンを設定したのですが、
チェックした値をうまく取れないという現象が発生。

調べてみたところ、radioの前にvalue=”"というhiddenタグが出力されていることが原因っぽい。
このhiddenタグを出さないようにするためには、radioの第3引数に適当な値を渡してやればよい。
radio(’user’, array(’all’=>’すべて’), array(’value’ => ‘all’)); ?>

この例のように、ラジオボタンの値に一致するvalueを渡すとその項目をcheckedにできる。
checkedにしたくない場合は、一致しないvalueを渡す。

以下のサイトを参考にしました
floatingdays

3 月 12

1.コントローラー名の取得

   $this->name

2.アクション名の取得

   $this->action

3.Webrootの取得

   $this->webroot

4.現在の位置(URL)を取得

   $this->here;

print_r ($this);
とすると、色々見れて実装に役立てられそう。

ビューで、URLの取得したいときは、
   $html->url()

第2引数をtrueにすると、絶対パスが取れる
   $html->url(’/', true)
とすると、コントローラー名までの、絶対パスが取れる
(’/'は、コントローラーまでを指すらしい)

3 月 06

CakePHPでGroup byを使いたかったので、そのときに調べたメモ

以下のようにすると、Group byを使える
$conditions = array("sex"=> "m");
$fields = array('pref','sum(age)','avg(age)');
$order = array('id' => 'ASC' );
$group = 'pref';
$users = $this->User->find('all', array('conditions'=>$conditions, 'fields'=>$fields, 'group'=>$group, 'order'=>$order));

以下のサイトを参考にしました
CakePHPユーザフォーラム:GROUP BY パラメータ