忍者ブログ
[PR]
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。



2025/11/30 00:01 |
Symfony1.2 10日目
ずいぶん久しぶりに再開。

投稿フォームを作成します。
通常の投稿フォームでは、まず入力画面を作成し、入力のバリデーションを作成し、保存を行うといった流れで開発すると思います。
Symfonyでは先に投稿フォーム用のクラスを作成し、画面描写もバリデーションもそちらに任せてしまうことになります。

Symfonyのフォームは、画面上の入力欄を決定するヴィジェットと、バリデーションを行うバリデータの二つに分かれています。
フォームは基本的にデータベースと直結しており、データベースを作成したときにフォームの基礎も一緒に作成されています。
lib/form/doctrine/base/BaseJobeetJobForm.phpを見てみると、BaseJobeetJobForm::setWidgets()でヴィジェットが、BaseJobeetJobForm::setValidators()でバリデータが定義されているのがなんとなくわかります。


とりあえずデフォルトのフォームを見てみます。
まずはこれまで機能していなかった「POST A JOB」リンクを編集。

apps/frontend/templates/layout.php
1
<a href="<?php echo url_for('@job_new') ?>">Post a Job</a>

ルーティングの一番上にあるjob:class:sfDoctrineRouteCollectionに引っかかり、/job/newへのリンクに変化します。
リンクを辿るとjobActions::executeNew()が実行されます。

中身は前作成したこれだけです。

apps/frontend/modules/job/actions/actions.class.php
1
2
3
4
<?php
    public function executeNew(sfWebRequest $request){
      $this->form = new JobeetJobForm();
    }

$formにJobeetJobFormクラスをそのまま突っ込んでいます。
setTemplate()が無いのでデフォルトのnewSuccess.phpが適用され、echo $formでJobeetJobFormの全てが表示されます。


これからデフォルトのフォームを改造していきます。
フォームを触る場合はlib/form/doctrine/base/BaseJobeetJobForm.phpではなくlib/form/doctrine/JobeetJobForm.phpを利用し、これらの初期値を上書きしていく形でフォームを整えていきます。

その前にとりあえず修正前のフォームを見てみると、Category idがテキスト入力欄ではなくカテゴリ名選択になっています。
スキーマではcategory_id:{ type: integer, notnull: true }となっており明らかにテキストなのですが、勝手にリレーションを辿ってJobeetCategoryに行き着くようです。
そこまではまあいいのですが、何処にもjobeet_category.nameを表示せよみたいなことを書いた覚えはないのですが、一体何処からどうやってjobeet_job.category_idjobeet_category.nameを結び付けると判断したのかさっぱりだ。


デフォルトでは全てのカラムが表示されるようになっています。
どのような入力欄となるかはスキーマから自動的に決められます。
主キーであるidはhiddenとなり、varchar型であるtypeやcompany等はtextとなり、bool型はチェックボックスとなり、datetime型は年月日時分選択フォームとなります。
それは便利ですが、created_atやexpires_atなんかはシステム側で自動的に登録させたいので入力欄を表示させたくありません。
フォームから入力欄を削除したい場合、単にフォームクラスからフィールドを削除します。

lib/form/doctrine/JobeetJobForm.class.php
1
2
3
4
5
6
7
8
9
10
11
12
13
<?phpclass JobeetJobForm extends BaseJobeetJobForm{
  /*
   * 初期設定
   */
  public function configure(){
      //不要な入力欄を表示しない
      unset(
      $this['created_at'], $this['updated_at'],
      $this['expires_at'], $this['is_activated']
    );
  }}

バリデータもスキーマから自動的に決定されます。
jobeet_job.companyはスキーマ上ではemail:{ type: string(255), notnull: true }となっており、バリデータにも予め「最大255文字」というバリデーションが設定されています。
単純なバリデーションであればこのままで問題無いですが、もっと複雑なバリデーションを行いたい場合もあります。
jobeet_job.emailはメールアドレスの登録欄ですが、現状ではjobeet_job.company同様255文字以内というバリデータしか設定されていません。
バリデータをメールアドレス形式のみを受け付ける形に差し替えます。

