배열 array 분리방법 문의드립니다.
본문
현재 아래와같이 array를 DB에 저장하려고하는데 {n}_test, {n}_date, {n}_date, {n}_desexing는 다른 테이블에 따로 저장하려고하는데 어떻게 하면 좋을지 조언 구해봅니다.. ㅜㅜ
* 초록색은 초록색 테이블에, 주황색은 주황색끼리 저장
* _test, _date, _gender, _desexing은 0~n 이 생성될 수 있습니다.
Array
(
[w] => u
[url] => %2Fbbs%2Fregister_form.php
[mb_tel] => *** 개인정보보호를 위한 휴대폰번호 노출방지 ***
[mb_email] => test@test
[agree] => on
[agree2] => on
[0_test] => 이름1
[0_date] => 2025-02-04
[0_gender] => male
[1_test] => 이름2
[1_date] => 2025-02-05
[0_gender] => female
[2_test] => 이름3
[2_date] => 2025-02-26
[2_gender] => male
[2_desexing] => on
)
답변 4
다음 코드가 도움이 될지 모르겠습니다.
<?php
function array_group_by($arr, $fn) {
$rv = array();
if (is_callable($fn) == false) {
return $rv;
}
array_walk($arr, function ($v, $k) use (&$rv, $fn) {
$k_new = $fn($v, $k);
if (isset($rv[$k_new]) == false) {
$rv[$k_new] = array();
}
$rv[$k_new][$k] = $v;
});
return $rv;
}
$data = array(
'w' => 'u',
'url' => '%2Fbbs%2Fregister_form.php',
'mb_tel' => '*** 개인정보보호를 위한 휴대폰번호 노출방지 ***',
'mb_email' => 'test@test',
'agree' => 'on',
'agree2' => 'on',
'0_test' => '이름1',
'0_date' => '2025-02-04',
'0_gender' => 'male',
'1_test' => '이름2',
'1_date' => '2025-02-05',
'0_gender' => 'female',
'2_test' => '이름3',
'2_date' => '2025-02-26',
'2_gender' => 'male',
'2_desexing' => 'on',
);
$data_00 = array_group_by($data, function ($v, $k) {
if (preg_match('/^\d+_/', $k) === 1) {
return 'group_b';
} else {
return 'group_a';
}
});
$data_01 = array_group_by($data, function ($v, $k) {
$check = preg_match('/^(\d+)_/', $k, $tmp);
if ($check === 1) {
return 'group_' . $tmp[1];
} else {
return 'group_a';
}
});
print_r($data);
/*
Array
(
[w] => u
[url] => %2Fbbs%2Fregister_form.php
[mb_tel] => *** 개인정보보호를 위한 휴대폰번호 노출방지 ***
[mb_email] => test@test
[agree] => on
[agree2] => on
[0_test] => 이름1
[0_date] => 2025-02-04
[0_gender] => female
[1_test] => 이름2
[1_date] => 2025-02-05
[2_test] => 이름3
[2_date] => 2025-02-26
[2_gender] => male
[2_desexing] => on
)
*/
print_r($data_00);
/*
Array
(
[group_a] => Array
(
[w] => u
[url] => %2Fbbs%2Fregister_form.php
[mb_tel] => *** 개인정보보호를 위한 휴대폰번호 노출방지 ***
[mb_email] => test@test
[agree] => on
[agree2] => on
)
[group_b] => Array
(
[0_test] => 이름1
[0_date] => 2025-02-04
[0_gender] => female
[1_test] => 이름2
[1_date] => 2025-02-05
[2_test] => 이름3
[2_date] => 2025-02-26
[2_gender] => male
[2_desexing] => on
)
)
*/
print_r($data_01);
/*
Array
(
[group_a] => Array
(
[w] => u
[url] => %2Fbbs%2Fregister_form.php
[mb_tel] => *** 개인정보보호를 위한 휴대폰번호 노출방지 ***
[mb_email] => test@test
[agree] => on
[agree2] => on
)
[group_0] => Array
(
[0_test] => 이름1
[0_date] => 2025-02-04
[0_gender] => female
)
[group_1] => Array
(
[1_test] => 이름2
[1_date] => 2025-02-05
)
[group_2] => Array
(
[2_test] => 이름3
[2_date] => 2025-02-26
[2_gender] => male
[2_desexing] => on
)
)
*/
?>
배열 데이터를 효율적으로 DB에 저장하기 위해,
기본 사용자 정보를 저장하는 user_info 테이블과
개별 데이터를 저장하는 user_details 테이블을 설계하여 1:N 관계를 형성.
user_info 테이블에는 w, url, mb_tel, mb_email, agree, agree2 등의 기본 정보를 저장하고,
user_details 테이블에는 test_name, test_date, gender, desexing 등의 가변 데이터를 저장하며,
각 데이터는 user_info의 id를 참조하여 연결된다. 데이터 저장 시,
먼저 user_info 테이블에 기본 정보를 삽입한 후
생성된 id 값을 활용해 숫자가 포함된 키(0_test, 1_test 등)를 개별 행으로 변환하여
user_details 테이블에 저장하는 방식이 적절해 보임.
*초록색 테이블 → 기본 사용자 정보를 저장하는 테이블
CREATE TABLE user_info (
id INT PRIMARY KEY AUTO_INCREMENT,
w VARCHAR(10),
url TEXT,
mb_tel VARCHAR(20),
mb_email VARCHAR(50),
agree BOOLEAN,
agree2 BOOLEAN
);
*주황색 테이블 → 개별 데이터를 저장하는 테이블 (user_info와 1:N 관계)
CREATE TABLE user_details (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT,
test_name VARCHAR(50),
test_date DATE,
gender ENUM('male', 'female'),
desexing BOOLEAN,
FOREIGN KEY (user_id) REFERENCES user_info(id)
);
*데이터 분리 및 저장 로직 (PHP/Python 등 활용)
- 숫자가 포함된 키(0_test, 1_test 등)를 추출하여 개별 데이터로 변환
- user_info 테이블에 먼저 저장하고 id 값을 받아 user_details에 삽입
※ 핵심 코드 (PHP + MySQL)
<?php
// 데이터베이스 연결
$conn = new mysqli("localhost", "user", "password", "database");
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// 예제 데이터
$data = [
"w" => "u",
"url" => "/bbs/register_form.php",
"mb_tel" => "공일공-1234-5678",
"mb_email" => "test골뱅이test.com",
"agree" => "on",
"agree2" => "on",
"0_test" => "이름1",
"0_date" => "2025-02-04",
"0_gender" => "male",
"1_test" => "이름2",
"1_date" => "2025-02-05",
"1_gender" => "female",
"2_test" => "이름3",
"2_date" => "2025-02-26",
"2_gender" => "male",
"2_desexing" => "on"
];
// user_info 테이블에 기본 정보 삽입
$stmt = $conn->prepare("INSERT INTO user_info (w, url, mb_tel, mb_email, agree, agree2) VALUES (?, ?, ?, ?, ?, ?)");
$stmt->bind_param("ssssss", $data["w"], $data["url"], $data["mb_tel"], $data["mb_email"], $data["agree"], $data["agree2"]);
$stmt->execute();
$user_id = $stmt->insert_id;
$stmt->close();
// user_details 테이블에 개별 데이터 삽입
foreach ($data as $key => $value) {
if (preg_match('/^(\d+)_(test|date|gender|desexing)$/', $key, $matches)) {
$index = $matches[1];
$column = $matches[2];
if (!isset($userDetails[$index])) {
$userDetails[$index] = ["user_id" => $user_id];
}
$userDetails[$index][$column] = $value;
}
}
// 개별 데이터 저장
$stmt = $conn->prepare("INSERT INTO user_details (user_id, test_name, test_date, gender, desexing) VALUES (?, ?, ?, ?, ?)");
foreach ($userDetails as $details) {
$stmt->bind_param("issss", $details["user_id"], $details["test"], $details["date"], $details["gender"], $details["desexing"]);
$stmt->execute();
}
$stmt->close();
$conn->close();
w값이 u라는 것은 insert가 아니라 update를 사용해야하는 것 같은데 조건이 없으니
insert 예는 다음처럼...
어떤 필드에 어느 값을 넣을 것인지 설명이 없으니 필드명과 넘어온 변수명이 같다는 가정하에
굳이 배열에 담을 필요는 없을 듯 하군요
배열에 넣으려면 $qry1, $qry2 대신 $arr1[$key] = $value; $arr2[$key] = $value;
ksort($_POST);
$qry1 = $deli1 = $qry2 = $deli2 = '';
foreach( $_POST as $key=>$value){
if($key=='w') continue;
if( $key =='url' || $key=='mb_tel' || $key=='mb_email' || $key=='agree' || $key=='agree2' ){
$qry1.=$deli1. "$key='$value'; $deli1=',';
}else{ $qry2.=$deli2. "$key='$value'; $deli2=','; }
}
sql_query("insert into table1 set $qry1");
sql_query("insert into table2 set $qry2");
<?php
// 배열 데이터
$data = [
'w' => 'u',
'url' => '%2Fbbs%2Fregister_form.php',
'mb_tel' => '*** 개인정보보호를 위한 휴대폰번호 노출방지 ***',
'mb_email' => 'test@test',
'agree' => 'on',
'agree2' => 'on',
'0_test' => '이름1',
'0_date' => '2025-02-04',
'0_gender' => 'male',
'1_test' => '이름2',
'1_date' => '2025-02-05',
'1_gender' => 'female',
'2_test' => '이름3',
'2_date' => '2025-02-26',
'2_gender' => 'male',
'2_desexing' => 'on'
];
// 데이터베이스 연결
$pdo = new PDO("mysql:host=G5_MYSQL_HOST;dbname=G5_MYSQL_DB", G5_MYSQL_USER, G5_MYSQL_PASSWORD);
// 1. 메인 테이블에 데이터 저장
$stmt = $pdo->prepare("
INSERT INTO users (w, url, mb_tel, mb_email, agree, agree2)
VALUES (:w, :url, :mb_tel, :mb_email, :agree, :agree2)
");
$stmt->execute([
':w' => $data['w'],
':url' => $data['url'],
':mb_tel' => $data['mb_tel'],
':mb_email' => $data['mb_email'],
':agree' => ($data['agree'] === 'on') ? 1 : 0,
':agree2' => ($data['agree2'] === 'on') ? 1 : 0
]);
$userId = $pdo->lastInsertId(); // 삽입된 user_id 가져오기
// 2. 서브 테이블에 데이터 저장
foreach ($data as $key => $value) {
if (preg_match('/^(\d+)_(test|date|gender|desexing)$/', $key, $matches)) {
$index = $matches[1];
$field = $matches[2];
// user_details 테이블에 데이터 삽입
$stmt = $pdo->prepare("
INSERT INTO user_details (user_id, test, date, gender, desexing)
VALUES (:user_id, :test, :date, :gender, :desexing)
ON DUPLICATE KEY UPDATE
test = VALUES(test), date = VALUES(date), gender = VALUES(gender), desexing = VALUES(desexing)
");
$stmt->execute([
':user_id' => $userId,
':test' => $data["{$index}_test"] ?? null,
':date' => $data["{$index}_date"] ?? null,
':gender' => $data["{$index}_gender"] ?? null,
':desexing' => ($data["{$index}_desexing"] ?? 'off') === 'on' ? 1 : 0
]);
}
}