CakePHP (1.3.5) modelキャッシュのクリア

Posted in CakePHP, PHP関連 on 10月 28th, 2010 by Site Administrator

tmp/cache/models以下に、テーブル構造を格納したmodelのキャッシュファイルが格納される。
findなどを行う際、CakePHPはテーブルの構造を取得し、構造に適したクエリを発行するが、
このキャッシュファイルが存在すると「CakePHPはテーブルの構造を取得し」の部分が省略される。

テーブル構造が変化しない場合は問題ないが、動的にテーブル構造が変更される場合、
このキャッシュが残っていることで不具合が発生することがある。
例)
1.テーブルAのデータをfind
2.テーブルAにカラムaを追加
3.テーブルAをfind→カラムaは取得されない
(キャッシュにカラムaは定義されていないため、発行されるクエリに含まれない)

構造が変化した場合、キャッシュを削除するために下記の処理も追加すること。
Cache::delete(‘useDbConfig名_実テーブル名’,’_cake_model_’);

例えばuseDbConfigがdefaultで、テーブルがabcの場合は
Cache::delete(‘default_abc’,’_cake_model_’);
となる。

CakePHP (1.3.5) DB接続先の動的な設定

Posted in CakePHP, PHP関連 on 10月 27th, 2010 by Site Administrator

database.phpにDBの接続情報を定義しておけば、modelの$useDbConfigを使用して
接続先を動的に選択できます。ただし、「database.phpにDBの接続情報を定義している」前提です。

例えば構造が同じDBをユーザー単位に作成し、ユーザーごとにDBを切り替える必要がある場合、
上記のように「database.phpにDBの接続情報を定義している」というやりかたでは対応できません。
そのような場合は
$db =& $this->getDataSource();
でデータソースを取得し、
$db->reconnect(array(
‘host’ => ‘localhost’,
‘login’ => ‘user’,
‘password’ => ‘pass’,
‘database’ => ‘db2’,
));
と「reconnect」を使用して、動的に接続情報を指定して接続先を変更することが可能です。

CakePHP (1.3.5) radioボタンのvalue

Posted in CakePHP, PHP関連 on 10月 26th, 2010 by Site Administrator

formヘルパーのradioで、optionが
array(”=>’空白’,’0’=>’値0′,’1’=>’値1′)
等で選択肢に空文字と0が混在している場合、空文字がこのformに設定されるとPHPの仕様で0が選択されることとなります。

