新しいブログに引っ越しました

tomotomoSnippetは新しいブログに移動しました
http://develtips.com/

2010-12-22

[GPL][MIT]ライセンスについて基本中の基本的なこと

今までずっと独学でHTMLやらプログラミングやらやってきました。
子供の頃からパソコンで何か作るのが好きで、とうとう職業にしちゃったわけです。

そんなわけで・・・

ライセンスについて今までちっとも勉強してこなかった!
英語やら法律用語やら専門用語やらで今まで読む気がしなかった。


ということで、今年中にいくつかライセンスについて知ったことをまとめたいと思います。

最終的には、
『GPLのPHPライブラリを利用したウェブアプリケーションを作成販売し、
 かつ、オリジナルで作った部分のソースを公開する必要があるのか?』
を理解することですが、ちょっと調べたくらいじゃ、そんなモノわかりませんでした。

今回は、初めてライセンスについて書くので、基本中の基本。
GPL(GNU General Public Licence)MIT Licence(X11 Licence)について分かったことを書きます。

GPLもMIT Licence(以下MIT)も、フリーソフトに関するライセンスで、どちらも。
・無償(無保証)
・利用/改造/再配布OK
・著作権表示義務あり
・商用利用OK
です。

まぁ、この辺りまではなんとなーく理解してましたが、じゃあどう違うねん、というと。

GPL
・ソースコードを公開する義務がある
・GPLを含む二次著作物もGPLにする必要がある(どんどん連鎖します←正しくは『ライセンスの継承』)

MIT
・ソース公開の義務なし
・二次著作物のライセンス変更もOK(元々の部分はMITのまま)

他にも、修正BSDライセンス(MITとほとんど一緒)、LGPL(緩いGPL)などあるので、次のサイトで確認すると良いと思います。
http://0xc000013a.wiki.fc2.com/wiki/%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E3%83%A9%E3%82%A4%E3%82%BB%E3%83%B3%E3%82%B9%E3%81%BE%E3%81%A8%E3%82%81

で、GPLのライセンスの継承ってやつが曲者で。
オープンソースなライセンスやコピーレフトなライセンス、クリエイティブコモンズについて、他のライセンスとどう組み合わせられるのかを図にしてみた
上記サイトが分かりやすく解説しているので、分からなくなった時に見に行くといいと思います。


さて、では実際に自分が作ったプログラムにGPLやMITを適用したい時はどうしたらいいのか。
ソースコードのどっか目立つ所(冒頭)にライセンスの宣言をすれば良いみたいです。
前述のまとめWikiによると、
GPLの場合:
(GPLバージョン3の和訳「4. 一字一句忠実なコピーの伝達」より引用) 『あなたはそれぞれのコピーにおいて、目立つように、かつ適切な形で、ふさわしい「コピーライト」告知を掲載しなければならない』
とあります。
全文っていうのがこれ

この全文をソースコードの先頭に書けば、GPLライセンスになります。

MITの場合:
ライブラリの著作権表示と許諾表示を、重要な部分に記載する必要がある。
とあります。

MITの場合はこんな感じで書けばいいようです。
実際の例はこれ


でもね、実際に見てみると、結構省略して書く人が多いみたいです。
例えばjquery-1.4.4.min.jsだってこーんな…
/*!
 * jQuery JavaScript Library v1.4.4
 * http://jquery.com/
 *
 * Copyright 2010, John Resig
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * Includes Sizzle.js
 * http://sizzlejs.com/
 * Copyright 2010, The Dojo Foundation
 * Released under the MIT, BSD, and GPL Licenses.
 *
 * Date: Thu Nov 11 19:04:53 2010 -0500
 */
(ちなみにjQueryはMITとGPLバージョン2のデュアルライセンスってやつです。)
ライセンスの宣言が
"Dual licensed under the MIT or GPL Version 2 licenses."
という一行で終わってます。
その次の行のhttp://jquery.org/licenseを見に行くと、それぞれのライセンス全文へのリンクがあります。

CakePHPはMITライセンスですが、こんな感じで表記しています。

どこにライセンスの全文が載っているか、を明記すればOKって慣例なんですかね。

なんだか、散らばった文章ですが、長くなってきたので終わります。(そして続きます、たぶん)


