2012年6月29日金曜日

2012年06月29日 講義088日目

2012年06月29日
講義088日目
------------------------------1H------------------------------
★職場体験
●インポートのプログラムを作成する
・任意のディレクトリを作成する
・実行権限のあるphpファイルを作成する
・コマンドでphpファイルを実行する
●ファイルが存在してるか確認の条件分岐
・file_exists()
------------------------------2H------------------------------
●ファイルを/csvから/importにコピーする
・copy()
・アパッチからの書き込み権限(その他の書き込み権限)が無かったので
  ブラウザ上からのコピーができてなかった
・puttyで自分のユーザで打てば解決
------------------------------3H------------------------------
●nkfコマンドを実行してutf-8に変換
・nkf -w --overwriteコマンドをphpのsystem()で実行するロジックを作成
☆linuxでしか動かない処理なので関数化するなどして複数の環境で対応できるようにする
●csvファイルを取り込む
・fopen()
・fgetcsv()  第二引数は一行のバイト数っぽい
・fgetcsv()はcsvファイルの接続情報しか変数に入らないので、接続情報をwhileでまわす
  $data配列をさらに別な$arr_import_file配列に入れて多次元配列で保持
  フラグを立てて、最初のカラム名部分を読み込まないロジックを作成してもいい
------------------------------4H------------------------------
●//データベースに接続
・配列を色々取得したりとか試行錯誤
・結局時間内には完成しなかった
  データベースに入力する部分までたどり着けなかったのは残念だ
------------------------------5H------------------------------
★職場体験
●インポートのプログラムの解説
・まずはファイル/ディレクトリ構成を決めておく
  base_csvディレクトリ→元になるcsvが置かれるべき場所
  tmpディレクトリ→作業ディレクトリ
  outputディレクトリ→吐き出されるcsvが置かれる場所
  logディレクトリ→ログ保存
  import_php→インポートの処理を行うプログラム
・ロジックの流れ
①ファイルのコピー
②データの読み込み、文字コードのチェック
③読み込んだデータを出力フォーマット配列に放り込む
  住所、沿線のチェック、必要に応じてログ吐き出し
④csvが置かれる場所に吐き出す
⑤tmpディレクトリのコピーを消す

☆returnでエラーの表示をして処理を終了させてもいい
  exitは使わないほうがいい
  exit(1);などで正常終了してるかを判断するなども可能
-----------------------------memo------------------------------

2012年6月27日水曜日

2012年06月27日 講義087日目

2012年06月27日
講義087日目
------------------------------1H------------------------------
★職業体験
●マッピングテーブルの作成
・m_stationのline_nameを抽出
SELECT line_name FROM m_station GROUP BY line_name;
・master_ensen_abstractのensen_nameを抽出
SELECT ensen_name FROM master_ensen_abstract GROUP BY ensen_name
------------------------------2H------------------------------
●マッピングテーブルの作成
・whileで回さないと配列にできないことをすっかり忘れていた件
$sql = "SELECT ensen_name FROM master_ensen_abstract GROUP BY ensen_name";
$result =mysql_query($sql);
$row = mysql_fetch_array($result);

while($row = mysql_fetch_array($result)){
    $sql_master_ensen_abstractEnsen_name[] =$row;
}

foreach($m_stationLine_name as $k => $v){
    foreach($master_ensen_abstractEnsen_name as $k2 => $v2){
        if($k == $k2){
            $ensen[] = $k;
        }else{
            $ensen2[] = $k
        }
    }
}
------------------------------3H------------------------------
●マッピングテーブルの作成
foreach($arr_master_ensen_abstractEnsen_name as $k2 => $v2){
    $flg = 0;
    foreach($arr_m_stationLine_name as $k => $v){
        if($v == $v2){
            $arr_ensen[$v] = $v2;
            $flg = 1;
        }
    }
    if($flg != 1){
        $arr_notmach_ensen[] = $v2;
    }
}
------------------------------4H------------------------------
●マッピングテーブルの作成
・similar_text()を使ってみた
foreach($arr_notmach_ensen as $k => $v){
    $flg = 0;
    foreach($arr_m_stationLine_name as $k2 => $v2){
        $c = similar_text($v, $v2, $percent);
        if($percent > 70){
            echo $v." と ".$v2." は ".intval($percent)."%一致します".$c."文字一致します<br>";
            $arr_ensen2[$v2] = $v;
            $flg = 1;
        }
    }
        if($flg != 1){
            $arr_notmach2_ensen[] = $v;
        }
    }
    print_r($arr_ensen2);
------------------------------5H------------------------------
●マッピングテーブルの作成
・マッピングに必要な沿線の総数→81件
・完全一致させるて抽出の結果→14件
・similar_text()を使用して抽出の結果
80%→36件
75%→44件 ほぼ大体間違えてない(気がする)
70%→56件 ほとんどマッチする、間違った結果もいくつか含まれた
65%→85件 なんだか微妙な結果に 重複が目に余る
60%→完全につかいものにならない結果に→数えるまでもない
------------------------------6H------------------------------
●インポートのプログラムを作成する
・目的:物件情報のcsv内のデータを
          沿線マッピングテーブル
          住所テーブル
          出力フォーマット
        を元にして、指定されたフォーマットに書き換えてcsvで出力するプログラムを作成する
・使用するファイル
  元となるcsvファイル、日々異なる内容のcsvを得る
  出力するcsvのフォーマット
  住所一覧のテーブル
●作業手順
・物件情報のcsvを読み込み、内容を出力用に書き換えてcsvで吐き出すロジックを作成する
●注意点
・csvを読み込んだだけでは文字化けしてる可能性がある
  ソース内で文字コードを変換する
  CentOS上で実施してるならexec関数でnkfコマンドを実行するなどして対処
・住所コードや沿線・駅コードに、実在しないデータが存在した場合は、その物件は処理しない
  (その際、エラーメッセージを出したり、ログに書き込むなどすると良い)
・出力ファイルに書き込む際にはflock関数を使って排他ロックする
・可能なら
    出力されるレコードの
    address_idには、「例)学園東町~」のデータを含む11桁の数字とする
    block_numberには、所在地詳細_非表示部のみが入る
  難しいなら、所在地名称と所在地詳細_非表示を合わせた文章をblock_numberカラムに入れる
-----------------------------memo------------------------------

