質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.53%

  • PHP

    20265questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • FuelPHP

    520questions

    FuelPHPは、軽量高速で開発が可能なPHPのWebアプリケーションフレームワークです。

Fuel phpでテーブル同士の紐づけチェック

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 411

permanent

score 20

fuel phpでテーブルAとテーブルBの紐付けのチェックを行い、テーブルAのデータがテーブルBになければ
紐づけされていないレコードの件数分、紐付けのモーダルを表示する機能を実装しています。

ですが、カウンターの表示がうまくいかなく一度モーダルを閉じて再度立ち上がった時のカウンターの表示
がうまくいきません。どうすればよいかわからないです。わかる方いらっしゃいましたらご教授お願い致します。

    // 確定ボタンを押したときの処理
    public function action_confirm($ym) {
            $this->format = "json";
            $data = [
                "result" => true,
                "data" => [],
                "msg" => ""
            ];

        if(\Input::method() === 'GET'){
            $post_id = \Input::get('param');

            // idをもとにファイル種別を取得

            // 取込み結果がない時エラーメッセージを表示
            if($post_id == null){
                // 文字数制限上とりあえず割愛
            }else{

               // タイトルマスタの紐づけチェック
                $wbs = \DB::select('wbs_code')->from('tbl_ams_title_wbs')->execute()->as_array();

                // 紐づけテーブルからwbsコードを取得
                $relation_wbs = array();
                foreach ($wbs as $key => $value) {
                    $relation_wbs[] = $value['wbs_code'];
                }

                // wbsコードを取得
                $android_wbs = \DB::select('wbs_code', 'wbs_name')->from('tbl_ams_deposit_details_android')
                    ->where('account_exec_month', $ym)->and_where('delete_flg', 0)->execute()->as_array();

                // iOSのwbsコードを取得
                $ios_wbs = \DB::select('wbs_code', 'wbs_name')->from('tbl_ams_deposit_details_ios')
                    ->where('account_exec_month', $ym)->and_where('delete_flg', 0)->execute()->as_array();

                // androidテーブルのユニークなWBSコードを取得
                $tmp = array();
                $android_uniq = array();
                foreach($android_wbs as $key => $value){
                    if(!in_array($value['wbs_code'], $tmp)){
                        $tmp[] = $value['wbs_code'];
                        $android_uniq[$key] = $android_wbs[$key];
                    }
                }

                // iosテーブルのユニークなWBSコードを取得
                $tmp = array();
                $ios_uniq = array();
                foreach($ios_wbs as $key => $value){
                    if(!in_array($value['wbs_code'], $tmp)){
                        $tmp[] = $value['wbs_code'];
                        $ios_uniq[$key] = $ios_wbs[$key];
                    }
                }

                // androidとiosの配列をマージ
                $unrelation_arr = array_merge($android_uniq, $ios_uniq);

                // 紐づけテーブルに登録されていないwbsコードがあるときポップアップ
                $relation_flg = 0;
                $data["data"]["count"] = 0;

                // 紐づけされていないデータを取得
                foreach ($unrelation_arr as $key => $value) {
                    if(!in_array($value["wbs_code"], $relation_wbs)){

                        $relation_flg = 0;

                        $data["data"]["wbs_code"] = $value["wbs_code"];
                        $data["data"]["wbs_name"] = $value["wbs_name"];

                        $data["data"]["count"]++;
                    }else{
                        $relation_flg = 1;
                        continue;
                    }
                }

            }
        }
        return $data;
    }

    // タイトルとWBSの紐づけ
    public function get_wbsrelation($ym) {
        $this->format = "json";
        $data = [
            "result" => true,
            "data" => [],
            "msg" => ""
        ];

        $title_id = \Input::get('title_id');
        $wbs_code = \Input::get('code');
        $count = \Input::get('count');

        $relation_data['title_id'] = intval($title_id);
        $relation_data['wbs_code'] = $wbs_code;

        // ログインユーザID取得
        if ($currentuser = \Auth::get_user_id()){
            $currentuser = $currentuser[1];
        }else{
            $currentuser = 0;
        }

        $relation_data['create_user'] = $currentuser;
        $relation_data['update_user'] = $currentuser;
        $relation_data['created_at'] = date('Y-m-d H:i:s');
        $relation_data['updated_at'] = date('Y-m-d H:i:s');
        $relation_data['delete_flg'] = 0;

        $result = \DB::insert('tbl_ams_title_wbs')->set($relation_data)->execute();

        // insertしたあとの処理
        if($result[1] > 0){

            $wbs = \DB::select('wbs_code')->from('tbl_ams_title_wbs')->execute()->as_array();

            // 紐づけテーブルからwbsコードを取得
            $relation_wbs = array();
            foreach ($wbs as $key => $value) {
                $relation_wbs[] = $value['wbs_code'];
            }

            // wbsコードを取得
            $android_wbs = \DB::select('wbs_code', 'wbs_name')->from('tbl_ams_deposit_details_android')
                ->where('account_exec_month', $ym)->and_where('delete_flg', 0)->execute()->as_array();

            $ios_wbs = \DB::select('wbs_code', 'wbs_name')->from('tbl_ams_deposit_details_android')
                ->where('account_exec_month', $ym)->and_where('delete_flg', 0)->execute()->as_array();

            // androidとiosのユニークなwbsコードを取得
            $tmp = array();
            $android_uniq = array();
            foreach($android_wbs as $key => $value){
                if(!in_array($value['wbs_code'], $tmp)){
                    $tmp[] = $value['wbs_code'];
                    $android_uniq[$key] = $android_wbs[$key];
                }
            }

            $tmp = array();
            $ios_uniq = array();
            foreach($ios_wbs as $key => $value){
                if(!in_array($value['wbs_code'], $tmp)){
                    $tmp[] = $value['wbs_code'];
                    $ios_uniq[$key] = $ios_wbs[$key];
                }
            }

            // 紐づけテーブルに登録されていないwbsコードがあるときポップアップ
            $data["data"]["count"] = intval($count);

            // androidとiosの配列をマージ
            $unrelation_arr = array_merge($android_uniq, $ios_uniq);

            // 紐づけされていないデータをviewに送る
            foreach ($unrelation_arr as $key => $value) {
                if(!in_array($value["wbs_code"], $relation_wbs)){
                    $data["data"]["count"]--; //このカウンターがうまくいかない

                    $data["data"]["wbs_code"] = $value["wbs_code"];
                    $data["data"]["wbs_name"] = $value["wbs_name"];
                }
            }
        }
        return $data;
    }