lib/form/doctrine/JobeetJobForm.class.php
1
2
3
4
5
<?phppublic function configure(){
  //メアドのバリデータ
  $this->validatorSchema['email'] = new sfValidatorEmail();
}

Symfonyには多くのバリデータが用意されており、基本的にバリデータクラスを選択するだけでバリデーションを行うことができます。
sfValidatorEmailはメールアドレス形式のバリデーションを行うことができます。
まあ、'...@a.aa'みたいなRFC違反のメールアドレスも通してしまうアバウトなものですが。

上記のバリデータはBaseJobeetJobFormで定義されているバリデータを上書きしています。
元々あった255文字以内というバリデータは消滅してしまうのです。
sfValidatorAndクラスを使うことで、一つのフィールドに複数のバリデータを定義することができます。

lib/form/doctrine/JobeetJobForm.class.php
1
2
3
4
5
6
7
8
9
10
<?phppublic function configure(){
  //メアドのバリデータ
  $this->validatorSchema['email'] = new sfValidatorAnd(
    array(
       $this->validatorSchema['email']
      ,new sfValidatorEmail()
    )
  );
}

元のバリデータにsfValidatorEmailをプラスしています。
これで「255文字以内、かつメールアドレス形式」というバリデーションが完成しました。
残念なことにフォームタグにmaxlength属性は付加されませんが、255文字以上の文字列を突っ込むとバリデーションエラーが発生し、エラーメッセージが表示されます。


現在jobeet_job.typeはvarchar型ですが、ここを特定の文字列しか入れられないようにしたい、というバリデーションを作成してみます。
特定の文字列しか許されないという具体的な内容はバリデータではなくテーブルに持たせるべきですので、JobeetJobTableモデルに記述する必要があります。
現在のJobeetJobTableに以下を追加。

lib/model/doctrine/JobeetJobTable.class.php
1
2
3
4
5
6
7
8
9
<?phpstatic public $types = array(
  'full-time' => 'Full time',
  'part-time' => 'Part time',
  'freelance' => 'Freelance',
);
public function getTypes(){
  return self::$types;
}

フォームのヴィジェットをデフォルトのテキストからラジオボタンに変更。

lib/form/doctrine/JobeetJobForm.class.php
1
2
3
4
5
<?php$this->widgetSchema['type'] = new sfWidgetFormChoice(array(
  'choices'  => Doctrine::getTable('JobeetJob')->getTypes(),
  'expanded' => true,
));
sfWidgetFormChoiceはラジオボタン、もしくはチェックボックスを意味するクラスです。
引数は配列になり、'choices'に具体的な選択肢を配列で与えます。
'multiple'及び'expanded'の引数を与えるとドロップダウンリストやチェックボックス等に変化します。

今変更したのはヴィジェットだけなので、選択肢以外の値を無理矢理送ったとしてもバリデーションを通過してしまいます。
バリデータもヴィジェットに合わせて修正する必要があります。

lib/form/doctrine/JobeetJobForm.class.php
1
2
3
4
<?php$this->validatorSchema['type'] = new sfValidatorChoice(array(
  'choices' => array_keys(Doctrine::getTable('JobeetJob')->getTypes()),
));

ヴィジェットと違うところとしてarray_keys()に注意が必要ですが、これで簡単にヴィジェットとバリデーションを合わせることが出来ました。
選択肢以外の値を送るとバリデーションエラーが発生するようになりました。


jobeet_job.logoは、ロゴ画像をアップロードした場合、そのファイル名を格納する場所になるということだそうです。
ということでファイルアップロード用のヴィジェットとバリデータを設定する必要があります。

まずアップロードしたファイルを置く場所を設置します。
web/uploads/jobsディレクトリを新規作成し、Apacheに書き込み権限を与えます。

ヴィジェットをファイルアップロードフォームに変更。

lib/form/doctrine/JobeetJobForm.class.php
1
2
3
4
<?php$this->widgetSchema['logo'] = new sfWidgetFormInputFile(array(
  'label' => 'Company logo',
));

ファイルのアップロード用フォームが設定されます。
また、このヴィジェットを設定すると<form> に自動的にenctype="multipart/form-data"が追加されます。

