開発メモ,主に補足by子連れ親父プログラマー

2012-07-08

一つ目を選択したら二つ目のセレクトの値が変化するようにしたいんだが、ソースの文字コードがEUCでjqueryのload()を使って読み込むと文字化けしてしまう。


一つ目を選択したら二つ目のセレクトの値が変化するようにしたいんだが、ソースの文字コードがEUCでjqueryのload()を使って読み込むと文字化けしてしまう。



文字コードがEUCなのは昔のソースなのでしょうがない。
いまさら直しようがない。
jquery の load() だと化けるってのもしょうがないだろう。調べるだけ無駄だ。
ということで、php側で一旦データを全部読み込んで、それをJSON形式のデータにして、直接javascriptのスクリプト部分に埋め込むことにしよう。

データのイメージ:
一つ目のセレクトがこんな感じであって、選択すると、

<select name="category_id">
    <option value="0">爬虫類</option>
    <option value="1">鳥類</option>
    <option value="2">昆虫option>
</select>
こんなようなデータが読み込まれて二つ目のセレクトが生成される。(鳥類だったら"1"のデータがセレクトになる)

var per_array ='{
    "0":{
        "1":"トカゲ",
        "2":"ワニ",
        "3":"ザリガニ",
    },
    "1":{
        "4":"スズメ",
        "5":"ハト",
        "6":"トンボ"
    },
    "2":{
        "7":"コオロギ",
        "8":"バッタ"
    }
}';

データベースにはこんな感じで入っている。

SELECT * FROM ikimono;
 id | category_id |   name   
----+-------------+----------
  1 |           0 | トカゲ
  2 |           0 | ワニ
  3 |           0 | ザリガニ
  4 |           1 | スズメ
  5 |           1 | ハト
  6 |           1 | トンボ
  7 |           2 | コオロギ
  8 |           2 | バッタ
(8 rows)

まず、データベースから値を読み込んで、JSON形式のデータを作成する。

$query = "SELECT id, name, category_id FROM ikimono";
$result = pg_query($pg, $query);
$n = pg_numrows($result);
if ($n){
    for ($i=0;$i<$n;$i++){
        $id = pg_result($result, $i, 0);
        $name = pg_result($result, $i, 1);
        $category_id = pg_result($result, $i, 2);
        // ここで一個一個配列に入れておいて
        $select_array[$category_id] .= '"'.$id.'":"'.$name.'",';
    }
}
// ここでカテゴリー別に {} で囲む
foreach($select_array as $k => $v) {
    $v = preg_replace('/,$/', '', $v);
    $ikimono_data .= '"' . $k . '":{' . $v . '},';
}
$ikimono_data = preg_replace('/,$/', '', $ikimono_data);// 最後のカンマを削除

で、ページ表示部分のjavascript部分をこんな感じで。
配列の定義のところに直接phpでデータを埋め込む。


<script>
$(document).ready(function(){
    $('select[name=category_id]').change(function(){
        var category_id = $(this).val();
        var ikimono_array ='{<?php echo $ikimono_data; ?>}';
        var obj = jQuery.parseJSON(ikimono_array)[category_id];
        var ikimono_select = '';
        for (key in obj) {
            ikimono_select += '<option value="'+key+'">' + obj[key] + "</option>";
        }
        $('select[name=ikimono_id]').empty().append(ikimono_select);
    }).change();
});
</script>

二個目のセレクトは空っぽで用意しておく。

<select name="ikimono_id">
</select>

もっと他にいい方法がありそうな予感が大いににするが、とりあえずこんなところで。

2012-07-01

登録日と更新日のフィールドがあって、その中で一番新しい日付を一発でセレクトするクエリー(CASE文とMAX)

登録日と更新日のフィールドがあって、その中で一番新しい日付を一発でセレクトするクエリー(CASE文とMAX)

登録日が created で、更新日が modified で、データを新規登録した時にね、
created には insert するけど、modified にはしない。
本当に編集した時だけ modified に入れるようなプログラムになってたとするじゃないですか。

そうするとデータはこんな感じになる訳で。

          created           |          modified          