// 確定ボタン→「はい」の処理
function confirm(list){
    $.ajax({
        url: '/admin/api/excel/confirm/' + ym,
        type: 'GET',
        data: {param: list}
    }).then(
        function(data){
            unblockUI();
            // 紐づけのモーダル

            if (data.data.wbs_code != null) {

                $('#modaldialog-title-wbs').modal();

                var wbs_code = data.data.wbs_code;
                var wbs_name = data.data.wbs_name;
                var count = data.data.count;

                $('#wbs_code').html(wbs_code);
                $('#wbs_name').html(wbs_name);
                $('#data_count').html(count);

            }else{
                $('#restable').empty();
                $('#msg').append(data.data.msg);
            }
            getData();

        },function(){
            unblockUI();
            console.log('confirm error');
    });
}


// タイトル割り当ての確認モーダルで「はい」
$('#modal-titlewbs-yes').on('click',function(e) {
    e.preventDefault();
    //blockUI();

    var wbs_code_str = $('#wbs_code').text().replace('<span id="wbs_code">', '');
    var code = wbs_code_str.replace('</span>', '');
    var count = $('#data_count').text();

    title_id = $('#form_title_code').val();

    var list = [];

    $('#restable > table > tbody > tr+tr').each(function() {
        list.push($(this).attr('id'));
    });

    $.ajax({
        url: '/admin/api/excel/wbsrelation/' + ym,
        type: 'GET',
        data: {list: list, title_id: title_id, code: code, count: count}
    }).then(
        function(data){
            unblockUI();

            if(count > 0){
                $('#modaldialog-title-wbs').modal();

                $('#wbs_code').html(data.data.wbs_code);
                $('#wbs_name').html(data.data.wbs_name);
                $('#data_count').html(data.data.count);

            }else{
                var msg = '<div class="alert alert-warning alert-dismissible fade in" role="alert">'+
                          '<button type="button" data-dismiss="alert" class="close">×</button>'+
                          '<p>タイトルの割り当てに成功しました</p>'+
                          '</div>';
                $('#msg').append(msg);
            }


        },function(){
            unblockUI();
            console.log('relation error');
    });

});
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • m6u

    2018/01/10 21:18

    FuelPHP由来の現象でしょうか、js由来の現象の可能性はありませんか?

    キャンセル

  • permanent

    2018/01/11 09:04

    controllerからviewにjsonでデータを渡して、モーダルが閉じられたタイミングで次のモーダルを開くところまではわかりました。

    キャンセル