バリデータを追加。

lib/form/doctrine/JobeetJobForm.class.php
1
2
3
4
5
6
<?php$this->validatorSchema['logo'] = new sfValidatorFile(array(
  'required'   => false,
  'path'       => sfConfig::get('sf_upload_dir').'/jobs',
  'mime_types' => 'web_images',
));
これでファイルのアップロードフォームが完成しまし……エラーになりました。

> 500 | Internal Server Error | InvalidArgumentException
> This form is multipart, which means you need to supply a files array as the bind() method second argument.

jobActions::processForm()内でフォームに投稿された値をバインドしていますが、現状は以下のようになっていました。

apps/frontend/modules/job/actions/actions.class.php
1
2
3
4
5
6
7
8
<?php
  protected function processForm(sfWebRequest $request, sfForm $form){
    $form->bind($request->getParameter($form->getName()));
    if ($form->isValid()){
      $jobeet_job = $form->save();
      $this->redirect('job/edit?id='.$jobeet_job->getId());
    }
  }

一方チュートリアル的にはこうなっているはずだったみたいです。

1
2
3
4
5
6
7
8
9
10
11
<?phpprotected function processForm(sfWebRequest $request, sfForm $form){
  $form->bind(
    $request->getParameter($form->getName()),
    $request->getFiles($form->getName())
  );
  if ($form->isValid()){
    $job = $form->save();
    $this->redirect($this->generateUrl('job_show', $job));
  }}

こんなところ触った覚えないんだが何故違うんだろう?
ファイルアップロードフォームは他のフォームと内容がかなり違うので、バインドもファイルだけ独立して行うことになっているようです。
jobActions::processForm()をチュートリアルに合わせて修正。


>バリデーターはデータベースに相対パスを保存するので、showSuccessテンプレートで使われているパスを次のように変更します

4日目で既に全く同じ記述にしてあるので、この節は意味がわかりません。

この時点で試しに投稿してみると、投稿が正しく処理されフォームから削除した値も正しく登録され画像も保存され投稿内容と画像をフロントから閲覧することが出来ます。
うひょお、気持ちわりい。


実は10日目までは1.2のころに作成していたりするので1.4の作りと違いがありますが気にしない。
ていうか、これ書いたころはJobeetJobPeerなんて影も形もなかったはずなんだが…?


PR


2010/10/22 23:33 | Comments(0) | TrackBack() | PHP
システムアーキテクト試験を受けてきた

平成22年度秋期情報処理技術者試験、システムアーキテクトを受けてきました。

会場は渋谷でした。
渋谷といえばヤングの街ですよね。
失礼な話ですが、秋葉系(私も含む)の方々には、
渋谷の領域に踏み入る事は不可能だと思います。
我々の立場も考えてもらいたい。
もちろん全員とは言いませんが、
渋谷はさすがに勘弁して欲しいという人が多いのでは無いでしょうか?
これ以上の批判要望は試験の中止に繋がりそうなので、
次回の参考にでもしておいてくださいな。


例によって時計を忘れ、会場には時計がありませんでした。
時計くらい置いてくれればいいのに。
幸い前席の人が置き時計だったのでそれを見て時間確認を行うことが出来ました。

さて、今回使用した教科書は 情報処理教科書システムアーキテクト および 専門知識+午後問題の重点対策 の2冊です。
これどちらも午後対策なんですよね。
前者も名前のわりに第一章から午後問題ですし。

何を言いたいかというと午前2がやべえ。
残りふたつくらいまではいけたが、そのあと勘で書いたような問題が半分はあったのではないでしょうか。

で、早々と解答が出てるのですが驚いたことに18/25で合格でした。
http://www.jitec.ipa.go.jp/1_04hanni_sukiru/mondai_kaitou_2010h22.html
めでたし。

午後1は問3、問4を選択。
というか問1問2の密度が高ぎて選択が脳に拒否されました。
問3はデータベース関連ですが比較的簡単で、問4は問題を読む力というより単に知ってるか否かという問題が多い印象でこちらも基本的には難しくないと思います。
設問3だけはまったくわかりませんでしたが、まあおそらく合格点は行っているはず。