フリーソフトの『フリー』は『自由』であって、無料という意味ではない。
ということを再認識しました。


2010-12-02

CakePHPアドベントカレンダー2010(まとめ)

CakePHP Advent Calendar 2010を開催!

RubyやPerl, Symfonyなどでも企画されているAdvent CalendarをCakePHPでもやってみたいと思います。
技術系の方がやっているAdvent Calendar(アドベントカレンダー)は、12/1からクリスマスまでに1日ごとにその技術に関する何かしらの記事を書いて、アップしていくというもので、担当日を決めて何人かでどんどん記事をアップしていくパターンが多いです。

ということで面白そうなのでCakePHPアドベントカレンダーのブログ記事を追っかけてまとめようと思います。(詳しい情報は本家で見るのが良いと思うよ)

"#. 記事タイトル @Twitterプロフィール(あれば)"という形でまとめときます。
  1. 画像にリンクをはる簡単な方法(CakePHP Advent Calendar 1日目) @cakephper
  2. CakePHPであることを隠蔽する (CakePHP Advent Calendar 2010 2日目) @k1LoW
  3. CakePHP Modelとの付き合い方(CakePHP Advent Calendar 2010 3日目) @shin1x1
  4. Re: Best Practices in MVC Design with CakePHP @remore
    ※日本語版
  5. [CakePHP]モデルに振られる @uechoco
  6. Gitと一緒にCakePHPを楽しむ – CakePHP Advent Calendar 2010 6日目 @tfmagician
  7. 【CakePHP】CakePHP Advent Calendar2010(day 7) : Tips for Routes @MASA-P
  8. CakeDCのsearch pluginの記事が少ないので1個置いときますね。CakePHP Advent Calendar 2010 8日目 @kanonji
  9. CakePHP/Smartyとのつきあい方 - CakePHP Advent Calendar 2010 9日目 @ixcy
  10. CakePHPの環境を判定するTips (CakePHP Advent Calendar 10日目) @mon_sat
  11. CakePHPでデバッグレベルが0の時だけ発生するエラー @msng
  12. フォームヘルパに関して(CakePHP Advent Calendar 12st) @ogaaaan
  13. Datasourceを使い倒す @kaz_29
  14. Lithiumについて (CakePHP Advent Calendar 2010 14日目) @camelmasa
  15. App::import() は凄い @hiromi2424
  16. CakePHP2.0 を触ってみて。 @aerith
  17. BakerがCakePHPのために.bashrcに設定すべき5行 (CakePHP Advent Calendar 2010 17日目) @nojimage
  18. authkittenプラグインで子猫認証 (CakePHP Advent Calendar 2010 18日目) @halt 
  19. ControllerからModelを使用するいくつかの方法 (CakePHP Advent Calendar 19日目) @kunit 
  20. PaginatorHelperでの複雑なURL指定(CakePHP Advent Calender 20日目) @connvoi_tyou
  21. Containable Behaviorを追いかけてみました。 @yashio
  22. CakePHPのmodelを動的に生成する方法 @knj77
  23. 【CakePHP】メディアビューの使い方(CakePHP Advent Calendar 2010) @osakanapower
  24. 極める!Security Component (CakePHP Advent Calendar 2010 24日目) @akiyan
アドベントカレンダーって何?と思ったらこちら。(本家に載ってるリンクと一緒)
http://d.hatena.ne.jp/tokuhirom/20081216/1229387324

2010-11-14

[Google Analytics]トラフィックサマリーの『その他』ってなんぞ?

Google Analyticsで変なトラフィックがあった。


なんだこれ、と思ったらすぐに分かった
キャンペーンのタブをクリックしたらFeedからのアクセスだった。

初めて見たのでちょっとびっくり。

2010-11-10

ブレンドモード・色相/彩度/カラー/輝度のまとめ