2012年6月25日月曜日

2012年06月25日 講義086日目

2012年06月25日
講義086日目
------------------------------1H------------------------------
★職場体験
●コンバート
・コンバートの流れ
公開したいデータ
入力したいデータ
↓インポート
コンバートシステム
↓エクスポート↓
サイトA、サイトB……
・目的:記述の異なる二つの沿線情報をマッピングするためのマッピングテーブルの作成
  サイトによって違う情報をすり合わせるためにマッピングテーブルを作成
  コンバートするサイトによってデータの形式が違う
●sqlファイルをデータベースにインポート
・mysql> create database work_experience;
データベースを作る
・FFFTPで
homeディレクトリにコピー
mysql -u nishi -p データベース名 < インポートしたいsqlファイル.sql
・myphpadminで
インポートの項目からインポートする
------------------------------2H------------------------------
★職場体験
●テーブルの作成
・mappingテーブルの作成
ensen_id : char(4)
eki_id : char(3)
line_cd : char(5)
station_cd : char(7)
☆line_cdとstation_cdがユニークなキー
------------------------------3H------------------------------
★職場体験
●phpプロジェクトの作成
・VM内にディレクトリを作成
・vhostとかhostsとか色々設定
・以前使ったmyUtilでDBに接続→パスワードが間違っててハマる
  echo ini_set("display_errors","1");
  でエラーを表示させて、解決
・とりあえずprint_r()でDBの中身を表示
------------------------------4H------------------------------
★職場体験
●DBにcsvファイルをインポートする
・四苦八苦するなど
・結局カラムの型を適当にintに設定してたのが原因だった
  charと緯度経度はdoubleに変更して正常にインポートすることができた
------------------------------5H------------------------------
★職場体験
●SQL文を復習するとか
------------------------------6H------------------------------
★職場体験
●SQL文の入れ子
・IN()などで二つのDBのカラム名の比較が実現可能らしい
・master_ensen_abstractDBのline_nameと
  m_stationDBのensen_name|ensen_name_short
・master_ensen_abstractDBのstation_name
  m_stationDBのeki_name|eki_name_short
  がそれっぽく一致したレコードに
  m_stationDBのline_cd,station_cd
  master_ensen_abstractDBのensen_id,eki_id
  をレコードに入れる
  的なロジックを作る感じのアプローチかな
・なんとなく一致してるロジックは正規表現?がスキル的に無理かなーとか
-----------------------------memo------------------------------

2012年06月21日 講義085日目

2012年06月21日
講義085日目
------------------------------1H------------------------------
★最終課題
●昨日進めたこと
・jqueryの読み込みの順番の見直し、ライブラリ別に整理するなどの改善
・ログイン画面にhero-unitの導入
・問題点→レシートモジュールのメニューのjavascriptが効かなくなった
          <!-- bootstrap-image-gallery -->を読み込んでる部分で再度古いbootstrapを読み込んでいた

●actionからtemplateへassign
action側  $this->でsymfonyのクラスを使ってオブジェクトをassign
例)$this->comments = 何かの値
template側 
例)<?php foreach($comments as $comment):?>
    $comment->getCategoryId()や$comment->getUrl()のようにオブジェクトから値を引っ張る
------------------------------2H------------------------------
------------------------------3H------------------------------
●レシートモジュール
・Feed内の値の取得方法で完全に迷宮に突入
・一つのFeedからテンプレート側で色々取得できる感じだったのに、ほしいurlまでたどり着けなかった
  関数が用意されてない
・foreachの中で別の配列をインクリメントさせてまわすとかで解決した
------------------------------4H------------------------------
------------------------------5H------------------------------
------------------------------6H------------------------------
●色々と行き詰るなど
-----------------------------memo------------------------------

2012年6月19日火曜日

2012年06月19日 講義084日目

2012年06月19日
講義084日目
------------------------------1H------------------------------
★小テスト返却
・vi で開いたファイル内の検索
/検索したい文字列で検索できる
例)/PHP
★最終課題
●コンポーネント
・コンポーネント化する部分について考えるとか
ログインページ(loguinSubmitのアクションで)
新規ユーザ登録ページ(loginモジュールでやるんじゃなくて別モジュールに飛ばして解決するほうがいい?)
使い方を見るページへ(別モジュールに飛ばすリンクのみ)
をdefault/indexに配置してるので、どうしようかと考える

結論→ログインモジュールはログインだけやらせる
      新規ユーザ作成モジュールを作成し、そこに飛ばすことに

●ログインの機能強化について
・setcookie()
  クッキーに接続情報を登録する関数
・データベースに最終アクセス日時が登録
  それとクッキーの中身を照合するロジックを配置するなどが必要
 
結論→そのうち作ってみるか
------------------------------2H------------------------------
●user_registrationモジュール
・とりあえずlogin画面と切り分け
・ボタンの場所とかレイアウトが気に食わないとかはとりあえず放置で
  むしろ、作業の優先順位的に新規作成モジュール自体を放置の予感
------------------------------3H------------------------------
●レシートモジュールを改修
・レシートの
  望む動きがページ遷移では実現できないっぽいことが判明
------------------------------4H------------------------------
●flexslider
・jqueryでコンテンツスライダーを実現する
  色々と探す、たくさんの候補があるがシンプルなものを選ぶ(時間がかかる)
・flexsliderというのがよさそうなので実装
------------------------------5H------------------------------
------------------------------6H------------------------------
●flexslider
・cssが効かないという問題
-----------------------------memo------------------------------
やらなきゃリスト
・レシートモジュールで取得したように
  マップモジュールで位置情報を取得する
  ポインタを位置情報の分だけ作成
  ・レシートモジュールに対して、そのレシート写真へのリンクを作る(レシートモジュールそういうアクションを作る)
  ・ドキュメントモジュールに対して、そのレシートドキュメントの編集リンクも作る(ドキュメントモジュールにそういうアクションを作る)

2012年6月18日月曜日

2012年06月18日 講義083日目