----------------------------+----------------------------
 2009-03-17 10:18:24.792449 | 2009-03-17 10:32:55.900294
 2009-03-25 19:32:18.205694 | 
 2009-03-26 14:44:18.787866 | 
 2009-03-30 16:56:56.128813 | 
 2012-06-22 18:26:11.540513 | 
 2012-06-23 12:18:09.649044 | 
 2012-06-22 18:26:37.815316 | 2012-06-26 15:07:45.34223
 2012-06-21 12:46:03.151537 | 2012-06-26 16:44:05.811683
 2012-06-26 19:05:44.473284 | 2012-06-26 20:15:18.196717
 

modified は NULL になってるデータがある訳です。

こういう状態で、更新があった一番新しい日付をセレクトせよ、ってことなんですが。。。


 SELECT MAX(CASE WHEN modified IS NULL THEN created ELSE modified END) AS dates FROM items;
 

これでこうなる。

           dates            
----------------------------
 2012-06-26 20:15:18.196717
(1 row)
まあ、最初っから両方入れとけよって話ですね。



2012-04-04

XAMPP for Windows の .htaccess 設置でエラーで Symfony2 用に short_open_tag が Offにできない

XAMPP for Windows の .htaccess 設置でエラーで Symfony2 用に short_open_tag が Offにできない

いやー、まあ、何事かと思いましたけどね。 XAMPP のデフォルトでは、php.ini の short_open_tag が On で、apache の AllowOverride が All じゃない、 ってことで、Symfony2 を動かそうとして short_open_tag を Off にするとメタメタになってしまうわけです。 で、悩むこと数日間。

設定は、

C:\xampp\apache\conf\httpd.conf
ではなく、
C:\xampp\apache\conf\extra\httpd-xampp.conf 
でやります。

以下のようになっている部分があるので、

<Directory "C:/xampp/htdocs/xampp">
    <IfModule php5_module>
     <Files "status.php">
      php_admin_flag safe_mode off
     </Files>
    </IfModule>
    AllowOverride AuthConfig
</Directory>
以下のように書き換えます。
<Directory "C:/xampp/htdocs/xampp">
    <IfModule php5_module>
     <Files "status.php">
      php_admin_flag safe_mode off
     </Files>
    </IfModule>
    AllowOverride All
</Directory>

それから、C:\xampp\php\php.ini を開いて、

short_open_tag = Off
として、 C:\xampp\htdocs\xampp 以下に、.htaccess を置いて、
php_flag short_open_tag On 
と書けばよい。ちなみに Windows で .htaccess というファイルを作るには、FTPソフトを使えばよい。

2012-01-13

OSX の MacPorts で ZendFramework を入れてみた

OSX の MacPorts で ZendFramework を入れてみた

まずは、インストール。 検索すると、

port search zend
こうでるので、
ZendFramework @1.11.11 (www, lang)
    A framework for developing PHP web applications
こうする。

sudo port install ZendFramework

インストールの最後の方でこんなメッセージが出る。

If this is your first install, you might want to add  /opt/local/www/ZendFramework/library to the
include_path in your php.ini  (e.g. include_path = ".:/opt/local/www/ZendFramework/library"). 

If you want to use the extra ZendX components  you might want to add
/opt/local/www/ZendFramework/extras/library too  (e.g. include_path =
".:/opt/local/www/ZendFramework/library:/opt/local/www/ZendFramework/extra/library").

ということで、php.ini を編集。

cd /opt/local/etc/php5
sudo vim php.ini

として、include_path の部分を、

include_path = ".:/opt/local/lib/php:/opt/local/www/ZendFramework/library:/opt/local/www/ZendFramework/extra/library"
とする。アパッチ再起動。

sudo /opt/local/apache2/bin/apachectl restart

で、zendのコマンドラインツールであるzf.shが使えるようにパスを通しておく。

vim ~/.profile

でエディターを起動して、以下を追加。

export PATH=/opt/local/www/ZendFramework/bin:$PATH

アプリを作りたいディレクトリへ行って、

zf create project sample
と打つ。

こんな画面が表示された。

2011-12-26

OSX の MacPorts で入れた mysql-connector-java は一体どうやって使えばいいのか?

OSX の MacPorts で入れた mysql-connector-java は一体どうやって使えばいいのか?

引き続き java の servlet でのデータベース接続をテストしていた時のことである。
tomcat も MacPorts で入れたんだから Connector/J も当然 MacPortsで 入れるべきだろう、ということで、