Photoshop, Illustrator, Fireworksなどの画像編集ソフト(ざっくりだな)を使うときに、良くカラーのブレンドってやりますよね。
"乗算"とか"スクリーン"とか"反転"とか"削除"とか。
まぁ、このあたりは直感的に分かるんですが、"色相"・"彩度"・"カラー"・"輝度"なんてのになると、訳が分からなくなるのは僕だけじゃないはず。
「何で、水色の上に茶色を色相でブレンドしたらオレンジ色になるん??」
なんて思っている人は僕だけじゃないはず。
と言う事でそのあたりをまとめてみました。
(Figure.1)
(Figure.2)
まずは、基本中の基本。
色の仕組み。
WEB屋さんだと色はRGBで考えがちですが、HSL(H:色相、S:彩度、L:輝度)で表現することもあります。(Figure.1,2)
CSS3使っている人は知ってるかも。
あえて詳しく説明する必要もないでしょう。

ブレンドモード"色相"とは、"ベースカラーの彩度と輝度"と"ブレンドカラーの色相"を合わせた色にすることです。
ブレンドモード"彩度"とは、"ベースカラーの色相と輝度"と"ブレンドカラーの彩度"を合わせた色にすることです。
ブレンドモード"輝度"とは、"ベースカラーの色相と彩度"と"ブレンドカラーの輝度"を合わせた色にすることです。
ブレンドモード"カラー"とは、"ベースカラーの輝度"と"ブレンドカラーの色相と彩度"を合わせた色にすることです。



…と、Adobeさんの説明を噛み砕いて書いてみましたが、はい?って感じです。
これで分かる人は賢い人ですね。
分からない人は次の図を見て下さい。(Figure.3,4)
(Figure.3)
(Figure.4)
上図の左がベースカラー(色相:中、彩度:中、輝度:中)です。右がブレンドカラーです。

「ブレンドモードで指定した要素のみ上書きする」と考えれば分かりやすいです。(余計分かりにくいですか?)
これが理解できればデザインの幅が少し広がりますね。

じゃあ、"焼き込み(リニア)"とか、"ハードミックス"はどうなんだって?
知りません。
また機会があればまとめます。

(余談)
輝度って「きど」って読むんですね。
読み方が分からず「けいど」って言っていました。お恥ずかしい。

(2010.11.12追記)
こちらの記事が大変詳しいです。
http://ofo.jp/osakana/cgtips/blendmode.phtml

2010-11-02

[html5]canvasタグで月の満ち欠けを書いてみる

今回はCanvas - HTML5.JPを参考にしながら、月齢から月の形を計算して、canvasに出力したいと思います。

とりあえず、canvasのIDを取得するJavascript関数を作ります。
Canvasの使い方 - Canvas - HTML5.JPに詳しい情報があります。
function getCanvas (canvasID) {
 var canvasObj = document.getElementById(canvasID);
 if (canvasObj && canvasObj.getContext) {
  return canvasObj.getContext('2d');
 }
 return false;
}
これを作ってしまえば、今後キャンバスを使う際に使い回しができます。


まず初めに満月を書いてみましょう。
function drawMoon () {
 var c = getCanvas('TheMoon');
 // 月の半径
 var moon_r = 100;
 // グラデーションの設定
 var gd = c.createRadialGradient(135,135, moon_r*0.9, 140,140, moon_r*1.2);
 gd.addColorStop( 0, 'rgb(233, 84, 100)' );
 gd.addColorStop( 1, 'rgb(123, 74, 80)' );
 // 円を塗りつぶす
 c.beginPath();
 c.arc( 140, 140, moon_r, 0, Math.PI*2, true);
 c.fillStyle = gd;
 c.fill();
}
// HTML
// <canvas id="TheMoon" width="280" height="280"></canvas>
canvasのメソッドについてはCanvas - HTML5.JPを見てね。本稿では解説しません。

drawMoon()を実行すると、半径100pxの円形グラデーションが適用された円が表示されます。
DEMO(月の色が変なのは気にしない)


次は、月が欠けた分だけ影を追加したいと思います。
上から黒で塗りつぶしても良いけど、芸が無いので、globalCompositeOperationプロパティを使って、円に重ねた影の領域を円から削除します。
c.globalCompositeOperation = 'destination-out';
これで準備OK。

次は、影の形を計算したいと思います。
ややこしいので、月の形を完全な球、月の軌道を完全な円にしてしまいます。
つまり、月齢0の時は全部影になって、右の方から光が当たり始めて、月齢7.5で半月(上弦の月)、月齢15で満月。
その後は右から徐々に影が増えて、月齢22.5で半月、月齢30(月齢0)で新月。