午後2で見事に死亡。
問1を選択しましたが要件定義に時間がかかりすぎ、設問アを書き上げた段階でなんと80分経過。
残り時間でまともな論旨展開とか書けるわけがなく見直す時間もあるわけもなく問題用紙に書き写す時間もなく、字は汚いわ物凄い思いつきの行き当たりばったり展開になるわ、字数も問イは800字に未達というアウトな状態でした。
問アと問イを見比べるとこれ書いたの本当に同一人物なのか?というかんじでした。

残念ながら、まともに勉強した資格試験としては初めて落ちるという経験になりそうです。


午前2
 イイイウイ
 アウエエア
 エウエエエ
 エウイウウ
 アアウアウ


午後1

問3
設問1:固定機器の設置場所を移動したが、固定資産テーブルを変更していない場合
設問2
 (1)複数の機器の一部が見つからなかった場合、レコード自体が削除されてしまう
 (2)・照合内訳数:現物照合に成功したときに現在の照合内訳数にプラス1される
   ・最新現物照合実施日:資産テーブルの照合内訳数と内訳数が一致したときに現在日に更新される
設問3
 a,f:移動レコードの移動場所コード
 b,c,e:内訳テーブルの設置場所コード
 d:999999
設問4
 (1)機器が遠隔地に設置してあり、バーコードをスキャンできない場合は照合業務ができない
 (2)遠隔地の資産全てをリストアップして貰い、手動で照合業務を行う

問4
設問1
 (1)・対象のディスプレイ端末の指定
   ・複数の割り込みの優先順位
 (2)再生時刻
設問2
 (1)・無線LANの有効範囲
   ・端末集中時の帯域
 (2)サーバと現在時刻を同期する機能
 (3)周囲の明るさに合わせて光度を調整する機能
設問3
 (1)複数のデータ伝送経路を設定する
 (2)ネットワークの幅輳によるスループットの低下が起こらない
設問4
 (1)タッチパネル
 (2)端末の記憶デバイスの容量が少なくてすむ


輻輳は漢字間違えた。



2010/10/18 22:29 | Comments(0) | TrackBack() | 資格
買ったものリスト 2010/10/17

明日システムアーキテクトなので繰り上げ。

いや、勉強せずにこんなことしてる場合じゃないんだが。


らき☆すた8 美水 かがみ
☆☆☆☆

あれ?
前巻は卒業したと思ったら夢オチだった、って話だった気がするんだが普通に卒業してるし知らないキャラがいきなりいっぱい出てるぞ?なんだこれ?
と思ったら前巻を読んだつもりが6巻だった。
7巻を完全にスルーしていたらしい。
なんてこった。
改蔵はまだあくまで愛蔵版で、通常のコミックは全部持っていたので抜けててもそこまで気にはならないのですが、新刊を抜かしてるとかありえなさすぎる。

アニメが終わり下火になったかと思いきや未だに影響が続いていたりするだけあって面白さは安定していますが、なんか時折みゆきが作画崩壊してるのが気になった。

あと後半の宣伝とかよくわからないらきすた以外の連中はあまり一緒にしてほしくないのですよ。


侵略!イカ娘 7 安部 真弘
☆☆☆☆

あれーおかしいなあ。
間違っても人気が出るような作品ではないはずなのだが。

ということでアニメの第1話がニコニコ公式に上がっていたので見てみたのだが、イカ娘の特徴を見事に表現していた良作でした。
すなわち、
Q.この漫画おもしろい?
A.イカ娘がかわいい

ただ主題歌がひでえ。


数学女子1 安田 まさえ
☆☆☆

ミルカさんみたいなのかと思いきや見事に騙された。
全然数学してないじゃないか。

場所が数学科という他に例のない場所だというだけで、それ以外は非常に良くある日常4コマでした。
数学科という特殊性が女が少ない、という一点に矮小化してしまっているのがどうにもこうにも。
あとせっかくなのでもうちょっと男共に頑張ってほしいものだ。


SIMPLE DSシリーズ Vol.47 THE推理 新章2009 D3PUBLISHER

