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

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

新規登録して質問してみよう
ただいま回答率
85.48%
MySQL Workbench

MySQL Workbenchは、オープンソースのデータベースモデリングツールです。ビジュアルなデータベース設計・SQL開発・サーバー設定・ユーザー管理・バックアップといった様々な管理ツールを備えます。

PHP

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

CakePHP

CakePHPは、PHPで書かれたWebアプリケーション開発用のフレームワークです。 Ruby on Railsの考え方を多く取り入れており、Railsの高速性とPHPの機動性を兼ね備えています。 MVCやORMなどを「規約優先の考え方」で利用するため、コードを書く手間を省くことができます。 外部のライブラリに依存しないので、単体での利用が可能です。

Q&A

解決済

3回答

2419閲覧

Cakephp3で多次元配列に入っている価をDBにInsertとUpdateしたいです。

lovelydai

総合スコア38

MySQL Workbench

MySQL Workbenchは、オープンソースのデータベースモデリングツールです。ビジュアルなデータベース設計・SQL開発・サーバー設定・ユーザー管理・バックアップといった様々な管理ツールを備えます。

PHP

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

CakePHP

CakePHPは、PHPで書かれたWebアプリケーション開発用のフレームワークです。 Ruby on Railsの考え方を多く取り入れており、Railsの高速性とPHPの機動性を兼ね備えています。 MVCやORMなどを「規約優先の考え方」で利用するため、コードを書く手間を省くことができます。 外部のライブラリに依存しないので、単体での利用が可能です。

0グッド

0クリップ

投稿2017/12/01 10:09

こんにちは!
ローカルにあるCSVファイルを読み込んで、サーバーに送信し、それをDBにインサートする機能を作ろうとしています。
ファイルの中身を読み取るのは成功し、Cakephp3にAjaxで投げて以下のような多次元配列csvContensを作りました。(ファイルの1行目はフィールド名が書いてあるので、2行目から読み取って配列インデックスは1からになりました。)

イメージ説明

この配列をForeach等でループを回し、DBのTable(Section)に入っているフィールド値と比較し、一致する情報があれば配列価でUpdateの更新し、一致する情報がなければInsertで追加することがしたいです。
DBのフィールドと値は以下のように入っています。

イメージ説明

しかし、この2つの連想配列をどういう風に扱い、比較し、DBに入れればいいか、がよく分かりません。
何かアドバイスか、ヒントになれるようなことあれば教えてください。
宜しくお願い致します。

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yambejp

2017/12/01 11:57

ソースはテキストで書き起こし、DBに登録するならどういった構造なのかも記載して下さい
guest

回答3

0

cakephp勉強中のものです!
以下のようなやり方ではどうでしょうか?
1 .

<?php namespace App\Controller; use Cake\ORM\TableRegistry; class TestsController extends AppController { public function index() { $csvContents=[ [9999,2017,1,99,'テスト','テスト','ああ',true,null,null], [8888,2017,1,88,'トステ','トステ','いい',false,null,null], ]; $tests=TableRegistry::get('Tests'); foreach($csvContents as $c){ if($tests->find('all')->where(['section_idx'=>$c[0]])->count()){ $test = $tests->get($c[0]); }else{ $test = $tests->newEntity(); }; $test->section_idx = $c[0]; $test->year = $c[1]; $test->customer_idx = $c[2]; $test->section_code = $c[3]; $test->section_name = $c[4]; $test->section_short = $c[5]; $test->memo = $c[6]; $test->is_used = $c[7]; $test->deleter = $c[8]; $test->deleted = $c[9]; $tests->save($test); } } }

2 .
MySQLを使っているのであればREPLACE INTOを使う方法もあるみたいです。
updateではなく、delete→insertらしいですけど、
MySQL :: MySQL 5.6 リファレンスマニュアル :: 13.2.8 REPLACE 構文