影の左右端はコサインで計算できそうだな。
月の中心座標を0,0として、影の左右端x座標をmoon_xとしよう。
月齢0~15のとき、moon_xが-moon_rから+moon_rに変化して、
月齢16~30のとき、moon_xが-moon_rから+moon_rに変化するんだから・・・
var moon_grow = (age>15)? true: false;
var moon_x = Math.cos(age/30*Math.PI*2) * moon_r * (moon_grow? -1: 1);
こんな計算をしてやればOK!
(age>15)? true: false; って条件が反対じゃないかというツッコミが来そうですが、良いんです。
後々、逆にしておく事で計算が簡単になるんだ。

半円の影とmoon_xを結ぶ片側が潰れた円を描けば良いので最終的にこうなります。
function drawMoon (age) {
 var c = getCanvas('TheMoon');
 var a = 0.5522847;
 var moon_grow = (age>15)? true: false;
 
 var moon_r = 100;
 var rate = Math.cos(age/30*Math.PI*2);
 var moon_x = moon_r*rate * (moon_grow? -1: 1);
 
 var gd = c.createRadialGradient(135,135, moon_r*0.9, 140,140, moon_r*1.2);
 gd.addColorStop( 0, 'rgb(233, 84, 100)' );
 gd.addColorStop( 1, 'rgb(123, 74, 80)' );
 
 c.beginPath();
 c.arc( 140, 140, moon_r, 0, Math.PI*2, true);
 c.fillStyle = gd;
 c.fill();
 
 c.globalCompositeOperation = 'destination-out';
 c.beginPath();
 c.fillStyle = 'rgb(192, 70, 80)';
 c.arc( 140, 140, moon_r, Math.PI*1/2, Math.PI*3/2, moon_grow);
 c.bezierCurveTo( 140+a*moon_x,140-moon_r,  140+moon_x,140-a*moon_r,  140+moon_x,140);
 c.bezierCurveTo( 140+moon_x,140+a*moon_r,  140+a*moon_x,140+moon_r,  140,140+moon_r);
 c.fill();
}
c.bezierCurveTo()メソッドで3次ベジェ曲線を使って楕円を描画しています。
制御点の計算が難しかったのですが、こちらを参考に係数をa=0.5522847として決めて様子見したところ、上手くいっていたのでそのまま採用しました。
c.arc( 140, 140, moon_r, Math.PI*1/2, Math.PI*3/2, moon_grow);で月齢16を境に、右半円、左半円を切り替えているところがポイントですかね。

そんなこんなで、色々とキャンバスの理解につながったので良かった。
今日のお月さま」というサービスでアップしたので、良かったら見て下さい。

今日のお月さま作成にあたり参考にしたサイト
月齢カレンダー
http://koyomi.vis.ne.jp/moonage.htm
Canvasリファレンス - HTML5.JP
http://www.html5.jp/canvas/ref.html
s.h's page - [graphic] ベジエ曲線
http://park12.wakwak.com/~shp/cgi-bin/wiki.cgi/view/bezier_curve
月齢 - Wikipedia
http://ja.wikipedia.org/wiki/%E6%9C%88%E9%BD%A2

2010-09-08

[CakePHP1.3]FormHelperが出力する必須項目*について

重い腰を上げてCakePHP1.3.3をダウンロードして使い始めました。
Scaffoldビューのリンクやボタンが角丸になっているなど、CSS3をふんだんに使っているようです。
(ぱっと見で)