私の携帯ゲームの主戦場は通勤電車なのですが、そこは資格勉強の舞台でもあるので両者は常に私の時間を取り合っています。
最近はずっとSAの勉強でしたが、終わればしばらくは遊ぼうということで今までプレイしたことのないポケモンでも買ってみようと思ったのですが、店頭で見かけてしまったので。
たしかPS1だか2だかで出てた同じシリーズがそこそこ楽しかったんだよね。


毛糸のカービィ

このPVを見て何も感じないようであればゲーマー失格。
http://www.youtube.com/watch?v=rQwbaVW4MaQ
というわけで迷わず購入。

カービィかわいすぎだろ。
毛糸と言ってますが明らかに毛糸じゃないんですが、何故か毛糸っぽく見えるリアリティがすごいです。
あと音楽が異常にいい。

現在火のステージ。
今のところ難易度が低すぎてちょっと微妙ではあるが、任天堂のことだからきっと後半は難しいのが出てくるに違いない。
 



2010/10/16 23:14 | Comments(0) | TrackBack() | 買ったもの
今週の実績 2010/10/17
2010/10/14の実績

Alan Wake

ダーリン キラー 50
自らの想像力を制した

光を目指す者 25
銃を撃つことなく、灯台へ到達した

ご利用階数は? 5
エレベーターに乗った

2010/10/13の実績

Dead Rising 2

ジャスティス 20
オーバータイムをクリアした。TKよ報いを受けよ...

無実の証明 20
THE FACTS をクリアした。これで終わり?

2010/10/11の実績

Dead Rising 2

コンボカードコレクター 20
コンボカードを25枚集めた。コンプリートまであと何枚?

略奪者 20
サイコから手に入る全てのコンボカードを集めた。君のほうがサイコなんじゃないか?

エクセキューショナー 20
10人のサイコを倒した。これでちっとはましな世の中になるかな。

初心者卒業 20
Lv. 25になった。MAXまで半分だ!

グッドファーザー 20
Katey にギフトをあげた。その程度じゃ子どものご機嫌はとれないよ。

2010/10/10の実績

智代アフター

免許皆伝 60
全てのJOBスキルを覚えました

Red Dead Redemption

きちんと身支度! 10
優雅なスーツを手に入れる。


2010/10/16 23:11 | Comments(0) | TrackBack() | 実績
ZF1.10 Zend_Cache
Zend_Cacheとは。

http://framework.zend.com/manual/ja/zend.cache.introduction.html
> Zend_Cache は、任意のデータをキャッシュするための一般的な手法を提供します。

なんだそれは。
ドキュメントの説明は長々と書いてあって丁寧は丁寧なのですが、長すぎて読むのがしんどいです。
簡単に言うとSmartyキャッシュで、要はob_start()、ob_end_clean()、file_put_contents()、file_get_contents()あたりを纏めてパッケージングしたようなものとなります。

とりあえず簡単な例を作ってみます。
ちなみにリファレンスでは最初にZend_Cache::start()Zend_Cache::end()が紹介されていますが不要なので忘れましょう。

zend_cache1.php
<?php
	//Zend_Cache
		require_once('Zend/Cache.php');
	
	//フロントエンドはCore(文字列のみ)を使用
		$zf_cache_frontend = 'Core';
	//フロントエンドオプション
		$zf_cache_frontend_option = array(
			//キャッシュの有効期限
			 'lifetime' => 30
			//シリアライズする
			,'automatic_serialization' => true
		);
	
	//バックエンドはFileを使用
		$zf_cache_backend = 'File';
	//バックエンドオプション
		$zf_cache_backend_option = array(
			//キャッシュを保存するディレクトリ
			'cache_dir' => './tmp/'
		);
	
	//インスタンス
		$zf_cache = Zend_Cache::factory($zf_cache_frontend, $zf_cache_backend, $zf_cache_frontend_option, $zf_cache_backend_option);
	
	//キャッシュを取得する
		$cache = $zf_cache->load('hoge');
		//キャッシュが取得できなければ
		if(!$cache){
			//キャッシュする内容を取得	本来はなんか重い処理
				$cache = 'abcde';
			//キャッシュに保存
				$zf_cache->save($cache, 'hoge');
		}
	
	//表示
		print($cache);