2012年06月18日
講義083日目
------------------------------1H------------------------------
★最終課題
●zend AuthSubの実装
------------------------------2H------------------------------
●zend AuthSubの実装
・find ./ -name "*.php" | xargs grep ""
でそのディレクトリにある.php内のキーワードを絞り込んで探せる
Zendまで行って関数を見に行くとかする
------------------------------3H------------------------------
●zend AuthSubの実装
・結局、マニュアルのAuthSubの説明のソースを使ったらうまくできた
・セッションに作成したトークンがモジュール間で重複していたのが原因の一つとしてありそうだったので、
そのあたりを解消できたっぽいので解決したという予想(結局原因は不明)
・echoされてる部分をheader()でリダイレクトに変更
------------------------------4H------------------------------
●zend AuthSubの実装
・ログアウトするとAuthSubで使ったセッションを消去したりするロジックを追加
  $_SESSION = array();
  セッションを空にするとか
  マニュアルではなんか色々と複雑なことをやってるっぽい感じだったけど
------------------------------5H------------------------------
●ドキュメント
FeedからspreadsheetKeyを取得するために試行錯誤してみるとか
------------------------------6H------------------------------
●ドキュメント
・spreadsheetKeyの取得
  strlen()で文字列の長さを取得
  str()でその文字列の長さ分削る
・メニューをスプレッドシート一覧にしてドキュメントの数だけループさせメニュー作成
  問題点→表示の上限をどうやって設定するか→登録したシートのみ表示させるとか
         
  ドキュメントは表示させるだけにしようか
・検索フォームも使いたい
-----------------------------memo------------------------------

2012年6月14日木曜日

2012年06月14日 講義082日目

2012年06月14日
講義082日目
------------------------------1H------------------------------
------------------------------2H------------------------------
●spreadsheetrenderer.js
・という便利なライブラリを公開してる人がいたのでありがたく使わせて頂く
http://webos-goodies.jp/archives/spreadsheetrenderer_js_an_easy_way_to_display_spreadsheet.html
・しかしサンプルソースではうまく動かなかった
<script type="text/javascript">
//template.addWindowEvent('load', function() {
  var renderer = new SpreadsheetRenderer({
    key: 'キーの値を入れます',
    template:'<li>%0% : %1% : %2%</li>' });

  renderer.render('select * limit 10', 'result');
//});
</script>
こうやったら動いた、自力では表示させられなかったので動きがよくわかってない
しかし、これで直接テーブルが作れるっぽいので試行錯誤してみるなど
------------------------------3H------------------------------
●小テスト
・Linuxコマンド
------------------------------4H------------------------------
●spreadsheetrenderer.js
・テーブルを表示させてみるなど
・表示はできたが、カラム名を読み込んでくれない仕様っぽいという問題
  解決プラン→カラム名決め打ちで<head>を準備してしまう
              例えば、ユーザの設定に配列で保持してそれを読み込むとか
              配列の数を数えてその分だけ<td>を作り出す<?php ?>を埋め込む
・そもそもテーブルを表示する必要あるのか疑問に思い始めるなど
・やっぱりinputモジュールが必要な気がしてきた
  receiptモジュールでインプットモードになるというのでもいいかもしれないが
------------------------------5H------------------------------
●google chart tools
・chartを表示させるテスト
・Homeのエリア3つ、タブでの表示切り替えについての問題点
  エリアが3つなので表示の迫力がなく、文字の視認性も悪くなってる
  表示エリアは2つが限界かもしれない
・やはりHomeが入力モードであるほうがいいのかも
  Homeでレシート画像、データ入力を登録
・レシートモジュールで画像をクリックすると編集モードになるように
・新たにチャートモジュールを作るのがいいかも
------------------------------6H------------------------------
●色々散漫になってきたので優先順位を考えるなど
・picasaに画像が入力できる
  spreadsheetにデータが入力できる
  spreadsheetのデータを編集できる
・入力したデータをチャートに表示できる
--------↑完成しないとグダグダになるライン---------
・カレンダーで購入履歴をチェックできる
・レシート画像表示選択で入力したデータの編集画面に飛ぶ
--------↓無ければ無いで諦めが付くライン-----------
・BBS機能
●サイトの構成を見直す
・チャートモジュールを作成
・Homeに入力フォーム領域、写真表示領域を作る
-----------------------------memo------------------------------
あと二週間で発表か

2012年06月13日 講義081日目

2012年06月13日
講義081日目
------------------------------1H------------------------------
★svn
●リポジトリの準備の流れ
・プロジェクトをサーバ側に作る
・クライアント側でバージョン管理したいプロジェクトを作成する
・クライアントとサーバを紐付ける.svnファイルを作成する(チェックアウト)
  svn checkout
・ひとまず空のプロジェクトをコミットする
  svn ci * -m ""
  リビジョンは1となる、中身はまだ無い
・クライアント側で開発が進行したら、差分を確認する
  svn stat -u
・コミットする
  svn ci * -m ""
  リビジョンは2となる