とりあえず、Formヘルパーを使ってログイン画面を作ってみたところ、少し不都合な事実に気づいてしまいました。
// views/users/login.ctp
echo $form->create('User', array('action'=>'login');
echo $form->input('User.username');
echo $form->input('User.password');
echo $form->end('ログイン');

モデルで必須項目に設定した項目のラベルが太字と*印(アスタリスク)で表示されています。
注意書きで「*印は必須項目です」と書こうとしたのですが、CSSを良く見ると*は:after疑似クラスで表示されている模様。
/* cake.generic.css L269 */
form .required label:after {
 color: #e32;
 content: '*';
 display:inline;
}
これではIE6はもちろんの事、IE7でも*が表示されません。
IE7以前で*を表示するなら別の方法を考えないといけませんね。
CSSからcontent: '*';を削除して、必須のラベルに手動で*を表示するとか。

CSS2.1に完全準拠していないブラウザからのアクセスを想定するサイトを構築する際には、ちょっと注意しましょう。

いっその事「IE7以前はサポート外です」と表示するか(笑)

(余談)
「FormHelperが出力する必須項目*について」というタイトルにしましたが、*は別にFormヘルパーが出力してるわけでは無いです。
<div class="input text required">というタグを出力しているだけです。
完全にcake.generic.cssの話ですが、私は最初、*印はFormヘルパーが出力していると勘違いしたので、こんなタイトルにしました。

2010-07-05

[CakePHP1.2]印刷用ページのルーティング

ちょっと軽い話題。

routes.phpを編集して、印刷専用のレイアウトを設定できるようにします。
具体的には
http://example.com/print/users/view/123
にアクセスした際にレイアウトのprint.ctpを適用します。


// routes.php の一番最後

/**
* 印刷用ページのルーティング
*/
Router::connect(
'/print/:controller/:action/*',
array('action'=>'index', 'print'=>1)
);

コントローラでは、$this->params['print']が使えるようになります。
AppControllerのbeforeRenderをいじってみましょう。


// app_controller.php

class AppController extends Controller
{
function beforeRender()
{
if (isset($this->params['print']) && $this->params['print']==1) {
$this->layout = 'print';
}
}
}

はい、これでコントローラの前に/printを付けるだけで
プリント用レイアウトが適用されるようになりました。
プリント用レイアウトは不要なナビゲーション関連の要素を削除する
などしておくとスッキリします。

(追記:2010/7/5)
残念ながら、プリントルーティングは完全ではないです。
pagesコントローラのルーティングなど、他にカスタムルーティングを
行っている場合は、プリントルーティングが適用されません。
個別に設定していきましょう。


// 例 routes.php
/**
* ...and connect the rest of 'Pages' controller's urls.
*/
Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display'));
// この一行を追加
Router::connect('/print/pages/*', array('controller' => 'pages', 'action' => 'display', 'print'=>1));

2010-04-21

[XAMPP]XAMPPを壊してしまったので再インストール手順

先日、ちょっとしたミスでXAMPPをぶっ壊してしまい、起動しなくなりました。
1.6.xを使ってたんですが、久しぶりに公式サイトを覗いたら1.7.3まで出てるじゃーん。アップグレードしよう。なんて、思ってアップグレードパッケージを使った後に、1.7.2-1.7.3専用だと気付くも時遅し。見事に起動しなくなりましたとさ。

そんなわけで、再インストールをしたので手順まとめ。
(環境はWindowsXP)
xamppインストールディレクトリはc:\xamppとします。

1.データのバックアップ
c:\xampp\htdocsの内、xamppフォルダ以外
c:\xampp\mysql\dataの内、自分で作ったデータベースと同じ名前のフォルダ
この2つを違う場所にコピーして、c:\xamppをすべて削除。

1.1.PCを再起動
必要かわからないけど、一応。

2.XAMPPをインストール
インストールしたいパッケージをインストール。
XAMPP1.7からはPHP5しか入ってないので、PHP4が必要なら1.6.xをインストール。(1.7を入れてから気付きました。)
ちなみに、1.6.8の日本語版は、本家からのリンクが無いので下記URLからダウンロード。
http://sourceforge.jp/projects/sfnet_xampp/downloads/XAMPP%20Windows/1.6.8/xampp-win32-1.6.8-installer.exe/

3.セキュリティ対策
MySQLにパスワードを設定してもいいんだけど、ローカルマシン以外からアクセスできないようにすればOK。
(参考)
http://www.be-webdesigner.com/technotes/server/install/xampp.htm
http://www.be-webdesigner.com/technotes/server/httpd_conf/security.htm

c:\xampp\apache\conf\httpd.conf v1.3.8ならL53あたり
[変更前]
Listen 80
[変更後]
#Listen 80
Listen 127.0.0.1:80

これで、XAMPPを起動してみればちゃんと、http://localhost/にアクセスできるはずです。

4.バックアップデータの復元
1.でバックアップしたデータを元の場所に戻す。
phpmyadminなどで確認するとちゃんとデータベースも元に戻ってます。

5.お好みでセットアップ
mod_rewriteを有効にする(v1.6.8の場合、初期では無効)
C:\xampp\apache\conf\httpd.conf
[変更前]
#LoadModule rewrite_module modules/mod_rewrite.so

[変更後]
LoadModule rewrite_module modules/mod_rewrite.so


mbstringだとか、gdだとか、cURLだとか、関数を使えるようにするには、
C:\xampp\apache\bin\php.ini
の中で該当する部分のコメントを外します。

なんとか、復活できてほっとしています。

2010-02-19

[CakePHP][eclipse]登録用ビューの$formを$dataに置換して表示用ビューを作る正規表現

データ入力用のフォームを作って、それを基にデータ表示用のビューを作るなら、$form->text('Model.field')$data['Model']['field']にすれば良いだけの話だが、何十か所もあると流石に面倒くさい。
私は開発ソフトがeclipseなので、正規表現で一発変換をしています。


// example.ctp

<?=$form->text('User.name', array('class'=>'abcd')) ?>

// 次のように変換したい...

<?=$data['User']['name'] ?>


eclipseの検索/置換で正規表現を選択し
検索
form->[a-z]+\('([\w]+)\.([\w]+)'.*\)
置換
data['$1']['$2']

とやってみてください。

正規表現

パーフェクトに置換はできませんが、作業がだいぶん楽になります。

2010-01-29

[CakePHP]ヘルパーを改造する!ただし、コアは書き換えない

CakePHP1.2のお話(最近、この一言を書き忘れていた)

携帯サイトを作っていると既存のHtmlHelperでは不十分だと思い、
思い切って、HtmlHelperを書き変えてやろうという事に。

ただし、コア(LIBS/views/helpers/html.php)は書き換えない方針で!

試しに、コアのHtmlHelperをAPP内にコピーしてみる。

// app/views/helpers/html.php

// メソッド内のどこかで
echo 'new helper';


// app/controllers/example_controller.php

// 普通に定義してやる
var $helpers=array('Html');


ページにアクセスしてみると、new helperが表示されました。

結論:
ヘルパーを改造する際は
LIBS/views/helpers/someone.php

APP/views/helpers/someone.php
にコピーするだけ。

ってことは、コンポーネントも同じ事が出来るのか?

2010-01-26

EclipseにJStyleプラグインをインストールする

JStyleプラグインって何?
http://mergedoc.sourceforge.jp/index.html#/jstyle.html
Eclipse のエディタで全角空白、半角空白、タブ、改行(LF、CRLF、CR)を表示可能にするプラグインです。
他に太字を通常文字と同じ幅で表示するオプションがあります。


コードインデントがタブなのか、半角スペースなのか、ぱっと見で分からなくて不便だったのでインストールしました。

JStyleからダウンロードしたファイルを、/eclipseインストールフォルダ/plugins/にコピーして、-cleanオプションを付けてeclipseを起動すれば、インストール完了。
Windowsならコマンドプロンプトから起動すればOK!

C:\(eclipseインストールフォルダ)>eclipse.exe -clean


JStyleの設定は、[ウィンドウ]->[設定]->[一般]->[JStyle]から変更できます。

2010-01-22

[CakePHP]モバイルヘルパーを改善する

CakePHPで携帯サイトを制作するには、文字コードの変換、カタカナの変換が必要です。
それを実行するためのヘルパーは既に
コントローラの afterFilter で文字コードを変換する方法で紹介されています。

もう一つ改良して、ビューの行頭のインデントを削除したいと思います。


class MobileHelper extends Helper {
function afterRender() {
$out = ob_get_clean();
// 次の一行を追加
$out = preg_replace('/\n[\s]+/', "\n", $out);
$out = mb_convert_kana($out, "rak", "UTF-8");
$out = mb_convert_encoding($out, "SJIS", "UTF-8");
ob_start();
echo $out;
}
}

preg_replace('/\n[\s]+/', "\n", $out)で、改行した後のインデント(タブ、半角スペース、改行)を改行コードに置換しています。
置き換え後の文字は必ず、”(ダブルクオート)で囲ってください。
’(シングルクオート)だとちゃんと改行コードになってくれません。

これで、十数バイトの容量節約になると思います。

2010-01-18

[CakePHP]Javascriptヘルパーを拡張したい

CakePHP1.2で外部Javascriptファイルを読み込むのに、Javascriptヘルパーを使って出力しますが、元のヘルパーだと、charset属性を指定できません。


View:
$javascript->link('http://maps.google.com/maps?file=api&v=2&hl=ja&sensor=false&key=XXXX', false);


Html:
<script type="text/javascript" src="http://maps.google.com/maps?file=api&v=2&hl=ja&sensor=false&key=XXXX"></script>


という事で、さっさとヘルパーを拡張することにしました。
CakePHP Formヘルパの拡張 その1日本語日付選択プルダウンを参考にすると、継承元のクラス名は必ずしもAppHelperでなくて良いようだ。

これなら必要な機能だけ拡張、または上書きすれば良さそう。
という事で、早速Javascriptヘルパーのlinkメソッドをコピーして、ちょちょっと書きなおしたコードがコレ。
// APP/views/helpers/ex_javascript.php

class ExJavascriptHelper extends JavascriptHelper
{
function link($url, $inline = true, $attr = array())
{
// (省略)

$htmlattributes = '';
foreach ($attr as $k => $v) {
$htmlattributes .= ' '.$k.'="'.$v.'"';
}

//$out = $this->output(sprintf($this->tags['javascriptlink'], $url));
$out = $this->output(sprintf('<script type="text/javascript" src="%s"%s></script>', $url, $htmlattributes));

// (省略)
}
}

第3引数にHTML属性を指定できるようにしました。


これでよし!と思ったら一つ問題が・・・
コントローラで、元のJavascriptヘルパーも併せてセットしないと動かないことが発覚。
var $helpers = array('Javascript','ExJavascript');


継承してるのに2つともインスタンス化しちゃうのはなんだかなぁ
ということで、先ほどのコードをちょっと書き換えます。

// APP/views/helpers/ex_javascript.php

// まずは元のJavascriptヘルパーファイルを読み込む
require_once CAKE.'libs'.DS.'view'.DS.'helpers'.DS.'javascript.php';

class ExJavascriptHelper extends JavascriptHelper
{
function link($url, $inline = true, $attr = array())
{
// (省略)

$htmlattributes = '';
foreach ($attr as $k => $v) {
$htmlattributes .= ' '.$k.'="'.$v.'"';
}

#$out = $this->output(sprintf($this->tags['javascriptlink'], $url));
$out = $this->output(sprintf('<script type="text/javascript" src="%s"%s></script>', $url, $htmlattributes));

// (省略)
}
}


Controller:
var $helpers = array('ExJavascript');


View:
$exJavascript->link('http://maps.google.com/maps?file=api&v=2&hl=ja&sensor=false&key=XXXX', false, array('charset'=>'UTF-8'));


Html:
<script type="text/javascript" src="http://maps.google.com/maps?file=api&v=2&hl=ja&sensor=false&key=XXXX" charset="UTF-8"></script>


期待通りの動きが実現できました。

2010-01-15

[CakePHP]アソシエーションを設定したモデルのデータも削除する

Model::del()でアソシエーションを設定したモデルのデータの削除の仕方をド忘れしたのでメモ。

用意するモデル:
*Company model 企業データ
*User model 社員データ
*Post model 投稿データ


// company.php

class Company extends AppModel
{
var hasMany = array(
'User' => array( 'dependent' => true ),
'Post' => array( 'dependent' => true )
);
}


アソシエーションを設定するときにdependentTRUEに設定してやれば、Company::del($id)を実行すれば、アソシエーション相手も削除されます。
一時アソシエーションを設定するときも同様なり。

// companies_controller.php

class Companies extends AppController
{
function del($id) {
$this->Company->bindModel(
array(
'hasMany' => array(
'User' => array( 'dependent' => true ),
'Post' => array( 'dependent' => true )
)),
false
);

$this->Company->del($id);
}
}

人気のエントリー

ブログ アーカイブ