Zend_Cache::factory()でインスタンスを作って、save()で保存、load()で取得するというそれだけの話です。
今回は'hoge'だけですが、ここに一意のIDを指定することで、複数の内容を保存することもできます。

バックエンドはそのまま、保存先に何を使用するかということです。
今回は'./tmp'フォルダにファイルとして保存しています。

フロントエンドは何を保存するか、という意味になります。
Coreは最も単純なフロントエンドで、静的文字列を保存します。

フロントエンドオプションのautomatic_serializationはデフォルトではfalseで、その状態だと本当にただのテキストで保存されます。
さすがに文字列しか保存できないといくら何でも役に立たないのでtrueにしておきましょう。
serialize()できるものならなんでも保存できるようになります。


以上でキャッシュを利用できるようになりました。
最初に実行した際に、キャッシュする内容が取得されて保存されます。
その後30秒間は何度読み込んでも保存したキャッシュが読み込まれるため、具体的なロジックは実行されません。
有効期限が過ぎると、それまでのキャッシュは無かったものとなり、再びキャッシュする内容が取得されて保存されることになります。

今回は取得する部分がただの文字列だったのでまったくなんのありがたみもありませんでしたが、これが一回10秒かかるDBアクセスだったりしたらどうなるか。
かわりにsleep()を仕込んでみたりすると、どれだけ快適になるかがわかると思います。


さて、デフォルトだとフロントエンドオプションのautomatic_cleaning_factorによって10回に1回ガベージコレクタが起動するようになっているように読めるのですが、実際には行われません。
キャッシュファイルはいつまでも残り続けます。
セッションと違いファイル名は変わらないのでファイルが際限なく増えたりする心配はないのですが、削除を行うメソッドも用意されています。
	//特定のキャッシュを削除
	$zf_cache->remove('hoge');
	//有効期限切れのキャッシュを削除
	$zf_cache->clean(Zend_Cache::CLEANING_MODE_OLD);
	//全キャッシュを削除
	$zf_cache->clean(Zend_Cache::CLEANING_MODE_ALL);

ていうか、フロントエンドでガベージコレクタって一体何するんだ?
バックエンドじゃないのか?


2010/10/15 23:44 | Comments(0) | TrackBack() | PHP
コメントSPAM投稿システム見つけた
最近一日1、2通ですがコメントスパムが発生するようになったので、NGワード設定を導入しました。
余談ですがここのNGワードって文字判定が厳格すぎてかえって役に立たないんですよね。
"sakura.ne.jp"をNG設定して"sakura%2ene%2ejp"が通るってどうなのよ。

さて、本ブログの訪問者はリファラを取得できる範囲では9割方GoogleやYahoo等検索エンジンからの訪問です。
"jquery アップロード プレビュー"とか"cakephp paginator"などといった技術系のワードがほとんどです。
たまに"こえでおしごと パスワード"とかもいるけどな。買えよ。