回答 1

checkベストアンサー

+1

新規紐づけ用の連想配列$data["data"]["count"]--部分は、必ず一件しかとらないコードになっているので、ループごとにマイナスしてはいけません。

public function get_wbsrelation($ym) {
    //...

    // 前のモーダル時の要紐づけトータル件数 - 1(必ず1件しかとらないので)
    $data["data"]["count"] = intval($count) - 1;

    // androidとiosの配列をマージ
    $unrelation_arr = array_merge($android_uniq, $ios_uniq);

    // 紐づけされていないデータをviewに送る
    foreach ($unrelation_arr as $key => $value) {
        if(!in_array($value["wbs_code"], $relation_wbs)) {
            $data["data"]["wbs_code"] = $value["wbs_code"];
            $data["data"]["wbs_name"] = $value["wbs_name"];
        }
    }

    //...
}

余談ですが、いろいろなところにin_array()を書いていますが、array_search()のほうがパフォーマンスが高いです。また、ロジックを見る限りSQLで重複なしのデータを一気に取れると思います。PHPで何度もループで処理すると負荷が高くなりますので。

== 追記 ==

下記のような流れでSQLを発行すればPHP側で重複なし処理のコードを書く必要はありません。テーブル構成にもよりますが、重複なしのレコードを見つけたり、データーをマージしたりするのはSQLのほうが断然早いはずですので。

  1. tbl_ams_deposit_details_android から wbs_code, wbs_name を重複なしで取り出す
  2. tbl_ams_deposit_details_ios から wbs_code, wbs_name を重複なしで取り出す
  3. 上記1., 2. をマージする(※下記SQLは重要なしにしています)
  4. 3. の結果中 tbl_ams_title_wbs には存在しない wbs_code を取り出す
  5. wbs_code でソートする
SELECT wbs_code, wbs_name
FROM (
    (SELECT wbs_code, wbs_name
    FROM tbl_ams_deposit_details_android
    WHERE delete_flg = 0
    GROUP BY wbs_code, wbs_name) 
    UNION DISTINCT (
    SELECT wbs_code, wbs_name
    FROM tbl_ams_deposit_details_ios
    WHERE delete_flg = 0
    GROUP BY wbs_code, wbs_name)
) AS rel
WHERE NOT EXISTS (
    SELECT wbs_code
    FROM tbl_ams_title_wbs AS mst
    WHERE mst.wbs_code = rel.wbs_code)
ORDER BY wbs_code
//Android, iOSからWBSを重複なしで取得するクエリ
$merged = \DB::expr('(('. 
    \DB::select('wbs_code', 'wbs_name')
        ->from('tbl_ams_deposit_details_android')
        ->where('delete_flag', '=', 0)
        ->group_by('wbs_code', 'wbs_name') .
    ') UNION DISTINCT (' .
    \DB::select('wbs_code', 'wbs_name')
        ->from('tbl_ams_deposit_details_ios')
        ->where('delete_flag', '=', 0)
        ->group_by('wbs_code', 'wbs_name') .
    '))');

//$merged の中で tbl_ams_title_wbs に存在しない wbs_code のレコードを取得
$query = \DB::select('wbs_code', 'wbs_name')
    ->from(array($merged, 'rel'))
    ->where(\DB::expr('NOT EXISTS ('. 
        \DB::select('wbs_code', 'wbs_name')
            ->from(array('tbl_ams_title_wbs', 'mst'))
            ->where('mst.wbs_code', '=', \DB::expr(\DB::quote_identifier('rel.wbs_code'))) .
    ')'))
    ->order_by('wbs_code');

