WordPress wp_user & wp_usermeta JOIN example
워드프레스에서 사용하는 wp_users, wp_usermeta 테이블 사용 예
워드프레스에서는 웹사이트 이용자를 관리하기 위해 등록한 이용자의 정보를 저장할 때 wp_users와 wp_usermeta 라는 테이블을 사용하고 있다
wp_users 테이블에는 이용자의 user_login(아이디), user_pass, user_email 등의 컬럼에 필수적인 정보가 저장되고 자동증가 필드로는 ID라는 컬럼이 있다.
wp_usermeta 테이블에는 umeta_id, user_id, meta_key, meta_value 등의 컬럼으로 구성되는데, wp_users 테이블의 ID컬럼과 연결하기 위해 user_id 라는 컬럼이 있고 umeta_id 는 자동증가 필드이고 meta_key, meta_value 컬럼에는 이용자 등록정보 중의 커스텀 필드의 값이 저장된다
아래의 코드는 wp_users, wp_usermeta 테이블을 JOIN 하여 가져온 데이터를 화면에 출력하고 화면에서 이용자가 AJAX 요청으로 폼을 전송하면 폼 데이터를 참조하여 테이블의 데이터를 변경하고 AJAX 요청에 대한 응답을 JSON 포맷으로 클라이언트에게 전달하는 예제이다.
WordPress와 PHP에 대한 경험이 부족하다보니 여기까지 성공하는데 적지 않은 시간을 보냈고 다음에는 참조하기 위해 코드를 남겨두기로 한다
테스트 환경
WordPress 4.3, cafe24.com 웹호스팅
액션함수, Shortcode 함수로 구성된 워드프레스 플러그인 형태의 코드
AJAX 요청에 응답으로 JSON을 사용할 때 wp_send_json( 배열 ) 함수가 특히 유용한 것 같다
<?php /* Plugin Name: Plugin-for-Excerpts Plugin URI: http://micropilot.tistory.com Description: A real simple plugin [shortcode_for_excerpt] [getTitle_mb_Notice_To_All] Version: 1.0 Author: Kim Chang Woon Author URI: http://micropilot.tistory.com */ // wordpress.org 사이트에 올려졌을 때 이 파일에 직접 접근하는 것을 방지한다 defined( 'ABSPATH' ) or die( 'Plugin file cannot be accessed directly.' ); /* 위의 헤더 내용은 워드프레스 관리자화면 [플러그인] 화면에 나타난다 plugin Name : 필수 (이 항목만 필수임) Plugin URI: 플러그인 상세정보 페이지(비필수), 워드프레스 플러그인 페이지에 [플러그인 사이트 방문] 링크 구성 Version : 버전번호 (비필수) License : 'GPLv2 or later', 혹은 'Free' (비필수) wordpress.org 사이트에 올려졌을 때 이 파일에 직접 접근하는 것을 방지한다 */ function display_msg($atts) { echo 'Shortcode 플러그인에서 생성한 Excerpt(요약) 메시지<p>'; } /* 테스트용 Shortcode 태그를 선언한다. 선언된 태그는 페이지 요약란에 사용할 수 있다 [shortcode_for_excerpt] 라는 Shortcode 태그를 페이지 편집화면의 요약(Excerpts)란에 입력하면 된다 */ add_shortcode('shortcode_for_excerpt', 'display_msg'); function set_style() { ?> <style> div.excerptContainer { border:1px solid lightgray; border-radius:10px; padding:15px;} ul { padding:5px; } li {/*list-style-type:circle; background:#cceeff;*/ padding:5px;} img.excerptImg {display:block; text-align:center; margin:0px auto; width:auto; height:auto; max-width:300px; max-height:200px;} img.excerptImg2 {display:block; text-align:center; margin:0px auto; width:auto; height:auto; max-width:500px; max-height:400px;} </style> <?php } function set_javascript($table_name){ ?> <script> var table_name ="<?php echo $table_name;?>"; jQuery(function(){ //alert('jQuery ready!'); }); </script> <?php } /* MangBoard에서 첨부파일 정보를 저장하는 테이블 : mb_files mb_files 테이블의 속성: pid, user_pid, user_name, board_name, board_pid, table_name, file_name, file_path, file_sequence file_path 컬럼에 저장된 경로는 아래의 URL에 포함된 'mb-file.php?path=' 이후의 문자열이다. 웹브라우저 화면에 이미지를 출려하려면 아래처럼, mb_files 테이블의 file_path 컬럼에 저장된 경로를 urlencode()함수로 변환하여 사용해야 한다 <img src="http://loveridgepre.net/wp-content/plugins/mangboard/includes/mb-file.php?path=2016%2F02%2F21%2FF3_KakaoTalk_20160217_%ED%94%84%EB%A6%AC%EC%8A%A4%EC%BF%A8%EB%A1%9C%EA%B3%A0_small.jpg" http://loveridgepre.net/2016%2F02%2F21%2FF3_KakaoTalk_20160217_%ED%94%84%EB%A6%AC%EC%8A%A4%EC%BF%A8%EB%A1%9C%EA%B3%A0_small.jpg */ // Shortcode 함수, 요약란에 입력한 Shortcode에 의해 호출되어 글의 제목과 특성 이미지를 가져옴 // Excerpt입력란에 사용하는 방법[get_excerpts_title_img table_name='mb_Notice_To_All'] add_shortcode('get_excerpts_title_img', 'getExcerpts'); function getExcerpts($atts) { $arr_page_id = array( 'mb_Notice_To_All'=>'54', 'mb_BBS_For_All'=>'56', 'mb_Notice_To_SEED'=>'46', 'mb_Notice_To_TREE1'=>'30', 'mb_Notice_To_TREE2'=>'38', 'mb_Notice_To_FRUIT1'=>'34', 'mb_Notice_To_FRUIT2'=>'42', 'mb_Notice_To_DAYCARE'=>'50' ); set_style(); $arr_pid = array(); $arr_title = array(); $rows = 0; if($atts['table_name']=='mb_Notice_To_All' || $atts['table_name']=='mb_BBS_For_All') { set_javascript($atts['table_name']); $rows = 10; } else $rows = 5; global $wpdb; $sql = "SELECT pid, title FROM ".$atts['table_name']." ORDER BY pid DESC LIMIT 0, $rows"; $rs = $wpdb->get_results($sql); foreach($rs as $notice){ array_push($arr_pid, $notice->pid); array_push($arr_title, $notice->title); } $arr_imgpath = getFeatureImg($atts['table_name'], $arr_pid); $cssClass = "excerptImg"; if($atts['table_name']=='mb_Notice_To_All') { $cssClass = "excerptImg2"; echo '<h6>[전체 공지]</h6>'; }else if($atts['table_name']=='mb_BBS_For_All') { $cssClass = "excerptImg2"; echo '<h6>[전체 게시판]</h6>'; } echo "<div class='excerptContainer'><ul>"; $img_dir = "http://loveridgepre.net/wp-content/plugins/mangboard/includes/mb-file.php?path="; for($i=0;$i<count($arr_pid);$i++){ $title = $arr_title[$i]; echo "<li><a href='http://loveridgepre.net/?page_id=".$arr_page_id[$atts['table_name']]."'>".$title; if($arr_imgpath[$arr_pid[$i]]!=null){ echo "<img class='".$cssClass."' src='".$img_dir.urlencode($arr_imgpath[$arr_pid[$i]])."'>"; } echo "</a></li>"; } echo "</ul></div>"; } /* 각 공지게시판의 최근 공지에 포함된 이미지 읽어오기*/ function getFeatureImg($table_name, $arr_pid) { $arr_imgpath = array(); global $wpdb; $sql = "SELECT board_pid, file_path ". "FROM mb_files ". "WHERE table_name='".$table_name."' ". "AND board_pid BETWEEN ".$arr_pid[count($arr_pid)-1]." AND $arr_pid[0] ". "AND file_sequence=1 ". "ORDER BY board_pid DESC ". "LIMIT 0, 1"; $rs = $wpdb->get_results($sql); foreach($rs as $record){ $arr_imgpath[$record->board_pid] = $record->file_path; } return $arr_imgpath; } /* 관리자의 회원가입 승인 절차 */ add_shortcode('get_new_comer', 'admin_approval01'); function admin_approval01(){ global $wpdb; $sql = "SELECT u.ID, u.user_login, u.user_email, u.user_registered, ". "m1.meta_key, m1.meta_value AS level, m2.meta_key, m2.meta_value msg ". "FROM wp_users u ". "INNER JOIN wp_usermeta m1 ". "ON u.ID=m1.user_id ". "AND m1.meta_key='wp_user_level' ". "AND m1.meta_value=0 ". "INNER JOIN wp_usermeta m2 ". "ON u.ID=m2.user_id ". "AND m2.meta_key='user_desc'"; $rs = $wpdb->get_results($sql); ?> <script> jQuery(function(){ jQuery('#btnSave').on('click',function(){ if(!confirm('선택된 이용자를 등록처리하시겠어요?')) return; ajax_request(); }); }); function ajax_request(){ var url = "<?php echo admin_url( 'admin-ajax.php' );?>"; var form_data = jQuery('#form1').serialize(); jQuery.post( url, form_data, function(data, textStatus, jqXHR){ if(data.success){ alert("이용자 등록처리에 성공했습니다"); } else { alert("이용자 등록처리에 실패했습니다"); } }, "json" ).fail (function(jqXHR, textStatus, errorThrown) { alert("에러:"+errorThrown); }); } </script> <form name="form1" id="form1"> <input type="hidden" name="action" value="reg_approve_submited"> <table> <tr><th>No</th><th>ID</th><th>Email</th><th>Registered</th><th>Level</th><th>Message</th><th>Approve</th></tr> <?php foreach($rs as $user) { echo "<tr><td>".$user->ID."</td><td>".$user->user_login."</td><td>".$user->user_email."</td>". "<td>".$user->user_registered."</td><td>".$user->level."</td><td>".$user->msg."</td>". "<td><input type='checkbox' name='approved[]' value='".$user->ID."'></td>". "</tr>"; } ?> </table> <button type="reset">취 소</button> <button id="btnSave" type="button">저 장</button> </form> <?php } add_action( 'wp_ajax_nopriv_reg_approve_submited', 'update_user_level' ); add_action( 'wp_ajax_reg_approve_submited', 'update_user_level' ); function update_user_level(){ if(!isset($_POST['approved'])) { return; } $arr_approve = $_POST['approved']; global $wpdb; $updated = true; foreach($arr_approve as $num){ $updated = $wpdb->update( 'wp_usermeta', array( 'meta_value' => '1'), // data array( 'user_id' => $num, 'meta_key'=>'wp_user_level' ),// where array( '%s'), // data format array( '%s','%s' ) // where format ); if(!$updated) { break; } } $response = array('success'=>$updated); wp_send_json($response); } ?>