・symfonyで開発してる場合、cacheやlogをいちいちコミットするのは非効率なのでリポジトリにコミットされないように設定する
  svn propedit svn:ignore ./cache
  viの中に対象外にするファイルを指定する
  全ての場合は*/*(cacheフォルダの下のファイルまで全部)と記述して保存
  やり直したい場合はコマンドをもう一度打って編集
  svn propedit svn:ignore ./log
  viの中に対象外にするファイルを指定する
  全ての場合は*と記述して保存
  やり直したい場合はコマンドをもう一度打って編集
・.svnを編集したのでリポジトリにコミットする
  svn ci * -m ""
  リビジョンは3となる
・symfony側のcache、logを更新する
  symfony fix-permes
  symfony cc
  これでリポジトリとの差分が発生
・リポジトリとの差分を確認
  svn stat -u
・!の表示はリポジトリに存在しない発生したcache、logなので、それらを消去
  svn rm 「svn stat -uで表示された!のついたフォルダ」
  stat -uで表示される!をD(消去)にする
・cache、logの無い状態のプロジェクトをコミットする
  svn ci * -m ""
  リビジョンは4となる
●リポジトリを使う
・共同で開発してる場合は、開発を始める前にsvn up
  自分の開発がひと段落したらコミットするsvn ci -m ""
--------------------------------------------------------------
★.htaccessについて(これだと通らないので後で修正)
●sakuraのwwwに配置する.htaccessについて
/www  ←webルート
/www/project/web  ←frontのパス
/www/project/web/backend  ←他のアプリのパス
の場合

/www/.htaccess
RewriteEngine On
RewriteBase   /
RewriteRule ^(backend/.*)$ /project/web/backend/backend.php
            ↑どんなurlか  ↑どのディレクトリに飛ばすか
RewriteRule ^(.*)$ /project/web
            ↑RewriteRuleの一番最後には、それ以外のアドレスを打たれたらどうするかを指定
           
☆RewriteRuleは上から優先
☆sakuraの本ドメインを使うことにしたらプロジェクトのディレクトリを指定して、
  それ以外のディレクトリにアクセスできないようにする必要がある
------------------------------2H------------------------------
★最終課題
・ログインページに新規登録を追加
  新規登録のactionを増やす
・helpモジュールの作成
  bbsと連動させたいけど今は保留
  わからないことがあったらbbsにいって質問してねフォームを作るとかで対応
  開発者にメールする機能も作ろうかどうしようか、メールが来ても答えられない気がするからどうしよう
・tourモジュールの作成
  外部から専用ページなのでレイアウトはloginlogout.phpを使う
・bbsモジュールの作成
  actionでなんとかなるっぽい
☆カベージコレクト
  サイトの余分なデータをどうにかすること
  cronでtempのデータを消去したりする
  phpではgc~~()などで関数が用意されてる
------------------------------3H------------------------------
●googledocsのspredsheetのfeed
・資料を読むなど
------------------------------4H------------------------------
●googledocsのspredsheetのfeed
・feedの内容を取得してみるなど
------------------------------5H------------------------------
●Zend_Gdata_Spreadsheets
・色々と接続してみる
------------------------------6H------------------------------
●Zend_Gdata_Spreadsheets
・google chart toolsはWEBに公開してないと
  直接Spreadsheetsで作ったガジェットを表示できない
・というか、ガジェットを作るという手間を導入する意味が基本的に無いということに気が付いた
  どーしたもんかなー楽に表を作れるんじゃないかというイメージとは程遠かった
・Zend_Gdata_Spreadsheetsの構造化問い合わせで取得したい値をgoogle chart toolsで表示していく感じか
・google chart toolsのscriptに<php ?>を埋め込んで動的に表示させる方向で
-----------------------------memo------------------------------

2012年6月13日水曜日

2012年06月12日 講義080日目

2012年06月12日
講義080日目
------------------------------1H------------------------------
★最終課題
●backendのurl直打ち対策など
・default:
  is_secure: on
  credentials: [member, admin]
  に設定、is_secure: をonにし忘れて/backendに進入できるというミスをするなど
  とりあえず権限を持ってないとbackendには入れない状態
------------------------------2H------------------------------
●バックエンドのページ遷移を整えるなど
・404エラーページの表示
・defaultに申し訳程度にリンクを作る
・memberのcrudは基本的なバリデーションとかかける程度で放置の予定
・seculityは多分大丈夫な気がする
------------------------------3H------------------------------
------------------------------4H------------------------------
★バージョン管理ソフトの導入
●リポジトリの保存に際してキャッシュを対象外にする
・svnで使うエディターを設定する
  [ユーザ名@localhost ~]$ vi .bash_profile
  export SVN_EDITOR="vi"
  を最後の行に追加
  [ユーザ名@localhost ~]$ source .bash_profile
  で変更を有効にする

・キャッシュとログを弾く.svnの設定を書き換える
  リポジトリにコミットされない様に設定
  svn propedit svn:ignore ./cache
  viの中に対象外にするファイルを指定する
  全ての場合は*/*(cacheフォルダの下のファイルまで全部)と記述して保存
  やり直したい場合はコマンドをもう一度打って編集
  svn propedit svn:ignore ./log
  viの中に対象外にするファイルを指定する
  全ての場合は*と記述して保存
  やり直したい場合はコマンドをもう一度打って編集
・svn stat -u
  M→変更がある
  A→新たに追加
  ?→リポジトリに無い
  !→リポジトリにしかない
  D→削除予定
  C→コンフリクト
・開発したソースをリポジトリにコミットするための準備
  svn add *で?をAする
  svn delete *で!をDにする

------------------------------5H------------------------------
●google docsのフィードの表示を試行錯誤してみる
・カレンダーと同様にClientAuthで接続(後日Auth subに変更する)
          //スプレッドシートの一覧の取得
        $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
        $spreadsheetService = new Zend_Gdata_Spreadsheets($client);
        $feed = $spreadsheetService->getSpreadsheetFeed();

        foreach($feed->entries as $entry){
            echo $entry->title->text;
            echo "<br>";
        }
------------------------------6H------------------------------
●google docsのフィードの表示を試行錯誤してみる
・spreadsheetKey
  どうやらURLらしい
  すでに取得してるらしい
-----------------------------memo------------------------------

2012年6月12日火曜日

2012年06月11日 講義079日目

2012年06月11日
講義079日目
------------------------------1H------------------------------
★最終課題
●マイアカウント画面作成
・タブ表示にする部分とそうでない部分を悩むなど
・タブ一つにつき一つのアクション(一つのタブにつき一つのデータベースを更新)
  コンポーネントにするという手もあるっぽいが、動的じゃないのでパーシャルでいい気がする
  アクションとテンプレートが連携していればコンポーネントということになるっぽい
  クラス作らないとコンポーネントとして定義できないから調べる
・モジュール内のテンプレートを指定する方法
  <?php include_partial("モジュール名/_テンプレート名")?>
------------------------------2H------------------------------
●マイアカウント画面のフォームを作成する
・formタグの@~~とか、別に今はとりあえず使わないでいいか
・なんかフォームがズレる件
------------------------------3H------------------------------
●modelとschema
・symfony propel-build-modelでデータベース名Peer.phpのextendした関数は上書きされてしまうんだっけ?
・backendにmemberモジュールを作成
・[ユーザ名@サーバ名 ~/www/sftest]$ symfony propel-generate-crud backend member Member
  引数は三つ、また間違えてサーバに怒られるなど
------------------------------4H------------------------------
------------------------------5H------------------------------
------------------------------6H------------------------------
★バージョン管理ソフトの導入
●SVN
・リポジトリ
  ソースの情報を管理する