<?php namespace App\Controller; use Cake\Datasource\ConnectionManager; use PDO; class TestsController extends AppController { public function index() { $csvContents=[ [9999,2017,1,99,'テスト','テスト','ああ',true,null,null], [8888,2017,1,88,'トステ','トステ','いい',false,null,null], ]; $conn = ConnectionManager::get('default'); foreach($csvContents as $c) { $stmt = $conn->prepare("REPLACE INTO tests VALUES(?,?,?,?,?,?,?,?,?,?)"); $stmt->execute($c); } } }

投稿2017/12/02 04:45

saitouakihiro

総合スコア85

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

こんな感じで書き直しました。
2つの配列を比較することは、うーん、あまりにもよくないですね。w

CSVファイルを1行づつよみ、DBにあるか確認してそれぞれ処理するようになりました。

PHP

1foreach($csvContents as $key => $csvContent) 2 { 3 $csv_section_idx = $csvContent[0]; 4 $csv_section_year = $csvContent[1]; 5 $csv_customer_idx = $csvContent[2]; 6 7 echo "Loop is : " . $key. " " . " "; 8 9 if($customer_idx == $csv_customer_idx) 10 { 11 $section = $this->Section->find()->where(['customer_idx' => $customer_idx]) 12 ->andWhere(['section_idx' => $csv_section_idx]) 13 ->andWhere(['year' => $csv_section_year]) 14 ->select(['section_idx','year','customer_idx','section_code','section_name','section_short','memo','is_used','deleter','deleted']) 15 ->toList(); 16 17 if(empty($section)) 18 { 19 echo "result : Insert with " . "csv_section_idx : " . $csv_section_idx . " csv_section_year : " . $csv_section_year . " "; 20 21 } 22 else 23 { 24 echo "result : update with " . "csv_section_idx : " . $csv_section_idx . " csv_section_year : " . $csv_section_year . " "; 25 } 26 } 27 else 28 { 29 echo "result : error , "; 30 // error 31 } 32 33 34 35 }

投稿2017/12/04 06:33

lovelydai

総合スコア38

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

まず「何の目的でそれがしたいのか」ということを書いた方がいいかと思います。
そうでないと「目的を達成する為の別の方法の提案」を他の方もできないからです。

質問の中身に戻りますが、やりたいことを端的に言うと
1.CSVを読み込む
2.読み取ったデータでDBを更新
それに加えて、下記でしょうか
3.CSVのカラムにはあって、DBのテーブルにはないカラムは自動的にDBにカラム追加する

もし上記の認識が間違っていたら申し訳ありませんが、
3.の方法はまず普通やらないです。
CSVの内容次第でDBの構造が変わるなんて言うのは怖すぎて運用できないです。
仮にそれをやるにしても追加するカラムのカラムの制約もCSVに書くのでしょうか?
とても現実的ではないですよね。
CSV自体が間違っていた場合など、意味のわからないゴミカラムは増えていきますし、
じゃあCSVに存在しないカラムは削除するのかとすると、何かの拍子に既存のカラムを削除してしまい、今までのデータが壊れるリスクと常に隣り合わせです。よってやめた方がいいです。

もし後から項目が追加されるというのであれば、
項目追加の度にDBのテーブルにカラムを追加すべきです。
あるいは、後からどんどん追加されていくような項目に関しては、カラムを1つ用意して、そこにjson形式で保管しておくという方法もあります。※DBに保管する際、jsonはただの文字列になり、記述形式も単純な文字列とは違う為、SQL文による検索や絞り込みでは使えなくなりますので、そういう点では注意

その他、読み取ったCSVに関してですがただの配列ではなく、CSVのヘッダーも読み取って連想配列にしてやらないとDBのどのカラムに対して更新をかける項目なのかがわからないですね。

投稿2017/12/02 00:39

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

lovelydai

2017/12/04 06:31

ありがとうございます。配列をまるごと比較しようと思った時点でちょっとまって!と。 CSVファイルを1行づつ読んで、フォーマットなどをチェックし、DBにあるか確認し、あれば更新、なければ登録というやり方の方がもっと簡単ですね。考え直すきっかけとなりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問