//SQL表示
echo $query->compile();

//結果
$unrelations = $query->execute()->as_array();
var_dump($unrelations);

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/01/11 11:37

    ご回答ありがとうございます。参考にしてコードを書き換えましたら、連続でモーダルが立ち上がるようになりました。しかし、同じwbsコードが表示されてしまい次のデータが表示されませんでした。修正しましたら、今度はPHPのin_arrayの処理に入らず、紐づけのモーダルが表示されなくなってしまいました。

    キャンセル

  • 2018/01/12 02:35

    意味はほとんど変わっていませんが、JavaScriptのコードを変更しておきました。「function modalopener()」をモーダル表示イベントに変更しておきました(Bootstrapのみ可)。
    また、PHP側にもコメント追加をしておきました。

    > 同じwbsコードが表示されてしまい次のデータが表示されませんでした。

    JavaScriptの「function confirm()」はどのタイミングでコールしているのでしょうか?
    グローバル変数(var wbs)を何度も初期化してしまっているので同じ「wbs_code, wbs_name」が表示されるのではないでしょうか?
    モーダル表示の度に、表示WBSコード、WBS名を削除するコードを追加しておいたのでデバッグしたい箇所に下記のようにJavaScriptコードを追加してブラウザのコンソール(F12)で確かめてみてはいかがでしょうか。
    ----
    console.log(デバッグしたい変数など);
    例)console.log(wbs, first.wbs_code, first.wbs_name);

    キャンセル

  • 2018/01/12 13:11

    ご回答ありがとうございます。コードを修正したところ、モーダルが表示されるようになりデータも登録されます。ただ、紐づけされていない件数が1件以上あればモーダルを表示し、その件数も表示させているのですが、モーダルを一度とじて再度立ち上がった時のcountの値がうまく取得できませんでした。
    度々すみません。修正したコードを記載いたします。

    キャンセル

  • 2018/01/15 15:35

    ご回答ありがとうございます。コードを実行してみたのですが、
    Fuel\Core\Database_Exception [ 42803 ]:
    SQLSTATE[42803]: Grouping error: 7 ERROR: 列"tbl_ams_deposit_details_android.wbs_name"はGROUP BY句で出現しなければならないか、集約関数内で使用しなければなりません LINE 1: ... "wbs_code", "wbs_name" FROM ((SELECT "wbs_code", "wbs_name"... ^ with query: "SELECT "wbs_code", "wbs_name" FROM (SELECT "wbs_code", "wbs_name" FROM ((SELECT "wbs_code", "wbs_name" FROM "tbl_ams_deposit_details_android" WHERE "delete_flg" = 0 GROUP BY "wbs_code") UNION DISTINCT (SELECT "wbs_code", "wbs_name" FROM "tbl_ams_deposit_details_ios" WHERE "delete_flg" = 0 GROUP BY "wbs_code")) AS "unq" GROUP BY "wbs_code") AS "rel" WHERE NOT EXISTS (SELECT "wbs_code" FROM "tbl_ams_title_wbs" AS "mst" WHERE "mst"."wbs_code" = "rel"."wbs_code") ORDER BY "wbs_code""
    と表示されてしまいました。

    キャンセル

  • 2018/01/16 00:10

    wbs_code, wbs_nameがAndroidとiOSのテーブルで一対一対応になっている前提で回答コードを修正しておきました。つまり、どのwbs_codeでも同じwbs_nameであれば問題ありません。
    たぶん、PHPコードでも特に気にしていないようだったので大丈夫かと思います。

    キャンセル

  • 2018/01/16 09:35

    丁寧なご回答ありがとうございます。無事紐づけが完了しました。
    クエリについても勉強させて頂きましたので、ベストアンサーにさせていただきます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.53%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • PHP

    20265questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • FuelPHP

    520questions

    FuelPHPは、軽量高速で開発が可能なPHPのWebアプリケーションフレームワークです。