ですので検索エンジン以外からの訪問は目立ちます。
そんだけリンク貼られてる数が少ないってことですがね(´・ω・`)

で、先日なんとなく訪問履歴を眺めていたところ、まったく見覚えのないアドレスを発見。
http://38.110.146.181/auto_comment/comment_log.php?user_id=53&pY=2010&pM=10&pD=12&fY=2010&fM=10&fD=12&c_url=0&search=1&p=5

URLからして胡散臭すぎる。
ちょっと覗いてみる。

20101013-spam1.png

いやあ、なんだこれ。

20101013-spam2.png

どう見てもコメントスパム投稿システムです。
本当にありがとうございました。

20101013-spam3.png

認可制御どころかBASIC認証すらかけずに担当者名明記とか漢らしいにも程があるわ。

20101013-spam4.png

はい、このサイトからのSPAM投稿だということが確定しました。
こっち側のログは削除してしまったので残念ながら照合は出来ませんが。


※認証制御を行っていないので、サイトを覗いても不正アクセスにはあたりません。


2010/10/13 21:45 | Comments(0) | TrackBack() | セキュリティ
ZF1.10 :file_get_contentsでZend_Http_Cookie
前回Zend_Http_Cookieでcookieを簡単に取得しましたが、file_get_contents()で実行することも可能です。

zend_http5.php
<?php
	
	$zend_http1='http://localhost/zend_http1.php';
	$zend_http2='http://localhost/zend_http2.php';

	//取得
		$file = file_get_contents($zend_http1);
	
	//HTTPレスポンスヘッダは$http_response_headerに入ってくる
		foreach($http_response_header as $key=>$val){
			//cookieを取得
			if(strpos($val, 'Set-Cookie:')!==false){
				$cookie_val = str_replace('Set-Cookie:', '', $val);;
				break;
			}
		}
	
	//ストリームコンテキスト作成
		$opts = array(
			'http'=>array(
				'method'=>'POST',
				'header'=>'Cookie:'.$cookie_val."\r\n"
			)
		);
		$context = stream_context_create($opts);

	//ストリームコンテキストを使用してfile_get_contents
		$res = file_get_contents($zend_http2, false, $context);

さほど難しくないといえばそのとおりなのですが、$http_response_headerとかstream_context_create()とかfile_get_contents()の第三引数とか、普通は使わないような関数を使わないといけないので少々面倒です。
あとcookieが無かった場合とか何も考えてない作りなのでそこらへんもどうにかする必要があります。


Zend_Http_Cookieまったく関係ないな。

 



2010/10/11 21:21 | Comments(0) | TrackBack() | PHP
買ったものリスト 2010/10/10



なんか近所のマクドナルドで3セット1000円で売ってた。
たまにジャンキーなものが食べたくなるんだが結局フライドポテトひとつで気持ち悪くなった。


僕たちは監視されている 里田 和登
☆☆☆

『このライトノベルがすごい大賞』金賞受賞作、ということであまり期待せずに読んだ。
最初の数十頁がやたら解説的で、また設定倒れかよと思ったがその後の展開はそれなりに、期待していたよりはよかった。
ただ、根本的そこまで大した秘密じゃないような気がするんだが気のせいか。
あと最後が彼女以外の周囲にとっては結局何の解決にもなってないというのはどうなんだ。

それにしても警察は無能で愚鈍だという偏見はいつまで続くのでしょうかね。
あの設定だったら普通は周知させるレベルの内容だろ。

てか、タイトルは「監視させている」の間違いだよな。


テルマエロマエ2 ヤマザキマリ
☆☆☆☆

見事勝ち取った連載第一話であんな話をやっちゃう度胸は評価する。
ネタがあまりにも限定されすぎているせいでやはりマンネリ感はあるものの、話自体は十分に面白いです。
一巻は基本的にギャグだったけど、二巻は多少作者の思想が入ってきてる感があるので、もしかしたらそこが合わない人もいるかもしれません。


かってに改蔵5 少年サンデーコミックススペシャル 久米田 康治
かってに改蔵7 少年サンデーコミックススペシャル 久米田 康治
☆☆☆☆☆

あれ?6巻が無いぞ?
いつのまにか買い逃していたらしい。


レッド・デッド・リデンプション

PS3版は除草されているという噂のRDR。
本作を一言で表すと、西部劇GTA。
…そういえばGTAってやったこと無かったんだ。
そこらを歩いていると一般人が狼に襲われていたり、山賊に襲われていたり、それを助けてみたり、一緒に撃ち殺してみたり、身ぐるみ剥いでみたり、日本にはあまりないなんでもできるRPGの系譜です。

グラフィックはただただとにかく圧倒的です。
ただ舞台が西部劇の荒野なので、オブリの山頂から帝都を遠くに見下ろしてみるとか、Fallout3の延々広がる瓦礫と廃墟とか、そういった目を見張る光景というものはありません。
あと視点のエイムがなんかちょっと肌に合わないんだが何故なんだろう。



2010/10/10 20:56 | Comments(0) | TrackBack() | 買ったもの
今週の実績 2010/10/10
2010/10/07の実績

Red Dead Redemption

政府の犬 10
「アメリカ横断記」をクリアする。

Dead Rising 2

自警団 20
5人のサイコを倒した。Fortune Cityの自警団員だ!

2010/10/06の実績

Dead Rising 2

バーテンダー 20
ミックスジュースを作った。ミックスジュースは旨い!

2010/10/03の実績

Dead Rising 2

ちょい悪オヤジ 20
10種類のコスチュームを試した。まあまあイケてるんじゃない?


2010/10/10 20:53 | Comments(0) | TrackBack() | 実績
XAMPP1.7.3 設定ファイルに定義されている管理ユーザ(controluser)での接続に失敗しました
http://localhost/phpmyadmin/
というURLでXAMPPにデフォルトで入っているphpMyAdminを利用できます。

それはいいのですがアクセスすると
設定ファイルに定義されている管理ユーザ(controluser)での接続に失敗しました

という謎エラーが。

ついでに
Your PHP parameter session.gc_maxlifetime is lower that cookie validity configured in phpMyAdmin, because of this, your login will expire sooner than configured in phpMyAdmin.

ってのも出てたので一緒にチェックしてみます。


まずDocumentRootにphpmyadminなんてディレクトリはありませんが、これは単純にxampp/apache/conf/extra/httpd-xampp.confでAliasが設定されています。
xampp/phpMyAdmin/あたりになっているはずですが、そこにphpMyAdminの本体が転がっています。
phpMyAdmin自体はMVC?何それ食い物?的な書かれ方をしてるので読むのは相当難儀です。

まず文言の定義はlang/japanese-utf-8.inc.phpです。
    $strControluserFailed = '設定ファイルに定義されている管理ユーザ(controluser)での接続に失敗しました';

で、次の$strControluserFailedはlibraries/dbi/mysqli.dbi.lib.phpです。
$GLOBALS…

PMA_DBI_connect()は都合二回呼ばれており、一回目の接続では失敗してtrigger_error()されています。
二回目の接続にはconfig.inc.phpで設定されている$cfg['Servers'][$i]['user']$cfg['Servers'][$i]['password']が使用されています。
ではこの一回目の接続にはどのパラメータが使用されているかというと、同じファイルの$cfg['Servers'][$i]['controluser']$cfg['Servers'][$i]['controlpass']です。

どゆこと?

名前からして$cfg['Servers'][$i]['user']には一般ユーザ、$cfg['Servers'][$i]['controluser']には管理者権限のユーザを割り当てるのかなとも思いますが、なんのためにこんな作りになっているのかはよくわかりませんでした。
$cfg['Servers'][$i]['controluser']をログインできる値にする、もしくは設定を削除することでエラーは発生しなくなります。


後者のエラーは、session.gc_maxlifetimeがcookieの有効期限より短いから意味がないぞ、というエラーです。
phpMyAdminは$cfg['LoginCookieValidity']でcookieの有効期限を設定します。
これが短すぎるとちょっと席を外しただけですぐログアウトされてしまい、不便になります。

で、それとは別にPHPではsession.gc_maxlifetimeでサーバ側セッションファイルの有効期限が設定されています。
この時間が過ぎたセッションファイルは廃棄処分されてしまいます。

結果として、session.gc_maxlifetime以上$cfg['LoginCookieValidity']以下の期間にアクセスされると、cookieは有効期限内だからブラウザはcookie値をちゃんと送ってくるのに、サーバ側のセッションファイルは削除されてしまっているので、セッションが継続できないよ、という状態になります。
実際のところは単にセッション期限切れになるだけなので特に問題はありません。
物凄い暇な人がcookieを解析して、有効期限が60分となっているのに50分後にアクセスしたらセッション期限切れになった!これはおかしい!とか言い出したりすることが万一あったりするかもしれないレベルの話です。

エラーが気持ち悪いならconfig.inc.phpの隅っこに
ini_set("session.gc_maxlifetime", $cfg['LoginCookieValidity']);
とか書いておけばいいです。


2010/10/08 23:37 | Comments(0) | TrackBack() | PHP

<<前のページ | HOME | 次のページ>>
忍者ブログ[PR]