・SVNサーバ用のソフトをインストールして使う
・クライアント側にもソフトをインストールする
[root@localhost ユーザ名]# yum -y install subversion mod_dav_svn
・svnサーバをネット上に持つ
  google codeを使う
  http://code.google.com/hosting/
  ・Project name  自分のプロジェクト名
    Version control system  Subversion
    などを記入してプロジェクトを作成
  ・自分のサーバのプロジェクトがある階層に[ユーザ名@サーバ名 ~/www]$ mkdir sftest_dev
  ・goglecodeのsouceタブを開き、
    svn checkout https://自分のプロジェクト名.googlecode.com/svn/trunk/ sftest-mis019 --username 自分のグーグルアカウント名
    を打つ
  ・開発してるディレクトリをコピー
  ・.svnのあるフォルダでリポジトリを作成するコマンド svn add * を打つ
  ・svn ci * -m ""
    -m はコメントを入れるオプション""で空文字を入れる
    空文字を入れないとviでコメントを入れないとならなくなる
●よく使うsvnコマンド
  ・コピー先に移動して
    svn add *
    svn ci * -m ""
  ・状態を調べる
    svn stat -u
    svn info
  ・リポジトリを消す
    svn rm
    svn delete
  ・複数のリポジトリ間で環境を一致させる
    svn merge
  ・ソースの衝突(コンフリクト)を解除する
    svn resolved
  ・リポジトリ無いのソースの表示
    svn list
  ・最新のリポジトリ情報で更新
    svn up
  ・リポジトリの情報でプロジェクトを作成
    svn co
   
●リポジトリをgooglecodeからチェックアウトする
  ・まだsvn管理していない本来のソースのあるプロジェクトに移動して
    svn checkout https://自分のプロジェクト名.googlecode.com/svn/trunk/ ./ --username 自分のグーグルアカウント名
    を打ってみる
  ・リポジトリがあるかどうか確認する
    googlecodeのBrowseで見ることができる
  ・チェックアウトできたらsymfonyコマンドで権限などを整える
    symfony fix-parms
    symfony cc

●バージョンを上げる場合
  svn stat -u
    差分を表示する
      M→変更されたファイル
      ?→新たに作られたファイル
    symfonyの場合は、cacheを避けたディレクトリで打つなどする
  svn add
  svn ci * -m ""

・データベースの情報はとって置けないのでdumpでどこか別に保持する

●レンタルサーバにsvnクライアントをインストール
svn infoでサーバに存在してるか確認
●xammpにsvnクライアントインストール
TortoiseSVNをインストール
外部でリポジトリを持ちたくない場合など
-----------------------------memo------------------------------
問題点メモ
マップ
表示にhtmlを宣言するときに publicを入れるとマップが表示されない
メニューの検索などのスタイルがpublicを入れないと崩れる

レシート
bootstrap ImageGalleryの挙動がなんかおかしい

マイアカウント
フォームのズレ

symfony propel-build-modelでデータベース名Peer.phpのextendした関数は上書きされてしまうんだっけ?

2012年6月8日金曜日

2012年06月08日 講義078日目

------------------------------1H------------------------------
★最終課題
●イメージギャラリーの設置
・マニュアルを見て試行錯誤
・スクリプトを読み込む位置に迷うなど→<head>でいいんじゃねという結論
レイアウトの切り分けも後でいいんじゃないかと思うなど
------------------------------2H------------------------------
●イメージギャラリーの設置
単純に<a href="">で指定するファイルの記述を間違っていただけ
とりあえず表示されたので、順次以下の問題を解決する
  picasaと接続した場合の表示
  サムネイルを並べて表示させたい
  ナビバーのメニューで昇順降順、年月日別、タグ別、店別などのソートができるといい(これは全ての機能に実装したい)
------------------------------3H------------------------------
●picasaへの接続テスト
symfonyがlibの下に置いてあるclassは読み込んでくれるのでrequire_onceとかを書かなくても良い
UserFeedは取得できるが、AlbumFeedが取得できずサムネイルが表示できない
インクリメントする前の変数は$i = 0;などで初期化しておくと、Noticeが出ないっぽい
サンプルソースのエスケープが効いてなかったっぽくて肝心の画像表示部分がソースに隠れてたorz
------------------------------4H------------------------------
●backendの作成
管理者は少人数なのでコマンドでざっくり作る
装飾などは別にやらなくていいかも
セキュリティだけは完全にする
●sfPageFrowでざっくり作るために
rootが取れるサーバでやらないとできない
☆同じデータベース名などで上書きされてしまう可能性があるので、気をつける
念のためにgenerate用のプロジェクトなどを作るのがいいかも
①schema.ymlのテーブル情報をrootが取れるサーバにコピー
②build-model
③symfony propel-generate-crud コマンドを使う
作られたモジュールをrootが取れないサーバにコピーするなどして使う
------------------------------5H------------------------------
------------------------------6H------------------------------
●マイアカウントページの作成
ユーザが自分のデータベースの内容を編集できる
やり直す機能なども実装したい、前の設定に戻す、デフォルトに戻すなど
conf_map
conf_calendar
conf_document
conf_receipt
テーブルの作成

中身はサービスが出来てきたら考える

-----------------------------memo------------------------------

2012年06月07日 講義077日目

2012年06月07日
講義077日目
------------------------------1H------------------------------
●ログインのレイアウトを独立させる
・layoutの切り替えを実装、各modulesのconfigにview.ymlを設置
・frontのtemplateにloginlogout.phpという新しいテンプレートを設置しそれを読み込む
------------------------------2H------------------------------
●マップ用の<head>を作るために
・_head.phpテンプレートを独自に作成させるプラン
  _head.phpテンプレート内で条件分岐させるプラン
↓ではなく
スロットを使って解決
☆どうやらfooterでjsで読み込んでるので全て表示されるまでjquery部分が動かない
  最適化する必要がある
 
●_menu.phpのメニューで表示中のページがアクティブになるようにする
<?php $module = $sf_context->getModuleName();?>
        <li <?php echo($module == "default")?"class=\"active\"":"";?>><a href="/">Home</a></li>
       
●404ページが表示されない件
☆error404Success.phpがerror404SUCCESS.phpと間違っていた
------------------------------3H------------------------------
★ログイン、ログアウトの実装
●modelが作成されない件
☆propel.iniとdatabase.ymlの設定をサーバにつなぐための値に変更し忘れてた
●ログイン機能の実装
seculity.ymlの編集でmember権限が無い場合にログインページに飛ばす処理をする

ログインの挙動メモ
①バリデーションにかける
  カスタムバリデーションを作って、ログイン失敗したら戻す
