元スレ[PHPフレームワーク]Laravel
php覧 / PC版 /みんなの評価 :
351 = :
>>349
モデルをテーブルには未セーブ、つまりIDがない状態でセッションに入れるとどう?
IDがないとhasOneはもちろん無理だけどbelongsToは可能
それがセッション通過後だとnullになっちゃう
>>351
名前か、確かにリレーションは複合語ばっかりだからあるかも
353 = :
>>351
未保存でそのままセッションに入れて別ページで取ってみたけど、問題なくbelongsTo先は取れたよ。
アンダーバー有りは試してないからそれかもね。
354 = :
モデル名に複合語つかってると、前者と後者のモデルの区切りを識別できないのかね?
なんかおかしな挙動になったのは覚えてる
355 = :
>>353
検証ありがとう。でも名前は関係無いようだ。そしてSessionも直接は無関係っぽい。
やっとちょっと整理できた気がするのでまとめます。長文容赦。
例としてUserとPhoneの関係。普通にPhone::userがbelongsTo('User')とします。
[ケース1]
$phone = new Phone();
$phone->user_id = 1;
$user = $phone->user;
return $user;
[ケース2]
$phone = new Phone();
$dummy = $phone->user;
$phone->user_id = 1;
$user = $phone->user;
return $user;
ケース1との違いは2行目が増えているだけ。もちろん$dummyにはnullが入ります。
で、結果はケース1だと普通に$userの内容が出力され、ケース2はnullが返ります。
つまり一度でも空っぽのリレーションを参照してしまうと、その後はキーの値を代入してもリレーションが作られない。
もちろん代入じゃなくてfillでも同じです。
fillや代入じゃなくてちゃんとassociateすれば大丈夫。
普通はfillの後saveして遷移するから、テーブルからの再取得時にリレーションができてめでたしとなるわけだけど、
セッションで引き継いでしまうとキーの代入やfillでは永久にリレーションができなくなってしまう。
結構イヤな挙動だと思いませんか?
357 = :
Laravelは(というかORMのEloquentは)
$phone->user とか未定義のプロパティにアクセスした際に走る __get, __set をオーバーロードして
Laravelのあの魔化不思議な動きを実装してる
具体的には、$phone->user とした時点で以下の動作が走る
プロパティ user の存在をチェック (PHPの動き)
- userプロパティが存在したら そのまま userプロパティの内容を戻す これはPHPの言語仕様でオーバーロードとかは一切できない
- userプロパティが存在しなかったら __get マジックメソッドが走る
で マジックメソッドはLaravel側でオーバーロードされていて 以下の処理をしている
- リレーションの有無をチェック
- リレーションが存在したら user_id の存在を確認する
- user_id も存在しなかったら userプロパティに null をセットした上で、そのnull を戻す
- user_id が存在して値が入っていたら select * from user where user_id = 1 が走った上で
userプロパティには userオブジェクトが格納し、その上でuserオブジェクトを戻す
キモは すでに存在するいプロパティにアクセスした時に効かせられるフックはPHPに存在しない って話。
ケース2では、すでに一度 $dummy = $phone->user; でアクセスし、この時点でuserプロパティが 内容null で作られてしまってる。
user_id をいじったら user の内容も連動して変わるってのは錯覚だって話なのよね。
初回だけマジックメソッドの効果でそう動いてるように見えるから混乱する。
user, user_id が共にセットされた後、つまりプロパティが作られた後は user_id を変えただけでは userの内容は自動的には変わらない。
さっき言ったように、すでに存在するプロパティにアクセスした時に効かせられるフックはPHPに存在しないから。
だから
$user = User::find(2);
$phone->user = $user;
とした後に、 $phone->user_id = 1; としても $phone->user の内容は自動的には変わらないし変えることも出来ない。
ただ、saveとか一旦すると user_id の値がDBに保存されて、次 またuser を再取得するときは user_id 1 のオブジェクトが戻されるため
いかにも自動的に変わったように錯覚してしまう。
359 = :
>>357
丁寧にありがとう。
・null値も「存在するプロパティ」の扱いになる
・存在確認のために参照するだけでnull値が入る
というあたりがなんともモヤモヤするところではありますな。言語仕様的に。
「セッションにモデルを持って複数フォームで順次更新、最後にテーブルへ書き込み」
という流れは割と普通にやりたくなるところだと思うけど、
それはあんまりLaravelish wayではないということなのでしょう。
__wakeupをオーバーライドしてリレーションを取得させるようにすれば
テーブルへの書き込み->読み出しを経た場合と挙動が近くなると思うんだけど、
そう簡単なもんでもないのかな。
360 = :
というか未定義プロパティにアクセスした時にnull値をセットしてるのがマジックメソッドの中でなら、
それをやめてくれるだけでいいのか。
そうすれば少なくとも初回のキー値代入で常にリレーションはできることになる。
361 = :
毎回取得してたら遅くなるから、一旦内部で保持しちゃうのかな
とりあえず、後から
$phone->user_id = 1;
としたら、その直後に
$phone->load('user');
ってすればいいなら許容範囲な仕様だと思うけどね
362 = :
>>361
わかってしまえば対処は楽なんですけどね。
新規作成はnew Model(Input::all())で問題ないから、
更新もfill(Input::all())で済ませたくなる。
で、その前にリレーションを一度も参照してなければなまじ動いてしまうもんだから
すっかり混乱してしまった次第。
こんなんで丸一日とか潰れちゃうんだよな・・・orz
363 = :
公式ドキュメントのdynamic properties
364 = :
のところに、この説明があってもいいかもしれない
365 = :
modelとcontrollerの書き方について教えていただけませんか。
特定の条件を入力して検索機能を作る場合、zendだとmodelにwhere文からfetchまでを書いてreturnすると思うのですが、
larabelではコントローラーで条件を書くのでしょうか?
↓こんな感じであってますか?
class Controroller extends BaseController {
public function anyIndex()
{
$query = new Model;
$query = query->leftJoin('sample', 'sample', '=', 'sample');
$query = query->where('sample', '=', 'sample');
$query->get();
}
}
class Model extends Eloquent {
protected $table = 'sample';
}
366 = :
60まで
現役通せ
プログラマ
367 = :
まちがえた。ごめん。
368 = :
>>365
別に唯一正しいやり方はないし簡単なクエリーならControllerで組み立てても問題ない
Eloquentの使い方についてはドキュメント読んだほうがいい
http://readouble.com/laravel/5/0/dev/ja/eloquent.html
複雑なクエリーをテストしたかったり他のアクションで再利用したかったり
コードを整理したりしたいならクエリースコープ使えばいいんじゃない
http://readouble.com/laravel/5/0/dev/ja/eloquent.html#query-scopes
class SearchController extends BaseController {
public function getIndex()
{
$condition1 = Input::get('hoge');
$condition2 = Input::get('fuga');
//入力値チェックなどしてから
$models = Model::search($condition1, $condition2)->get();
}
}
class Model extends Eloquent {
public function scopeSearch($query, $condition1, $condition2)
{
return $query->whereHoge($condition1)->whereFuga($condtion2);
}
}
ORMはオブジェクトありきで裏のRDBの存在をあまり意識しないで済むようにするための道具
SQLに近いコードが書きたいならクエリービルダーのほうが向いてるかもね
http://laravel.com/docs/5.0/queries
369 = :
>>357
これめっちゃハマりどころじゃね?
普通きづかんだろ
370 = :
>>369
リレーションの仕様を理解していないだけの話だよ
そもそもプロパティなんて作らん、リレーションのキャッシュが働いているだけだ
371 = :
裏で何が起きてるのか理解してないと使えないような機能なら
公式ドキュメントのよっぽど目立つところにそういう説明がないと
まあ普通にハマる人は出るわね
結果「使えねーフレームワーク」という評価が広まることにもなるかと
実際俺はそうなりかけてたよ
372 = :
公式ドキュメントはほんとうに最小限の事しか書いてないから
暇な奴はhttp://github.com/laravel/docs にPR出してくれ
373 = :
>>370
リレーションをプロパティ(PHPのプロパティでもあるしLarvelのDynamicPropertyでもある)を使って実装してる
374 = :
>>373
何を言いたいのか判らんけど間違ってるのはここ
>>357
> プロパティ user の存在をチェック (PHPの動き)
> - userプロパティが存在したら そのまま userプロパティの内容を戻す これはPHPの言語仕様でオーバーロードとかは一切できない
> - user_id が存在して値が入っていたら select * from user where user_id = 1 が走った上で
> userプロパティには userオブジェクトが格納し、その上でuserオブジェクトを戻す
>
> キモは すでに存在するいプロパティにアクセスした時に効かせられるフックはPHPに存在しない って話。
> ケース2では、すでに一度 $dummy = $phone->user; でアクセスし、この時点でuserプロパティが 内容null で作られてしまってる。
375 = :
引用が長くてどこが「ここ」なのかよくわからんけど
「未設定リレーションを参照するとnull値が設定されて
その後はキー値を代入してもリレーションは取得されない」
という挙動が言語仕様的に不可避じゃないなら
ぜひとも解消してほしいところかな
原状、リレーションのプロパティがいつ設定されるのか見ようとして
デバッガでウォッチしてるといつまでもできないんだよね
ウォッチも参照だから先にnullが入っちゃうわけ
デバッガ通すと挙動が変わるってのは少なくとも開発に優しくはないと思うよ
376 = :
>>375
なんで>>357みたいな事言ってたのか判った気がするわ
$relationsがキャッシュの入れ物なのに他のプロパティ監視しててもブレークする訳ないさ
一度Modelのソースを読んだ方がいいよ
377 = :
話にならんな
俺は355じゃないし
ソース読まないと使えないようなフレームワークなりライブラリは
そもそも使う気にならんという
ごくヘタレなプログラマでしかないよ
Laravelの開発者もユーザーに「一度ソース読んでみたら」
なんて平気で言うような「情強」じゃないことを切に祈るわ
まあでも元MSの人なんだっけ?
じゃ典型的な「情強」()なんだろうなきっとw
378 = :
ソース読まなくていいフレームワークを教えて欲しい
あればそれを使いたい
379 = :
真面目な話、.Netとかみんな読んでんの?
380 = :
罵り合い的なのは良くないな
この問題にどう対処するかの実際のとこが知りたい
ってことでざっと Eloquent/Model.php まわり読んでみたけど
>>357 の解釈であってるように見えた
__get をオーバライドして、メソッド setAttribute を呼び出してる。
setAttribute内で呼び出しプロパティ名をメタプログラミング的にメソッド呼び出ししてる。
hoge->user; だと user() が呼ばれるようになってる。
それがたまたま以下の様な リレーション定義だと BelongsToオブジェクトが戻されてる(Userじゃない)。
fucntion user() { return $this->belongsTo("User") };
protected な $relations って変数もあってリレーション作る度に そこに配列として格納されてるけど、
以降 hoge->user にアクセスした際は、$relations は見ずに やっぱ単にプロパティにアクセスされて
先述のBelongsToオブジェクトが戻ってるように見える。
っていうか hoge->user にアクセスした際に、その都度、 $relations の中身を戻すのって
原理的に出来るのかな?
もっというとプロパティを呼んだ時に、メソッド呼び出しに置き換えられるのかなって話になるのか。
でもそれ出来るなら >>355 みたいな問題おこらんよう気も・・・
381 = :
まだ検証してないけど
hoge->user というプロパティ形式じゃなくて
hoge->user() で必ずメソッド形式で呼ぶといいのかも
副作用があるかもしれんがw
382 = :
>>381
それは大丈夫だろうなあ
検証してないけど
383 = :
イマイチ名前空間についてが理解できん。
書かなくても動くのと、動かないのがあるのは何でなんだぜ?
384 = :
それだけ言われてもな
他の主流な言語の名前空間とだいたい同じだし
386 = :
Javaとかの名前空間と確かに違う気がする
387 = :
ワイルドカードによる指定ができないのは結構痛いかも
388 = :
変な仕様ではあるね。ないよりマシだけど
http://pornel.net/phpns
389 = :
>>383
もしかしてエイリアスが定義されているかどうかって話?
http://github.com/laravel/laravel/blob/master/config/app.php#L163-L194
390 = :
エイリアスは登録してるんだけど、
カスタムコマンド作ったりすると、結局書かないと動かないでしょ。
どっかで他にも設定するところあるの?
391 = :
動かないパターンの具体例が無いと答えられる人いないんじゃないか?
392 = :
ドメインキングとかいう糞鯖だからssh使えないんだけど、sshなしじゃデプロイできないよね?
試しにディレクトリ全部ftpでアップロードしてみたけど動かなかった
393 = :
>>392
herokuを使ってみます
395 = :
>>368
すみません、凄い遅レスなんですが、返信ありがとうございます。
396 = :
ドメインキングって調べたらPHPが5.3だな
LaravelはPHP5.4以上が必要
398 = :
5.3系のバージョンアップはもうないって意味ならそのとおりだが
XPとかのサポート切れとはまた意味が違う気がする
安定しててセキュリティに問題がなく新機能が不要なら
ずっとそのまま運用して別に問題ないんじゃね?
399 = :
脆弱性が発見された時に、詳しい人がすぐに対応できる体制が整ってるならいいんだろうね
400 = :
そもそも無料なんだから問題出たら5.4以上に移行してね、で済む話ではあるんだがな
移行にあたって互換性の問題がある?そもそも無料なんで我慢してね、って話でもあるし
そもそも無料なんだからサポートってなにそれ美味しいの?って話でもある
みんなの評価 :
類似してるかもしれないスレッド
- symfony PHPフレームワークpart2 (530) - [60%] - 2022/4/10 22:45
- 【PHP】フレームワーク Akelos (129) - [60%] - 2019/5/9 7:46
- 【PHP】フレームワークPharonスレ (306) - [57%] - 2022/10/10 20:00
- [PHP][フレームワーク]CodeIgniter Part2 (983) - [56%] - 2015/4/7 12:46
- [PHP][フレームワーク]CodeIgniterスレ (983) - [53%] - 2011/3/5 23:17 ○
- 【PHP】フレームワークMapleに舌鼓 (470) - [48%] - 2017/12/31 9:31
- 【PHP】PHPフレームワーク総合スレ15 (989) - [42%] - 2013/9/27 6:00 △
トップメニューへ / →のくす牧場書庫について