sudo port install mysql-connector-java
こうした訳ですが、これはどうやら以下の場所に設置されるようです。

/opt/local/share/java/mysql-connector-java-5.0.jar

で、こいつをどう使ったらいいのか?
まずはコンパイルする時のために自分の.profile にパスを追加。
エディターで、

vim ~/.profile  
として、以下を追加。

export CLASSPATH=/opt/local/share/java/tomcat6/lib/servlet-api.jar
export CLASSPATH=/opt/local/share/java/mysql-connector-java-5.0.jar:$CLASSPATH
export CLASSPATH=$CLASSPATH:.

パスが通ったかどうか、

echo $CLASSPATH
して確認。

これでコンパイルは通る。

で、tomcat上で、作ったservletを実行するためには、

/opt/local/share/java/mysql-connector-java-5.0.jar
このファイルを、
/opt/local/share/java/tomcat6/webapps/sample/WEB-INF/lib
以下に置く(sampleは自分で作ったservlet置き場)。

もしくは、

/opt/local/share/java/tomcat6/lib/
以下に置く。

シンボリックリンクでもいけるので、

cd /opt/local/share/java/tomcat6/lib
sudo ln -s /opt/local/share/java/mysql-connector-java-5.0.jar mysql-connector-java-5.0.jar
こうしておけばよいかもしれない。

2011-11-20

OSX Lion に Tomcat6 を入れて Java のサーブレットで HelloWorld するまでのすったもんだ

OSX Lion に Tomcat6 を入れて Java のサーブレットで HelloWorld するまでのすったもんだ

そういえばLionにしてから自宅の開発環境がほったらかしになってたな、と、嫌な予感はしていたんだが、いざ始めてみると大仕事に。 Java の SDK は入ってるはずだから Tomcat だけ入れればいいはず、と思って、

sudo port install tomcat6

と打った最初っからつまづいた。 まず MacPorts そのものがバージョン2.0.3にアップしていてこの selfupdate ができない。 Xcode を4.1にバージョンアップしろ、と言われる。 でApp Store で Xcode を検索してインストール。 App Store の画面でインストール済みになって、それからどうすればいいのか分からず、途中作業中断もはさんで大幅に時間ロス。 ふと見ると Application の中に Install Xcode というアイコンができているのでそれを起動で無事完了。 MacPorts のバージョンアップをして、引き続き Tomcat を入れる。

http://localhost:8080

を開いてみると得体の知れない EnterpriseDB とかいう画面が開くだけなので、(←なんすかね、これ)

sudo vim /opt/local/share/java/tomcat6/conf/server.xml

として、8080になってるところを8090に変更。 さらに、

sudo vim /opt/local/share/java/tomcat6/conf/tomcat-users.xml

として、Tomcat のアプリケーションマネージャ画面に入るためのIDとパスワードを設定する。

<tomcat-users>
    <role rolename="manager-gui"/>
    <user username="myname" password="mypassword" roles="manager-gui"/>
</tomcat-users>

HelloWorld 用のjava ファイルを用意して、

javac HelloWorld.java 

とするも文字化け。

vim ~/.profile

として、末尾に

alias javac="javac -J-Dfile.encoding=UTF8"
alias java="java -Dfile.encoding=UTF8"

を追加。文字化けは収まったが、コンパイルに失敗するので、 さらに .profile に

export CLASSPATH=/opt/local/share/java/tomcat6/lib/servlet-api.jar

を追加。

javac HelloWorld.java 

とやって、HelloWorld.class を作成する。

/opt/local/share/java/tomcat6/webapps

以下に、

/opt/local/share/java/tomcat6/webapps/sample

というフォルダーを作り、さらにその中に、

/opt/local/share/java/tomcat6/webapps/sample/WEB-INF
/opt/local/share/java/tomcat6/webapps/sample/WEB-INF/classes
/opt/local/share/java/tomcat6/webapps/sample/WEB-INF/src
/opt/local/share/java/tomcat6/webapps/sample/WEB-INF/lib

とフォルダーを作って、 classes の中に HelloWorld.class を、src の中に HelloWorld.java を、 WEB-INF 直下に web.xml を置いて、

http://localhost:8090/sample/Hello

で完成。

2011-11-13

