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

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 だけ引き継いで検索し直してる感じですかね。

CakePHP1.3で作る会員管理システム(24) 検索とPaginationとHABTM

検索とPaginationとHABTM

で、さらにやっかいなのが、ここに「好きな物」のチェックボックスの複数選択検索を入れる場合です。 HABTMの関連テーブルですね。 一体どうすりゃいいんでしょうか。ということで相当悩みました。 結論としては、一旦その「好きな物」を選択している会員のIDを全部取り出して、そいつを条件に入れちゃえばいいんじゃなかろうかと。 クエリーのイメージはこんな感じ。

SELECT m.id FROM members m WHERE m.id IN
(SELECT member_id FROM members_favorites mf WHERE mf.favorite_id IN (1,2));

つまり()内のSELECTの部分をあらかじめデータ取得しておけばいいと。 ということでこうなった。

            $fid = $this->Member->MembersFavorite->find('list', array(
                'order'=>array('MembersFavorite.member_id DESC'),
                'group'=>array('MembersFavorite.member_id'),
                'fields' => array('MembersFavorite.member_id'),
                'conditions' => array('MembersFavorite.favorite_id' => $favorite_id)
            ));
            $conditions = array("Member.id" => $fid);
            $data = $this->paginate('Member', $conditions);

これは上記ではIN ()の中はSELECT文になっているが、CakePHPの文法だとそれは入らないようなので、実際に配列が入る。こんな感じになる。

SELECT `MembersFavorite`.`id`, `MembersFavorite`.`member_id` 
FROM `members_favorites` AS `MembersFavorite` 
WHERE `MembersFavorite`.`favorite_id` IN (1, 2, 3) 
GROUP BY `MembersFavorite`.`member_id` 
ORDER BY `MembersFavorite`.`member_id` DESC 

最終的にこうなりました。

    function admin_search() {
        $this->Member->recursive = 0;

        if (!empty($this->data)) {
            $f = $this->data['Member']['from'];
            $t = $this->data['Member']['to'];
            $email = $this->data['Member']['email'];
            $type_id = $this->data['Member']['type_id'];
            $favorite_id = $this->data['Member']['favorites'];
        }else{
            foreach ($this->passedArgs as $k => $v){
                if ($k == 'from'){
                    list($f['year'], $f['month'], $f['day']) = preg_split("/-/", $v);
                }elseif($k == 'to'){
                    list($t['year'], $t['month'], $t['day']) = preg_split("/-/", $v);
                }elseif($k == 'email'){
                    $email = urldecode($v);
                }elseif($k == 'type_id'){
                    $type_id = urldecode($v);
                } elseif(preg_match("/^favorite_id_([0-9]+)$/", $k, $regs)) {
                    $favorite_id[$regs[1]] = $v;
                }
            }
        }
     
        if (isset($f) && isset($t)){
            if ($this->_from_to_check($f, $t)) {
                $from = $f['year']."-".$f['month']."-".$f['day'];
                $to = $t['year']."-".$t['month']."-".$t['day'];
                $this->data['Member']['from'] = $f;
                $this->data['Member']['to'] = $t;
            }
        }
        if(isset($email)){
            $this->data['Member']['email'] = $email;
        }
        if(isset($type_id)){
            $this->data['Member']['type_id'] = $type_id;
        }
        if (isset($favorite_id)){
            $this->data['Member']['favorites'] = $favorite_id;
        }
        
     
        $searchword = array();
        $conditions = array();
        if (isset($from) && isset($to)){
            $searchword = array(
                "from" => urlencode($from),
                "to" => urlencode($to),
            );
            $conditions = array("Member.created BETWEEN ? AND ?" => array($from,$to));
        }
        if (isset($email) && $email){
            $searchword = $searchword + array(
                "email" => urlencode("$email"),
            );
            $conditions = $conditions + array("Member.email LIKE" => "%$email%");
        }
        if (isset($type_id) && $type_id){
            $searchword = $searchword + array(
                "type_id" => urlencode("$type_id"),
            );
            $conditions = $conditions + array("Member.type_id" => $type_id);
        }
        if (isset($favorite_id) && $favorite_id){
            foreach ($favorite_id as $k => $v){
                $temp_favotite['favorite_id_'.$k] = $v;
            }
            $searchword = $searchword + $temp_favotite;
            $fid = $this->Member->MembersFavorite->find('list', array(
                'order'=>array('MembersFavorite.member_id DESC'),
                'group'=>array('MembersFavorite.member_id'),
                'fields' => array('MembersFavorite.member_id'),
                'conditions' => array('MembersFavorite.favorite_id' => $favorite_id)
            ));
            $conditions = $conditions + array("Member.id" => $fid);
        }
     
        $data = $this->paginate('Member', $conditions);
        $this->set('searchword', $searchword);
        $this->set("members", $data);
         
        $favorites = $this->Member->Favorite->find('list');
        $types = $this->Member->Type->find('list');
        $this->set(compact('favorites','types'));
    }

このブログを検索

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バナー