②executeSubmitでテンプレートを指定する
例)
  $this->setTemplate("読み込ませたいテンプレート");
  $this->mailaddress = $this->getRequestParameter("mailaddress");
  などにしてアサインする
③forwordさせる(handleerrorと同じ挙動)or redirect
例)
  $this->forword("default","index");

  ①と②、①と③を組み合わせるパターンで作成するのが良い
●handleErrorSubmit()の作成
とりあえずバリデーションを作成した後のために作った
------------------------------4H------------------------------
●ログアウト実装
logoutモジュールにseculity.ymlを作成して、  is_secure: offに設定
loginモジュールにもseculity.ymlを作成して、  is_secure: offに設定
してやらないと、権限が無くて挙動がおかしくなる
☆loginモジュールにexecuteSubmitを作成したのはバリデーションをかけるため
------------------------------5H------------------------------
------------------------------6H------------------------------
●Zendを読み込むために
libの下に直接Zendのライブラリを配置して解決するしかなかった
本来ならpearでインストールしたZendを読み込んで、複数のプロジェクトから読み込みたかったが
今はとりあえずこれで読み込めてるので我慢して開発していく
-----------------------------memo------------------------------
やらなきゃならんことメモ
bootstrap ImageGalleryの設置

2012年6月5日火曜日

2012年06月05日 講義076日目

2012年06月05日
講義076日目
------------------------------1H------------------------------
------------------------------2H------------------------------
★最終課題開発
●仕様書の作成
・内部仕様書
  データベース構成を大体決める
・外部仕様書
  画面遷移図の作成
・ページの構成
  ユーザが移動できるのはfrontのみ
  backendは管理者(とりあえず一人)のみ
  backendに関しては基本的にsymfonyで作成、とりあえず見た目は凝らなくていいんじゃないか
------------------------------3H------------------------------
●各メニューページの作成
・各ページを作成していく
・遷移のテスト
------------------------------4H------------------------------
●データベースとテーブルの作成
・さくらの管理ページからデータベースを作成する
  テーブルも少ないのでとりあえず作ってテスト用のデータを入力
・routing.yml
色々設定できる
・404ページを作成
先に作っておいて、表示されたらリンクとrouting.ymlを確認する的な
setting.ymlの404の設定部分のコメントが外れてることを確認

・datanases.ymlの接続情報を編集
dsn:          mysql://ユーザ名:パスワード@データベースサーバ名/データベース名
・テーブルを作る
CREATE TABLE member (
id int not null auto_increment,
username text,
mailaddress text,
password text,
admin_yn char(1),
delete_yn char(1),
updated_at datetime,
created_at datetime,
primary key(id)
);

データの入力
INSERT INTO member(
username, mailaddress, password, admin_yn, delete_yn, updated_at, created_at)
values
("test1", "test1", "test1", "y", "n", "2012-06-06 00:00:00", "2012-06-05 00:00:00");
sql文がぜんぜん受け付けられなくて四苦八苦(結局カラム名に""を使ったのが原因っぽい)
------------------------------5H------------------------------
●ruthingとかなんとかで詰る、集中力が完全に終了するなど
------------------------------6H------------------------------
●なんだかbackendに.htaccessをコピーして書き換えるとかなんとか
-----------------------------memo------------------------------

2012年06月04日 講義075日目

2012年06月04日
講義075日目
------------------------------1H------------------------------
★最終課題開発
●.htaccessの挙動がコントロールできない
・色々いじるが結局symfonyに飛ばせないのでサブドメインを取得して直接飛ぶことにした
・mod_rewriteの挙動は公開するまでになんとか把握することに
・正規表現も同時に学習しないと
------------------------------2H------------------------------
●.htaccessの挙動への対応
・BASIC認証をかける
・symfonyのプロジェクトはサブドメインで対応
・その他のテストファイルは放置
・wordpressとec-cube、ポートフォリオ(予定地)も順次サブドメインに逃がす
問題→取得できるサブドメインが一個足りないのでどうしたもんか
------------------------------3H------------------------------
●googlemapのapiを使う場合
<!DOCUTYPE PUBLIC>

PUBLICを消去しないと動かない
●smartyで書かれたレシート管理webサービスをsymfonyに移行する
・とりあえずトップページからコピペで、動かないであろう部分の修正
・menuなどのテンプレート部分をsymfony向けに見直すなど
------------------------------4H------------------------------
●レイアウト、設定などの移行作業
・/web/index.php
開発中のデバック有効にする
・開発中の表示部分の見栄えをよくするためのシンボリックリンクを作成(というか丸ごとコピーでも可)
[ユーザ名@サーバ]$ find ./ -name sf
./local/lib/php/data/symfony/web/sf
これをコピー
[ユーザ名@サーバ ~/www/sftest/web]$ cp -a /home/ユーザ名/local/lib/php/data/symfony/web/sf ./sf
------------------------------5H------------------------------
●jqueryのCDN
・リンクを貼る場所に悩む
とりあえず
・cssファイルへのリンク→_head.php
bootstrapとかもCDNあると楽なんだけど、なんか見つけられなかった

・scriptへのリンク→_footer.php
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/jquery-ui.min.js"></script>

なんかheadに書いたほうが気がするけどfooterでまとめて管理、後でどちらが良いのか調べる
------------------------------6H------------------------------
●モジュールを作る
・zendでつなぐ予定のモジュール→calendar、map、receipt、を作成
早いところ大枠を作って接続、編集、サイトに結果を反映まで行かないと間に合わないかも
カレンダー→google calendar
地図→google map
データシート→google docs
レシート→picasa
を使う予定
・わかりにくかったレシート、データシートメニューの改善

データシートはdocument
・費目だけではなく、タグ的なカラムも設定した方が検索などにもいいんだろうけど
  複数のタグを入力とかに対応するのはどうしよう
-----------------------------memo------------------------------
・明日はとりあえずはバックエンドと外枠の使用を固める
・ユーザの設定ファイルのみをデータベースに保持する
  費目などののユーザによる設定などを実装したい

2012年6月4日月曜日

2012年06月01日 講義074日目

2012年06月01日
講義074日目
------------------------------1H------------------------------
★symfony
●pager
・.pagerをstyle.cssに追加
.pager {
    text-align: center;
}

.pager ul {
    text-align: center;
    height: 25px;
}