JavaScript の継承とカプセル化

JavaScript の継承とカプセル化

参考文献:Supercharged JavaScript Graphics: with HTML5 canvas, jQuery, and More より。

いろんなやり方があるが、これが一番自然な方法なんじゃないかと筆者は言っている。

<script type="text/javascript">
var pet = function(name, legs) {
    var that = {
        name: name,
        getDetails: function(){
            return that.name + ' has ' + legs + ' legs';
        }
    };
    return that;
};
var cat = function(name) {
    var that = pet(name, 4);
    that.action = function(){
        return 'free as a bird';
    };
    return that;
};
</script>
var neko = cat('tama');

こうして neko を作った後で、neko の name を変えることはできるが、legs は変えられない、という訳である。

2011-11-06

CakePHP1.3で作る会員管理システム(26) バッチ処理

バッチ処理

では最後、バッチを使ってデータを更新したり、削除したりします。 バッチの処理は /app/venders/shells/ の中にファイルを作ります。今回はmembersテーブルのデータを処理するので、 /app/venders/shells/member.php とします。 で、中に以下のように書きます。

<?php
class MemberShell extends Shell {
    var $uses = array('Member');
    function main() {

        //メールアドレスにgを含むデータを削除、関連テーブルからも
        $this->Member->deleteAll(
            array('Member.email LIKE' => "%g%"), true, false
        );
    }
}
?>

$uses で使うモデルを指定しています。 削除ではなく、更新をする場合は、

$this->Member->updateAll(
    array('Member.birthday' => "'1970-03-15'"),
    array('Member.created <=' => "$this_day")
);

こんな感じになります。 このファイルを用意しておいて、コンソールから、

cd /Users/myname/Sites/cake/app
cake member

と実行します。app に入っていることが大事です。 crontab から実行する時はフルパスで書けばよいでしょう。

/Users/myname/Sites/cake/cake/console/cake member -app /Users/myname/Sites/cake/app

以上で今回作ったシステムのまとめは終わりです。

[おわり]

CakePHP1.3で作る会員管理システム(25) 検索結果CSVダウンロード

検索結果CSVダウンロード

検索結果をCSVでダウンロードする処理を追加します。 検索の処理部分は全く同じで言い訳ですから、同じadmin_serchアクションに、またモードを指定して、ダウンロードモードの時はCSVにするようにします。 まず、レイアウトとビューを用意しておきます。 /app/views/layouts/csv.ctp を新規作成して、

<?php
    header('content-type: text/plain');
    header("Content-Type: application/octet-stream");
    header("Content-Disposition: attachment; filename=member.csv");
?>
<?php echo $content_for_layout; ?>

とします。 ビューは、 /app/views/members/admin_download.ctpとして、

<?php foreach ($members as $member): ?>
<?php 
    echo $member['Member']['id'];
    echo $member['Member']['email'];
    echo $member['Member']['password'];
    echo $member['Type']['name'];
    echo $this->Time->format($format = 'Y/m/d', $member['Member']['birthday']);
    echo $this->Time->format($format = 'Y/m/d', $member['Member']['created']); 
?> 
<?php endforeach; ?>

このように書いておきます。 で、会員検索のビュー、admin_search.ctp に以下を追加しておきます。

<p><?php echo $this->Paginator->link(__('CSVダウンロード', true), array('mode'=>'DL')); ?></p>

こうするとリンクに引数を渡せます。 で、コントローラ members_controller.php のadmin_searchアクションの一番下に、

        if ((isset($this->passedArgs['mode'])) && ($this->passedArgs['mode'] == 'DL')) {
            Configure::write('debug', 0);
            $this->layout = 'csv';
            $data = $this->Member->find('all',  array(
                'order'=>array('Member.id'),
                'conditions' => $conditions
            ));
            $this->set("members", $data);
            $this->render('admin_download');
        }

を追加します。 mode=”DL” で来た時は $conditions だけ引き継いで検索し直してる感じですかね。

このブログを検索

Powered by Blogger.

ラベル

php (17) jQuery (13) OSX (10) MySQL (8) Javascript (7) Postgres (7) port (7) apache (6) Java (3) Smarty (2) html (2) pear (2) FCKEditor (1) XAMPP (1) css (1) git (1) perl (1) ruby (1)

Facebookバナー