tag:crieit.net,2005:https://crieit.net/tags/OR%E3%83%9E%E3%83%83%E3%83%91%E3%83%BC/feed 「ORマッパー」の記事 - Crieit Crieitでタグ「ORマッパー」に投稿された最近の記事 2022-06-09T23:58:40+09:00 https://crieit.net/tags/OR%E3%83%9E%E3%83%83%E3%83%91%E3%83%BC/feed tag:crieit.net,2005:PublicArticle/18211 2022-06-09T23:58:40+09:00 2022-06-09T23:58:40+09:00 https://crieit.net/posts/eloquent-use-db-raw-a-facade-root-has-not-been-set-error-20220610 Eloquent 単独で COUNT(*) を使用したいが DB:raw() を使用すると A facade root has not been set. エラーになる <h2 id="経緯"><a href="#%E7%B5%8C%E7%B7%AF">経緯</a></h2> <p>Eloquent 単独利用しているプログラムの中で COUNT(*) を使用したくなったのでその方法をメモ。</p> <p>単純に件数をカウントしてその数値を使いたいだけであれば</p> <pre><code class="php">$data_count = $dbConnect->table('hoge') ->count(); </code></pre> <p>で済ませることができます。が、今回はサブクエリとして使用した方がコード的にすっきりしそうな状況でした。</p> <p>先の方法ではコード上は関連性のない別のクエリをもう1つ記述しなければならないので如何なものかと思い……。</p> <h2 id="調査"><a href="#%E8%AA%BF%E6%9F%BB">調査</a></h2> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://awesome-programmer.hateblo.jp/entry/2019/07/03/162835">LaravelのEloquentで集計関数Count()などを使うとき - バックエンドとフロントエンドを行き来するWEBプログラマ―のメモ帳</a></li> </ul> <p>検索したところ、 SQL で <code>COUNT(*)</code> を使用する場合は <code>DB:raw()</code> を使うとのこと。</p> <p>ただし、 Laravel の中ならばいざ知らず今回は Eloquent 単独使用なので、 <code>DB</code> なるクラスはどこから来るのか……となってしまいました。しかも <code>::raw()</code> は static メソッドですし。</p> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://readouble.com/laravel/8.x/ja/queries.html">データベース:クエリビルダ 8.x Laravel</a></li> </ul> <p>引き続き検索すると、 <code>DB</code> はファサードでした。</p> <p>しかし、 Laravel 公式のサンプルのように</p> <pre><code class="php">use Illuminate\Support\Facades\DB; </code></pre> <p>を追加すると、</p> <blockquote> <p>A facade root has not been set.</p> </blockquote> <p>というエラーが発生して怒られてしまいます。</p> <p>通常の Laravel 内で使用する場合はインスタンスとの紐付けが上手く行われますが、今回は Eloquent のみの単体使用なのでこのパターンではできそうにないように見受けられました (できたとしても素直に Laravel を使った方が早そう)。</p> <p>最終的には</p> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/s-higuma/items/ab8fa110b13301d0c959">Eloquentを単体で導入している時にDBファサードを使用する方法 - Qiita</a></li> </ul> <p>この記事の方法で</p> <pre><code class="php">use \Illuminate\Database\Capsule\Manager as DB; </code></pre> <p>を <code>DB::raw()</code> を使うクラスのファイルの中で再度読み込ませる (別のファイルでDB接続用のインスタンスを生成していて、それを DI していたので今回は「再度読み込ませる」という表現) ことで乗り越えることができました。</p> <h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2> <h3 id="count()"><a href="#count%28%29">count()</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/zaburo/items/d665804f8ea850502c64">Laravelでの基本的なリレーションシップもしくはJOIN - Qiita</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://www.84kure.com/blog/2017/07/12/laravel-eloquent%E3%81%A7%E3%82%AB%E3%82%A6%E3%83%B3%E3%83%88%E3%81%99%E3%82%8B%E3%81%A8%E3%81%8D%E3%81%AE%E6%B3%A8%E6%84%8F/">[Laravel] Eloquentでカウントするときの注意 – 端くれプログラマの備忘録</a></li> </ul> <h3 id="DB::raw()"><a href="#DB%3A%3Araw%28%29">DB::raw()</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://awesome-programmer.hateblo.jp/entry/2019/07/03/162835">LaravelのEloquentで集計関数Count()などを使うとき - バックエンドとフロントエンドを行き来するWEBプログラマ―のメモ帳</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://readouble.com/laravel/8.x/ja/queries.html">データベース:クエリビルダ 8.x Laravel</a></li> </ul> <h3 id="A facade root has not been set. エラー"><a href="#A+facade+root+has+not+been+set.+%E3%82%A8%E3%83%A9%E3%83%BC">A facade root has not been set. エラー</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://re-engines.com/2020/05/11/laravel-facade/">LaravelのFacade(ファサード)とは? 何気なく使用していた裏側の仕組みを解説! | RE:ENGINES</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://www.wakuwakubank.com/posts/453-laravel-sql-basic/">Laravel|DBデータ操作(DBファサード, クエリビルダ, Eloquent) - わくわくBank</a> (バージョン古い)</li> <li><a target="_blank" rel="nofollow noopener" href="https://matchingood-engineer.hatenablog.com/">エンジニアブログ</a> (バージョン古い)</li> <li><a target="_blank" rel="nofollow noopener" href="https://stackoverflow.com/questions/22925451/how-can-i-query-raw-via-eloquent">php - How can I query raw via Eloquent? - Stack Overflow</a> (バージョン古い)</li> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/s-higuma/items/ab8fa110b13301d0c959">Eloquentを単体で導入している時にDBファサードを使用する方法 - Qiita</a></li> </ul> arm-band tag:crieit.net,2005:PublicArticle/18193 2022-05-19T23:50:29+09:00 2022-05-19T23:50:29+09:00 https://crieit.net/posts/eloquent-connect-multiple-db-20220520 Eloquent で複数DBに接続する <p>単独の Eloquent を利用して異なるデータソースにアクセスしてみたのでメモしておきます。</p> <h2 id="コード"><a href="#%E3%82%B3%E3%83%BC%E3%83%89">コード</a></h2> <pre><code class="php"><?php declare(strict_types=1); use Illuminate\Database\Capsule\Manager; class DBConnection { private $db; public function __construct() { $this->db = new Manager; // default $this->db->addConnection([ 'driver' => 'mysql', 'host' => $_ENV['MYSQL1_HOST'], 'database' => $_ENV['MYSQL1_DBNAME'], 'username' => $_ENV['MYSQL1_USER'], 'password' => $_ENV['MYSQL1_PASSWORD'], 'charset' => 'utf8', ]); // second $this->db->addConnection([ 'driver' => 'mysql', 'host' => $_ENV['MYSQL2_HOST'], 'database' => $_ENV['MYSQL2_DBNAME'], 'username' => $_ENV['MYSQL2_USER'], 'password' => $_ENV['MYSQL2_PASSWORD'], 'charset' => 'utf8', ], 'second'); // addConnection() メソッドの第二引数に接続名を指定する (1つ目はなしだと default になる) $this->db->setAsGlobal(); $this->db->bootEloquent(); } // 略 } </code></pre> <p>肝はコメントにも記した通り <code>Manager</code>クラス の <code>addConnection()</code>メソッド について、第二引数に接続名を指定することです (1つ目はなしだと <code>default</code> になり、後で使用する分にも指定は不要) 。</p> <p>あ、しれっと書いていますが <code>dotenv</code> を使用した想定です。</p> <pre><code class="php"><br />$db = new DBConnection(); $secondDBrows = $db->connection('second')->table('hoge_db') ->where( /* 略 */ ) ->select( /* 略 */ ) ->get(); </code></pre> <p>こちらもしれっと書いていますがイメージとしては先程のDB接続用クラス <code>DBConnection</code> をインスタンス化して、その中から <code>connection()</code>メソッド で引数に先程指定した接続名を記述することで二つ目の接続を利用してDBにアクセスできる、ということです。</p> <p>これで意図したことを実装することができました。</p> <h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://blog.bagooon.com/?p=1492">Laravelを使わず、直接PHPからEloquentを使用し、かつ複数のDBに接続する方法。</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://technoledge.net/composer-eloquent-illuminate-database/">LaravelのORM「Eloquent」を単体で使ってスクラッチ開発する | テクナレジ</a></li> </ul> arm-band tag:crieit.net,2005:PublicArticle/18191 2022-05-18T00:03:50+09:00 2022-05-18T00:03:50+09:00 https://crieit.net/posts/eloquent-multiple-where-condition-closure-20220518 Eloquent で複合条件の抽出をする <p>Eloquent を実践的に使い始めたばかりなので初歩的なところですが、複合条件を組み立てるところについてメモ。</p> <h2 id="コード"><a href="#%E3%82%B3%E3%83%BC%E3%83%89">コード</a></h2> <p>やりたいこととしては、 <code>WHERE A AND B AND (C OR D)</code> という条件。</p> <pre><code class="php">$departName = [ '総務部', '営業部', ]; $dataRows = $dbConnect->table('hoge_db') ->where( [ ['user_id', '>', 23], ['age', '<', 42], ] ) ->where(function($query) use ($departName) { $query->orWhere('depart_name', '=', $departName[0]) ->orWhere('depart_name', '=', $departName[1]); }) ->select( 'fuga_db.name', 'fuga_db.attribute', 'fuga_db.parameter' ) ->join('fuga_db', 'hoge_db.user_id', '=', 'fuga_db.employee_id') ->get(); </code></pre> <p><code>$dbConnect</code> にDB接続情報が入ったインスタンスがあるという前提ですが、イメージとしてこのようなコードです。</p> <p>肝は以下。</p> <ul> <li><code>OR</code> 条件の括弧の中身を <code>where()</code>メソッド の中にクロージャとして無名関数で記述する。</li> <li>関数の引数はクエリ。そこに <code>orWhere()</code>メソッド を足していく。</li> <li>クロージャの外部の変数はスコープの関係で Undefined Variable になってしまうので <code>use</code>句 でクロージャ内に持ち込む</li> </ul> <p>これで意図した挙動になることを確認しました。</p> <h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/Hwoa/items/542456b63e51895f9a55">Laravel5で「.. or ...) and (..」みたいな複雑な条件を書く - Qiita</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/mitashun/items/7b1a6c4bb44acd08472e">【Laravel】EloquentでOR検索する方法 - Qiita</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://umebius.com/laravel/querybuilder%E3%81%AB%E3%82%88%E3%82%8Band%E6%A4%9C%E7%B4%A2%E3%81%A8or%E6%A4%9C%E7%B4%A2%E3%81%AE%E8%A4%87%E5%90%88/">Eloquent\/QueryBuilderによるAnd検索とOr検索の複合 - Laravel5開発</a></li> </ul> arm-band