/cake/libs/view/helpers/form.php
の1087行目(Ver1.3.5の場合)
if (isset($value) && strval($optValue) == strval($value)) {
としておけば空文字・0をきちんと区別してくれます。

ちなみにselectの場合はデフォルトで大丈夫。

CakePHP (1.3.4) 異なるDB間のjoin

Posted in CakePHP, PHP関連 on 10月 22nd, 2010 by Site Administrator

CakePHP1.3.4の話。

model内に$useDbConfigを定義すれば、default以外の複数のDB接続設定を切り替えることができます。

ただしbelongsToなどで、あるmodelから違うDB接続設定がされたmodelのアソシエーション設定を行った場合、

発行されるSQL文が異なるDBを意識したものにはなりません。

このようなケースではbelongsToを使わず、素直にfind時のoptionsでjoinの設定を手動で行いましょう。

例えばpaginateで使用する場合は下記のような感じ。

$this->paginate['joins'] =  array(
 array(
  'type' => 'LEFT',
  'alias' => 'ModelName1',
  'table' => '`DbName`.`table_name`',
  'conditions' => array('ModelName2.id = ModelName1.id',),
 ),
);

CakePHP リバースプロキシ経由の接続

Posted in CakePHP, OS関連, PHP関連 on 10月 21st, 2010 by Site Administrator

Apacheでリバースプロキシを構築し、プロキシ経由でCakePHPサイトへ接続する場合

ProxyPass /aaaa http://target/aaaa
ProxyPassReverse /aaaa http://target/aaaa
ProxyPreserveHost On

などと設定する。「ProxyPreserveHost On」が必要。

CakePHP element間の変数の共有

Posted in CakePHP, PHP関連 on 10月 18th, 2010 by Site Administrator

CakePHPではviewを構成する要素の塊をelementとして定義できます。
そのelement間で変数の共有をしたかったので、いろいろ試してみました。

1.呼び出し元のviewで変数を定義

→NG。elementでは定義した変数が見えない。

2.Session変数

→NG。element(view)からはSessionへの書き込みができない。

3.Helperを定義し、その中で変数を定義。

→OK。element間で共有できた。

PHP 例外処理

Posted in PHP関連 on 10月 18th, 2010 by Site Administrator
    function test() {
        try
        {
            0/0;
        }
        catch(Exception $e)
        {
            throw $e;
        }
    }

0除算の際に例外が発生して、catch部で例外がthrowされるのかと思ったら、
PHPは例外発生時点で処理が止まってしまうのですね。
「0除算していないかのチェックを行い、問題があれば例外を発生させる」
という処理を明示的に書かなければならないというのが、他言語からすると信じられない。。。

Silverlight 同期処理

Posted in Silverlight on 10月 16th, 2010 by Site Administrator

SilverlightではWebClient等を使用して、非同期で各種データの取得ができます。

なんとか同期でデータの取得ができないかと調べてみたのですが、結論としては無理っぽい。

下記サンプルはデータを非同期で作成して、作成完了を待って戻すメソッドgetStringを含むtestクラスです。

呼び出し元からすると、getStringは同期処理で動くはずです。

    class test
    {
        private BackgroundWorker worker = new BackgroundWorker();
        private AutoResetEvent are = new AutoResetEvent(false);
        private string data = "";
        public test()
        {
            worker.DoWork += new DoWorkEventHandler(worker_DoWork);
            worker.RunWorkerCompleted += new
            RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
        }

        public string getString()
        {
            data = "";
            worker.RunWorkerAsync();
            are.WaitOne();
            return data;
        }
        private void worker_DoWork(object sender, DoWorkEventArgs e)
        {
            System.Threading.Thread.Sleep(1000);
            return;
        }
        private void worker_RunWorkerCompleted(object sender,
        RunWorkerCompletedEventArgs e)
        {
            data = "complete";
            are.Set();
        }
    }

上記クラスの呼び出し元について、下記のように書いてみます。

	private void button_Click(object sender, RoutedEventArgs e)
	{
		MessageBox.Show(this.getData());
	}

	private string getData()
	{
		string returnStr = "";
		test objTest = new test();
		returnStr = objTest.getString();
		return returnStr;
	}

結論として、動きません。反応なしです。書き換えてみます。

	private string getData()
	{
		string returnStr = "";
		Thread newThread = new Thread(() =>
		{
			test objTest = new test();
			returnStr = objTest.getString();
		//Dispatcher.BeginInvoke(() => MessageBox.Show(returnStr));
		});
		newThread.Start();
		return returnStr;
	}

動きますが、メッセージが空白表示です。Dispatcher.BeginInvokeのコメントをはずすと、きちんと表示されます。

別スレッド内では正常に動いているようです。スレッド終了を待つように書き換えてみます。

	private string getData()
	{
		string returnStr = "";
		Thread newThread = new Thread(() =>
		{
			test objTest = new test();
			returnStr = objTest.getString();
		//                Dispatcher.BeginInvoke(() => MessageBox.Show(returnStr));
		});
		newThread.Start();
		newThread.Join();
		return returnStr;
	}

正常に別スレッドのデータを取得できました!

次に、WebRequestでデータを取得するように変更します。
test.getStringを書き換えます。

	public string getString()
	{
		data = "";
		var wait = new AutoResetEvent(false);
		WebResponse ret = null;
		WebRequest wr = WebRequest.Create(new Uri("http://localhost:49698"));
		wr.BeginGetResponse(gr =>
		{
			ret = wr.EndGetResponse(gr);
			wait.Set();
		}, null);
		wait.WaitOne();
		var sr = new StreamReader(ret.GetResponseStream(), Encoding.UTF8);
		data = sr.ReadToEnd();
		ret.Close();
		return data;
	}

反応がありません。
getDataのThread.Joinをコメントアウトしてみます。

	private string getData()
	{
		string returnStr = "";
		Thread newThread = new Thread(() =>
		{
			test objTest = new test();
			returnStr = objTest.getString();
		//                Dispatcher.BeginInvoke(() => MessageBox.Show(returnStr));
		});
		newThread.Start();
		//newThread.Join();
		return returnStr;
	}

動きますが、メッセージが空白表示です。Dispatcher.BeginInvokeのコメントをはずすと、きちんと表示されます。

調べてみると、WebRequestの非同期データ取得の完了イベントは、UIスレッドに通知されるようです。

なので、UIスレッドでJoinなどの停止処理をいれていると、そこでロックがかかってしまうみたいです。

reactive extensionsを使えばできそうでもあるので、今後調べてみます。

Silverlight Object生成時の初期化パラメータ

Posted in Silverlight on 10月 15th, 2010 by Site Administrator

initparamsパラメータに、「パラメータ名=値」の形式で、複数ある場合はカンマ区切りで値を渡す。

<param name=”initparams”

value=”param1=param1value,param2=param2value />

なお、値を使うときは下記のとおり

private void Application_Startup(object sender, StartupEventArgs e)
{
string param1 = e.InitParams[“param1”];
string param2 = e.InitParams[“param2”];

//値を使う処理を下記続ける

}