symfony PHPフレームワークpart2
>>220 $this->thread = Doctrine_Core::getTable('thread') ->createQuery('t') ->where('t.id',$request->getParameter('id')) ->leftJoin('t.User u') ->execute(); $this->thread = Doctrine_Core::getTable('thread') ->createQuery('t') ->where('t.id = ?',$request->getParameter('id')) ->leftJoin('t.User u') ->fetchOne(); に変えたらどう? fetchOne()に変えて、$thread['User']['name'] で取得できました! SQLも新しく発行されていないようです。 ただ、$thread->getId() の構文が使えなくて $thread['id'] に全部書き換えないといけませんけど>< サンプルに合わせて言い方変えちゃいましたけど、 実際はfetchArray()で取得して、foreach()でループさせました。 とりあえずうまく行ったようです。 $form->isValid()に失敗したとき、失敗の内容はどうやって取得できますか? 具体的には、CSRFチェックに引っかかったとき、自動的にhoge/newにリダイレクトさせたいんです。 >>224 sfErrorSchemaにでも、入ってるんじゃないの? $form->getErrorSchema()だったかな? 特定のユーザーを、強制ログアウトさせるにはどうすればいいですか? >>226 myUserの初期化メソッドで通常の処理の後にIDみて強制ログアウトする処理を足す。 >>227 すいません、そうゆう意味じゃないです。 たとえば、管理者が荒らし行為真っ最中のユーザーを見つけたら、 そいつのセッションやらクレデンシャルやらをクリアしてログアウトさせることをイメージしてました。 セッションにユーザーIDを入れておき、 全セッションファイルをトラバースして、 「id|i:(\d)+:123;」みたいにマッチしたファイルを削除すればいいかな? symfony関係なくなっちゃうけど。。。 Doctrineで書いたコードの、selectがうまく反映されません。 count()をやめて、execute()にして返ってきたDoctrineCorectionをcount()すると正しい件数が取得できます。 でも重いので、SQLのcount()でなんとか処理したいです。 public static function getLoginDays($id) { return LoginTable::getInstance() ->createQuery('l') ->select('DATE_FORMAT(l.created_at,"%Y-%m-%d") as days, count(*) as num') ->where('l.user_id = ?',$id) ->groupBy('DATE_FORMAT(l.created_at,"%Y-%m-%d")') ->orderBy('days') ->count(); } #symfonyが発行したSQL SELECT COUNT(*) AS num_results FROM log l WHERE l.user_id = '1' GROUP BY DATE_FORMAT(l.created_at, "%Y-%m-%d"); 結果、日付の区別無しに、ログの総数が返ります。 恥ずかしいミスした! DoctrineCorectionは、DoctrineCollectionの間違いでした^^; >>228 それならis_active int(1)とかでフラグ項目をDBのユーザーテーブルに持たせておいて、公開側では myUserの初期化で$dbuser->getIsActive()の値を調べて強制ログアウトさせればいいんじゃない? 強制ログアウトさせたいユーザーは、管理者が裏画面からis_activeの値を更新して強制ログアウト側に 落とす。 username password is_active ごめん、途中送信。 username password is_active testuser ****** 1 ⇒ログインできる nguser ****** 0 ⇒ログインできない&強制ログアウト myUserにコンストラクタ定義すると、深い迷路に迷い込めそうな予感。。。 ちょっと語弊がありました。 グループ化された日付が1つだけの場合、グループ化されていないままのレコード総数が返ります。 日付が複数の場合、正しい値が返ります。 分かったら当たり前だけど、myUserのコンストラクタは public function __construct(sfEventDispatcher $dispatcher, sfStorage $storage, $options = array()) { parent::__construct($dispatcher, $storage, $options); } って書かないとダメなのね。__construct()とだけ書いてちょっと泥沼になった。 テンプレート内でvar_dump()すると、指定した変数以外もすんごい量がダンプされるんですけど $thisとかも見に行ってるんですか?? >>236 変数といってもDoctrine_Recordのオブジェクトが入ってる変数だったらものすごい量でて当たり前。 フォームで、ユーザーに改ざんされたくない値を扱う方法で質問です。 formで隠したいパラメータ(from_id)をunsetしておいて、アクションで > $message = new Message(); > $message['from_id'] = $this->getUser()->getAttribute('id'); > $form = new MessageForm($message); とやる方法と、 formでunsetせずに > $values = $this->getUser()->getAttribute($form->getName()); > $values['from_id'] = $this->getUser()->getAttribute('id'); > $form = $this->processForm($form, $values); と上書きする方法の2通りがあると思うのですが、 どちらも安全でしょうか? それとも、他に方法があるんでしょうか? セッションがタイムアウトして、AuthenticatedとCredencialがクリアされたのに、 $this->getUser()->setAttribute()した値が残ってるのですが、 これって普通ですか? >>239 認証とセッションデータをごっちゃにするなよ DoctrineでのInnnerJoinの書き方で苦戦しています(汗 下記のSQL文でコマンドラインでは動いてるんですが、 どのように記述すればよいのでしょうか? SELECT w.target_user_id as user_id, DATE_FORMAT(w.created_at,"%Y-%m-%d") as days,w.type as type,count(*) as num FROM warn w INNER JOIN ( SELECT target_user_id,count(*) AS datas FROM warn GROUP BY target_user_id ) AS SUB USING(target_user_id) GROUP BY user_id,days,type ORDER BY datas DESC ,user_id ASC,days ASC,type ASC; ユーザー情報を持つUserAccountテーブルと、そのIDをカラムに持つBlogテーブルをリレーションさせておくと、 フォームの作成で下記のようなファイルが生成されます。 これが、ユーザー数が多くて、かつuser_idをunset()して使うケースではかなり無駄な気がします。 手作業でsetup()を上書きして、widgetをsfWidgetFormInputText、 validatorをsfValidatorIntegerに変える、という感じに書き換えたいのですが、 スキーマのオプションとかでsfWidgetFormDoctrineChoice()&$this->getRelatedModelName()を 使わないようにはできないんでしょうか? $this->getRelatedModelName()の呼び出しは1回で済むはずなのに無駄なコードだし。。。 ユーザーが1万人になったら、フォームの表示のたびに2万件のレコード引っ張ってくるつもり? abstract class BaseBlogForm extends BaseFormDoctrine { public function setup() { $this->setWidgets(array( 'id' => new sfWidgetFormInputHidden(), 'user_id' => new sfWidgetFormDoctrineChoice(array('model' => $this->getRelatedModelName('UserAccount'), 'add_empty' => false)), )); $this->setValidators(array( 'id' => new sfValidatorChoice(array('choices' => array($this->getObject()->get('id')), 'empty_value' => $this->getObject()->get('id'), 'required' => false)), 'user_id' => new sfValidatorDoctrineChoice(array('model' => $this->getRelatedModelName('UserAccount'))), )); sfWidgetFormDoctrineChoice::getChoices() が呼ばれるのはrender()の時だけ? 大ポカだった。 sfGuardPluginを使わずに、自分でログインページを作ったのですが、 is_secure:true にした場合にログインページにforwardしてくれるのはいいのですが 認証成功後にforwardする前のページにredirectするにはどうすればいいでしょうか? 認証情報はセッションに入ってるものだと思ってました。 認証情報はどこに保存されているんでしょう?? ファイルアップロードで、ファイル名の「'」が「\'」になるんですけど これってSymfonyの問題ですか? PHPも初心者なもんでどうすればいいのか分かりません。。。 問題があるとしたらファイル名に「'」を使ってることかな セッション(認証?)が30分程度で切れてしまいます。 以下の設定だけでは、変更できないんでしょうか? #.htaccess php_value session.gc_maxlifetime 86400 php_value session.gc_probability 1 php_value session.gc_divisor 100 #setting.yml all: user: class: myUser param: timeout: 86400 factories.ymlに書くんだと思う user: class: myUser param: timeout: 86400 こんな感じ sfDoctrineGuardPlugin使ってます。 バックエンドで、is_super_adminなアカウントだけ閲覧を許可していんですけど 以下のsecurity.ymlでうまくいきません。クレデンシャルが違うんでしょうか? index: is_secure: true credentials: admin それと、新規登録時に Notice: Undefined offset: 1 in D:\MyProject\symfony\lib\vendor\symfony\lib\config\sfGeneratorConfigHandler.class.php on line 68 という謎のエラーが出てしまいます。 sfGuardAuthに空のgenerator.ymlを作ると治るという情報があったのですが 治りませんでした。他に解決方法はありませんでしょうか? >>252 credentails: [admin] じゃなくて? sfDoctrineGuardPlugin使ったことないからよくしらんけど 「Notice: Undefined offset: 1」のエラーのほうは、 http://www.symfony-project.org/blog/2008/11/12/call-the-expert-customizing-sfdoctrineguardplugin を参考にしたAPP/congig/generator.ymlの変更をやめて、 中身を全部削除したらうまくいったみたい。 日別のアクセス数を集計しようとしてるのですが、正常にうごきません。 日付の比較がおかしくなっている感じがします。 スキーマはこんな感じです。 AccessLog: tableName: access_log actAs: { Timestampable: ~ } columns: user_id: varchar(50) コードと同等(と思っている)のSQLをMySqlコマンドラインから実行すると、正常にいきます。 SELECT a.id, a.user_id, COUNT(*), DATE(a.created_at) AS date FROM access_log a WHERE (a.user_id = 'admin' AND a.created_at > '2010-11-01 00:00:00' AND a.created_at < '2010-11-29 23:59:59') GROUP BY date ORDER BY a.created_at; 「->andWhere('a.created_at < ?',$end)」の行を抜かすと一応取得はできます。 原因はなんでしょうか? $id = 'admin'; $start = "'2011-11-01 00:00:00'"; $end ="'2011-11-30 23:59:59'"; $this->accesslogs = Doctrine_Query::create() ->select('a.user_id, count(*) as count, DATE(a.created_at) as date') ->from('accesslog as a') ->where('a.user_id = ?',$id) ->andWhere('a.created_at > ?',$start) ->andWhere('a.created_at < ?',$end) ->groupBy('date') ->orderBy('a.created_at') ->execute(); ついでにfixture.ymlも書いておきます。 AccessLog: log1: user_id: admin created_at: '2010-11-13 21:56:54' log2: user_id: admin created_at: '2010-11-13 21:56:54' log3: user_id: admin created_at: '2010-11-14 21:56:54' log4: user_id: admin created_at: '2010-11-14 21:56:54' log5: user_id: admin created_at: '2010-11-15 21:56:54' (たぶん)解決しました。 ->from('accesslog as a') じゃなくて ->from('accesslog a') に変えると期待通りに動きました^^; 夜中3時間悩んだのに、昼に起きて5分で解決しました。 休憩や睡眠って大事ですね。みなさんもがんばってください。 なんで$endの行が無いときにうまくいったかは謎のままですが。。。 sfDoctrineGuardPluginって使ってる人いる?? symfony慣れてないくせして導入してみたんだけど、symfonyとバージョン合ってないのかな? sfGuardRememberMeFilterが機能してない気がする。 settings.ymlで enabled_modules: [default, sfGuardGroup, sfGuardUser, sfGuardPermission, sfGuardAuth, sfGuardForgotPassword] を記述しても、バックエンドに追加されてない。 sfGuardUserは手動でバックエンドに追加できるけど、sfGuardPermissionは足りないファイルがたんまり。ネットで拾ってきてもまともに動かない。 あと、save-fixtureしてリロードすると、パスワードがハッシュされてログインできなくなる。 このあたり、どうにかなりませんか? こうゆう複雑なSQLはDoctrineでできますか? Doctrineは単純なSQLだけで、複雑な合成はPHPでやったほうがいいのかな。 SELECT u.id as u__id, u.username as u__username, s.date as s__date, a.access as a__access, s.sales as s__sales FROM sf_guard_user u LEFT OUTER JOIN (SELECT user_id, DATE(created_at) AS date, SUM(amount) AS sales FROM sales GROUP BY user_id, DATE(created_at)) s ON u.username = s.user_id LEFT OUTER JOIN (SELECT user_id, DATE(created_at) AS date, count(*) AS access FROM access_log GROUP BY user_id, DATE(created_at)) a ON u.username = a.user_id AND s.date = a.date WHERE u.username = 'admin' AND s.date > '2010-11-01 00:00:00' AND s.date < '2010-12-01 00:00:00' ORDER BY s.date; これ、どうゆう意味ですか? > 500 | Internal Server Error | Doctrine_Query_Exception > The root class of the query (alias s) must have at least one field selected. ユーザー毎の売上げを集計したいだけなんだけど。。。 #action.php public function executeSalelist(sfWebRequest $request) { $this->saless = Doctrine_Query::create() ->select('s.user_id as id, p.name, sum(s.amount) as amount') ->from('Sales s') ->leftJoin('s.Profile p') ->groupBy('id') ->execute(); } #schema.yml Sales: tableName: sales actAs: { Timestampable: ~ } columns: user_id: type: integer amount: integer relations: User: class: sfGuardUser foreign: id local: user_id type: many onDelete: cascade foreignType: many foreignAlias: Sales Profile: class: sfGuardUserProfile foreign: user_id local: user_id type: many onDelete: cascade foreignType: many foreignAlias: Sales sfGuardPluginついでに。 > $this->setWidget('user_id', new sfWidgetFormDoctrineChoice(array('model' => $this->getRelatedModelName('User')))); フォームのプルダウンでuser_id=0のアカウントを選択してポストすると、 user_id=1として格納されてしまいます。 なんで〜?? user_idをauto_incrimentにしてない? selectからp.nameをとるととりあえずいける。 Profileがおかしいのかな? Sales: tableName: sales actAs: { Timestampable: ~ } columns: user_id: type: integer amount: integer relations: User: class: sfGuardUser foreign: id local: use_id type: many onDelete: cascade foreignType: many foreignAlias: Sales Profile: class: sfGuardUserProfile foreign: user_id local: user_id type: many onDelete: cascade foreignType: many foreignAlias: Profile sfGuardUserProfile: tableName: sf_guard_user_profile actAs: { Timestampable: ~ } columns: id: integer user_id: type: integer primary: true bank_name: varchar(50) bank_point: varchar(50) bank_type: type: enum values: [ordinary, current] default: ordinary name: varchar(50) bank_number: varchar(50) relations: User: class: sfGuardUser foreign: id local: user_id type: one onDelete: cascade foreignType: one foreignAlias: Profile フォーム難しいですね。。。 スキーマでは user_id(type:integer) にリレーションしてるんだけど、 フォームでは user_name(type:varchar(255)) で入力したい場合はどうすればいいですか? Newのときは下記コードでうまく「ユーザー名入力→ユーザーIDに変換」できるようになったんですが、 Editのとき編集フォームがuser_idのままです。。。 public function configure() { $this->widgetSchema['user_id'] = new sfWidgetFormInputText(); $this->setValidator('user_id', new sfValidatorString(array('max_length' => 128, 'required' => true))); $this->validatorSchema->setPostValidator(new sfValidatorCallback( array( 'callback' => array($this, 'validateUsername'), ), array( 'invalid' => 'アカウント名を正しく入力してください。', ) )); } public function validateUsername(sfValidatorBase $validator, $values) { if (strlen($values['user_id'])) { $user = Doctrine_Core::getTable('User')->findOneByUsername($values['user_id']); if (!$user) { throw new sfValidatorError($validator, 'invalid'); } $values['user_id'] = $user->getId(); } return $values; } } コンストラクタ上書きでできたけど、上記含めてお作法的にこれでいいんかな。。。 このスレにはお世話になってるし、 だれかの役に立つかもしれないから、動いたコンストラクタのコードも一応書いときます。 けんちゃんより(はぁと) public function __construct($defaults = array(), $options = array(), $CSRFSecret = null) { if(isset($defaults['user_id'])) { $user = Doctrine_Core::getTable('User')->find($defaults['user_id']); if($user) { $defaults['user_id'] = $user->getUsername(); } } parent::__construct($defaults, $options, $CSRFSecret); } 他システムへのアクセスがあったときに、タスクを用いてSymfony側にアクセスログを取ろうとしています。 実行すると「There is no open connection」というエラーが出てしまいます。 なにがおかしいんでしょうか? > $databaseManager = new sfDatabaseManager($this->configuration); > $connection = $databaseManager->getDatabase('links')->getConnection(); を追加してみたのですが、 「 Database "links" does not exist.」 というエラーが出てしまいます。これは正しいDB名です。 C:\MyProject\link>php symfony link:access user01 111.111.111.111 #accessTask.class.php <?php class accessTask extends sfBaseTask { public function configure() { $this->namespace = 'link'; $this->name = 'access'; $this->addArgument('username', sfCommandArgument::OPTIONAL); $this->addArgument('ip', sfCommandArgument::OPTIONAL); } public function execute($arguments = array(), $options = array()) { $access = new Accesslog(); $access->setUsername($arguments['username']); $access->setIp($arguments['ip']); $access->save(); $this->log('access from '. $arguments['ip']); } } >>273 ・extends sfDoctrineBaseTaskにする ・executeの冒頭に $configuration = $this->createConfiguration('users', 'cli'); new sfDatabaseManager($this->configuration); と書く。 理屈は知らんがw doctrineならこれで動くんじゃね あ、ごめん。createConfigurationの最初の引数はapp名で。 できた〜! しっかし重いなぁ。。。 まだ連動させてないけど、Doctrineがログ吐くのが悪さしないといいんだけど。 (-quiet指定したら、"-u","-i","-e"オプションが無いとエラーが出たのであとで調べる。) マイグレーションについてなんですけど、 カラムの追加は公式ドキュメントでなんとなく分かりました。 ただ、テーブル(既存テーブルとのリレーション有り)を新たに追加する場合は どうすればよいのでしょうか? Symfonyが吐いたテーブル作成のSQL文をコピペしてprod環境で実行、 モデル等のファイルをアップロード、 キャッシュクリア というような手作業になるのでしょうか? ビルドはいらないですよね? まだあまりsymfonyを理解していないのですが、 symfony doctrine:build --all --and-load すると、まずデータベースがdropされますよね? 複数プロジェクトで共通のユーザー情報マスタDBを使うつもりでいるので 1つのプロジェクトを更新するたびにユーザー情報がdropされると困るのですが、 どのように構成すればよいでしょうか? #仮にユーザー情報マスタDBのスキーマだけを持ったプロジェクトを作って、 #ほかのプロジェクトはユーザー情報DBをスキーマに記述しない構成も考えたのですが、 #モデル等が作られないのでリレーション等が働かない気がしています。 >>278 つttp://symfony-doc-ja.googlecode.com/svn/branches/1.2/html/book/09-Links-and-the-Routing-System.html#url.rewriting 初心者のくせにサーバでsymfony運用始めちゃったんですけど、 新しいテーブル追加するにはどうすればいいですか?? サーバでbuild-allするとdropしちゃいますよね? 一旦save-fixtureすることも考えたんですが sfGuardPluginなんで、パスワードが変わっちゃいますよね?;; >>281 build-allじゃなくて必要なタスクだけ実行すればいいんじゃないの? やり方は色々あると思うけど 例えば新しいテーブルはSQLで作って symfony --xml build-schema symfony build --model symfony build --forms symfony cc とか。 遅くなりました。 ちょっとそれでやってみることにします。 駄目フレームワークの典型symfony だから誰も使わないし流行らない。 2.0で大きく変わるんだから、自身で悪い点は分かってるんだろうよ。 フレームワークは所詮道具なんで、どれを使ってもいくつも使ってもいいと思う。 ケースバイケース、適材適所で。 1個覚えれば他に移行するのも楽だよ。 俺はsymfonyともPHPとも心中する気は無いけど、 それでも、今現在の最善策だと思って使ってく。 5年も経てば、CakeでもZendでもない新しいフレームワークにみんな移ってると思うよ。 そんな気持ち。 多言語サポートしたいんだけど、 URLにdomain.com/jp/とかdomain.com/en/とかアドレスを分けたくない場合は どうすればいいですか? サーチエンジンからすると、分けてたほうがいいのかな?? なぜ英語はen(english)なのに日本語はjpですか? その流れではjaなのではないのですか? symfony使いこなせる人はスキル高いと思うよ symfonyから学ぶことはたくさんある symfony2.0への前準備として1.4勉強するといいよ 2.0のチュートリアル等の日本語化は誰がやるか決まってるの? >>289 symfonyユーザー会で分担してやるんじゃね?やる気があるならユーザー会へ立候補どぞー チュートリアルやってみたけどSubversion導入するところでめんどくさくなって挫折した。 >>284 まぁお前が無知だから使われてること知らないだけだけどな Doctrineについて質問だけど、join系にサブクエリって入れれる? どうもやり方が見つけられない・・・。 >>286 JavaScript で対応。jQuery プラグインなら jquery.localize.js とか MS 謹製の jQuery Globalization Plugin が見つかるね。 >>289 主だった人は執筆やら勉強の会の準備に忙しいから、 >>295 のつづき。すぐに翻訳はそろわないと思うよ。ただ、コードサンプルはわかりやすいから、英語が読めなくても内容をかなりつかめるんじゃないかな。 >>284 ガラパゴス基準で考えてほしくないな。github のウォッチングランキングに入っているのでじゅうぶん人気はあると思うよ。 https://github.com/popular/watched VPSも安くなったし、もう無理してPHP使う必要無い時代になったな。 >>298 パフォーマンスの問題というよりも、PHPでは体験できない新しい勉強をしたいということではないだろうか。世界の状況はどんどん変わってゆくのだから、>>285 と同じことだけど特定のフレームワークや言語に囚われる必然性はないよ。 VPSだからPHP要らない? お前は何を言っているんだw >>298 の言いたいことはよく分かる。 PHPなんて糞だと思いつつも、格安鯖にはPHPとPerlしかないし… と、他の言語に興味がありながら、なかなか手を出せなかった人にとってはいい転換期だと思う。 インフラの心配なく、自動スケールするGoogle App Engineとかもあるしね。 JavaとかPythonもやってみると意外と面白い。 確かに>>298 が何を言おうとしているのかその意図がわからんな VPSにしてWAS入れてとかの話なのか? まあここはsymfonyスレだが・・ ルート権限あるなら、mod_perlでもPassengerでも自由にインストール出来るから名。 これまでのレンタルサーバの共用プランだと、mod_phpかPerl/CGIしか選択肢がなかった。 そういう事だろう。 Perlも最低限SSHでシェルにアクセスできんと local::libでCPANモジュールぶっこみができないのがつらいところ Doctrineで新しくレコード追加したわけだが、 追加したレコードのIDが取得できん。 $xxxx = new AAAAA(); : (各種設定setXXXX()) $xxxx->save(); $xxxx->getId();←常に0が返ってくる。 別のテーブルでも試してみて、原因は複合主キーだとは わかっているんだが、どうやってInsertしたテーブルの キーを取得すればよいのか誰か教えて欲しい。 なぜ、Symfonyのスレが盛り上がらないのか? その答えは単純明快である。 Symfonyの素晴らしさを理解できる優秀なエンジニアは この世に一握りしかいないからである。 世間の評価など気にせずに、優秀なエンジニア達は 迷わずSymfonyを使えばいい。 Symfonyの素晴らしさを理解できる優秀なエンジニアだけで Synfonyを独占すればいい。 APIの結果をページングしたい場合、 sfPagerを継承して独自のページャを作る、っていう方法であってますか? 手嶋屋のおかげでsymfonyの評価がた落ちだよ。 最近、諸事情でしぶしぶCakePHPを触ることになったのだが、 やっぱCakeのがシンプルで融通聞くと思い始めた。 symfony2は原型とどめてないしビジネス的に見てもCakeかなあ・・・ あとやっぱりschema.ymlとmigration両方書くのもめんどい。 symfony1.0とPHP5.3って相性良くないですか? なんかデバッグしにくい妙なエラーが・・ 無理に5.3にせずに5.2で行く方が無難かな 自分の書いたクラスでメソッドの修飾子をpublic publicと二回書いてて 5.2まではそれでも動いていたのが、5.3では動かなくなっていて しかもそれがバッドノウハウ的にエラー表示を消してるところで起きていたので分からなかっただけでした・・orz read.cgi ver 07.5.5 2024/06/08 Walang Kapalit ★ | Donguri System Team 5ちゃんねる