.pager li {
    margin: 0 6px;
    display: inline;
    zoom: 7;
}

・pagerの拡張
ヘルパーを
/lib/helper/MyPagerQueryHelper.php
配置

/fornt /default actions.class.php
$this->search_arr = array()
に追加
        $this->search_arr = array(
        //pager機能に持たせるクエリパラメータ

        //実装するページのモジュールとアクション名
        "module" => "default",
        "action" => "index" ,
        //昇順降順情報
        "order" => $this->getRequestParameter("order_by"),

/front /default indexSuccess.php
<?php include_partial("global/pager",
            array("pager" => $pager,
                  "query" => $sf_context->getModuleName().
                             "/".
                             $sf_context->getActionName().
                             "?"
                 )
)?>

<?php include_partial("global/pager",
            array("pager" => $pager,
                  "query" => parameter_to_query(
                                $sf_context->getModuleName(),
                                $sf_context->getActionName(),
                                $search_arr)
                 )
------------------------------2H------------------------------
★symfony
●昇順降順機能の実装
・とりあえずリンクを作る
front /default actions.class.php

<?php  if($search_arr["order_by"] != "asc"):?>
<a href= "./?order_by=asc">created_atをascで並び替える</a>
<?php else:?>
<a href= "./order_by=desc">created_atをdescで並び替える</a>
<?php endif;?>


・クリックしたら出力が逆になる
→MODELの修正
/model CommentPeer.php

        //pagerの昇順降順入れ替えのための条件分岐
        if($search_arr["order_by"] != "asc"){
            $c->addDescendingOrderByColumn(self::CREATED_AT);
        }else{
            $c->addAscendingOrderByColumn(self::CREATED_AT);
        }

・他のパラメータも持ったままにする
→テンプレートの修正


class CommentPeer extends BaseCommentPeer
{
    static function getBbsArticles($search_arr = array(), $page = 1, $perpage = 10){
        $c = new Criteria;

        //$search_arrが存在する場合、検索条件によりadd
        foreach($search_arr as $k =>$v){
            switch($k){
                case "word":
                    if($v != ""){
                        $c->add(self::CONTENT, "%{$v}%", Criteria::LIKE);
                    }
                    break;
                case "category":
                    if($v != ""){
                        $c->add(self::CATEGORY_ID, $v);
                    }
                    break;
                case "date_start":
                case "date_end":
                    if(isset($date_flg)){
                        break;
                    }
                    //一つのカラムに複数の条件をつける際にgetNewCriterion()を使う
                    if($search_arr["date_start"] && $search_arr["date_end"]){
                        $c1 = $c->getNewCriterion(self::CREATED_AT,$search_arr["date_start"], Criteria::GREATER_EQUAL);
                        $c2 = $c->getNewCriterion(self::CREATED_AT,$search_arr["date_end"], Criteria::LESS_EQUAL);
                        $c1->addAnd($c2);
                        $c->add($c1);
                    }elseif($search_arr["date_start"]){
                        $c->add(self::CREATED_AT,$search_arr["date_start"],Criteria::GREATER_THAN);
                    }elseif($search_arr["date_end"]){
                        $c->add(self::CREATED_AT,$search_arr["date_end"],Criteria::LESS_THAN);
                    }
                    $date_flg = 1;
                    break;
                case "photo":
                    if($v == "y"){
                        $c1 = $c->getNewCriterion(self::PHOTO, "", Criteria::NOT_EQUAL);
                        $c2 = $c->getNewCriterion(self::PHOTO, NULL, Criteria::NOT_EQUAL);
                        $c1->addAnd($c2);
                        $c->add($c1);
                    }elseif($v == "n"){
                        $c1 = $c->getNewCriterion(self::PHOTO, "");
                        $c2 = $c->getNewCriterion(self::PHOTO, NULL);
                        $c1->addOr($c2);
                        $c->add($c1);
                    }
                    break;
                case "url":
                    if($v == "y"){
                        $c1 = $c->getNewCriterion(self::URL, "", Criteria::NOT_EQUAL);
                        $c2 = $c->getNewCriterion(self::URL, NULL, Criteria::NOT_EQUAL);
                        $c1->addAnd($c2);
                        $c->add($c1);
                    }elseif($v == "n"){
                        $c1 = $c->getNewCriterion(self::URL,"");
                        $c2 = $c->getNewCriterion(self::URL,NULL);
                        $c1->addOr($c2);
                        $c->add($c1);
                    }
                    break;
            }
        }

        //自身のクラスを参照する場合のみ、「Peer」ではなく「salf」で参照する

        //pagerの昇順降順入れ替えのための条件分岐
        if($search_arr["order_by"] != "asc"){
            $c->addDescendingOrderByColumn(self::CREATED_AT);
        }else{
            $c->addAscendingOrderByColumn(self::CREATED_AT);
        }


        //ページ数とページ位置により、表示する内容を操作するクラス
        $pager = new sfPropelPager("Comment",$perpage);
        $pager->setCriteria($c);
        $pager->setPage($page);
        $pager->init();
        return $pager;

        //↓sfPageFlowを使わない場合
        //return self::doSelect($c);
    }

↓関数を分割してわかりやすく
    static function getBbsArticles($search_arr = array(), $page = 1, $perpage = 10){
        $c = new Criteria;

        //$search_arrが存在する場合、検索条件によりadd
        foreach($search_arr as $k =>$v){
            switch($k){
                case "word":
                    if($v != ""){
                        $c->add(self::CONTENT, "%{$v}%", Criteria::LIKE);
                    }
                    break;
                case "category":
                    if($v != ""){
                        $c->add(self::CATEGORY_ID, $v);
                    }
                    break;
                case "date_start":
                case "date_end":
                    if(isset($date_flg)){
                        break;
                    }
                    //一つのカラムに複数の条件をつける際にgetNewCriterion()を使う
                    if($search_arr["date_start"] && $search_arr["date_end"]){
                        $c1 = $c->getNewCriterion(self::CREATED_AT,$search_arr["date_start"], Criteria::GREATER_EQUAL);
                        $c2 = $c->getNewCriterion(self::CREATED_AT,$search_arr["date_end"], Criteria::LESS_EQUAL);
                        $c1->addAnd($c2);
                        $c->add($c1);
                    }elseif($search_arr["date_start"]){
                        $c->add(self::CREATED_AT,$search_arr["date_start"],Criteria::GREATER_THAN);
                    }elseif($search_arr["date_end"]){
                        $c->add(self::CREATED_AT,$search_arr["date_end"],Criteria::LESS_THAN);
                    }
                    $date_flg = 1;
                    break;
                case "photo":
                    if($v == "y"){
                        $c1 = $c->getNewCriterion(self::PHOTO, "", Criteria::NOT_EQUAL);
                        $c2 = $c->getNewCriterion(self::PHOTO, NULL, Criteria::NOT_EQUAL);
                        $c1->addAnd($c2);
                        $c->add($c1);
                    }elseif($v == "n"){
                        $c1 = $c->getNewCriterion(self::PHOTO, "");
                        $c2 = $c->getNewCriterion(self::PHOTO, NULL);
                        $c1->addOr($c2);
                        $c->add($c1);
                    }
                    break;
                case "url":
                    if($v == "y"){
                        $c1 = $c->getNewCriterion(self::URL, "", Criteria::NOT_EQUAL);
                        $c2 = $c->getNewCriterion(self::URL, NULL, Criteria::NOT_EQUAL);
                        $c1->addAnd($c2);
                        $c->add($c1);
                    }elseif($v == "n"){
                        $c1 = $c->getNewCriterion(self::URL,"");
                        $c2 = $c->getNewCriterion(self::URL,NULL);
                        $c1->addOr($c2);
                        $c->add($c1);
                    }
                    break;
            }
        }

        //昇順降順を指定
        $c = self::setOrderByParam($search_arr["order_by"], $c);

        //getPropelPagerObject()のオブジェクトを取得
        $rtn = self::getPropelPagerObject($c, $perpage, $page);
        return $rtn;

        //↓sfPageFlowを使わない場合
        //return self::doSelect($c);
    }

    protected static function setOrderByParam($param, $c){
                //自身のクラスを参照する場合のみ、「Peer」ではなく「salf」で参照する

        //pagerの昇順降順入れ替えのための条件分岐
        if($param != "asc"){
            $c->addDescendingOrderByColumn(self::CREATED_AT);
        }else{
            $c->addAscendingOrderByColumn(self::CREATED_AT);
        }
        return $c;
    }

    protected static function getPropelPagerObject($c, $perpage, $page){
        //ページ数とページ位置により、表示する内容を操作するクラス
        $pager = new sfPropelPager("Comment",$perpage);
        $pager->setCriteria($c);
        $pager->setPage($page);
        $pager->init();
        return $pager;
    }
------------------------------3H------------------------------
★symfony
●pager
・パラメータを取得できるようにする

actions.class.php

$this->search_arr = array(

"order_by" => $this->getRequestParameter("order_by", "desc"),
を追加

        //パラメータの値を書き換える処理
        if($this->search_arr["order_by"] == "desc"){
            $this->search_arr["order_by"] = "asc";
        }else{
            $this->search_arr["order_by"] = "desc";
        }
indexSuccess.php

<?php //pagerでリンクを作るときのパラメータ取得部分を変数に入れですっきりさせた
$query = parameter_to_query($sf_context->getModuleName(), $sf_context->getActionName(), $search_arr)?>

<?php include_partial("global/pager", array("pager" => $pager, "query" => $query))?>
<?php //ifでascかdescを各々出力させていた部分をパラメータの値を省略?>
<a href= "/<?php echo $query?>">created_atを<?php echo $search_arr["order_by"]?>で並び替える</a>
------------------------------4H------------------------------
★symfony
●symfony freezeとsymfony unfreezeでsandboxにする
・symfony freeze
symfonyのライブラリを別の領域にコピーして独立させることができるコマンド
バージョン管理などで使う
☆使うときに/web/sfは消しておく(あるとコマンドが効かない)
・symfony unfreeze
symfonyのバージョンアップなどを反映させるためにfreezeを解除させるコマンド
☆注意点!
・sandbox化した後の権限を正常にする
symfony fix-parms

●開発用symfony環境サーバ→本番用symfony環境サーバ移行の注意点
バージョンに注意
configのサーバのパスなどに注意

開発環境
複数の場所で開発したりする

●開発フロー
テスト環境
データベース、アプリケーションのバージョンを本番環境と同様にして動かす
細かい詰め作業をする
うまくいかなかったら開発環境に戻る

本番環境
実際に稼動させる

●バージョン管理ソフト
Subversionなどのソフトで管理
------------------------------5H------------------------------
★最終課題
centOSかxammpで開発しておき、後でリリース
●サーバ選び
・CGIが使えるかどうか(自分の開発言語、たとえばPHPが使えるかどうか、バージョン情報も確認)
・DBが使えるかどうか
・MYSQLが使えるかどうか
別に他のデータベースを使うんでもいい
・取れるサブドメイン、メールアカウントの数
SEO的に共有だと同サーバの他のサイトにも影響しあう
・SSH接続
無いとputtyとかでつなげない
●制作の条件
なんでもいい
外部に公開するつもりで作る
------------------------------6H------------------------------
★最終課題開発
●.htaccess
/local/lib/php/htdocs/sf.testにリダイレクトする
はずだったが、うまくいかないので
/wwwに直接プロジェクトを作成
・[nishi@localhost web]$ vi .htaccess
Options +FollowSymLinks +ExecCGI

<IfModule mod_rewrite.c>
  RewriteEngine On

  # uncomment the following line, if you are having trouble
  # getting no_script_name to work
  #RewriteBase /

  # we skip all files with .something
  # comment the following 3 lines to allow periods in routes
  RewriteCond %{REQUEST_URI} \..+$
  RewriteCond %{REQUEST_URI} !\.html$
  RewriteRule .* - [L]

  # we check if the .html version is here (caching)
  RewriteRule ^$ index.html [QSA]
  RewriteRule ^([^.]+)$ $1.html [QSA]
  RewriteCond %{REQUEST_FILENAME} !-f

  # no, so we redirect to our front web controller
  RewriteRule ^(backend/.*)$ backend/backend.php [QSA,L]
  RewriteRule ^(.*)$ ./sftest/web/index.php [QSA,L]
</IfModule>

# big crash from our front web controller
ErrorDocument 500 "<h2>Application error</h2>symfony application failed to start properly"

・↑だとうまくいかないので次回に
-----------------------------memo------------------------------