제목 | 쿼리 성공여부를 검증하는 로직 적용되었을 때, 작동이 되지 않습니다. | ||
---|---|---|---|
카테고리 | CI 2, 3 | ||
글쓴이 | Chris Ray | 작성시각 | 2018/02/22 08:44:43 |
|
|||
컨트롤러 코드
<?php defined('BASEPATH') OR exit('No direct script access allowed'); class Register extends CI_Controller { /** * Index Page for this controller. * * Maps to the following URL * http://example.com/index.php/welcome * - or - * http://example.com/index.php/welcome/index * - or - * Since this controller is set as the default controller in * config/routes.php, it's displayed at http://example.com/ * * So any other public methods not prefixed with an underscore will * map to /index.php/welcome/<method_name> * @see https://codeigniter.com/user_guide/general/urls.html */ // private $validationStatus = null; public function __construct() { parent::__construct(); $this->load->helper(['url', 'date']); $this->load->library('form_validation'); $this->load->model('register/user_model', 'UserRegister'); } private function _procAssets() { $procAssets = [ 'style_css' => base_url('assets/css/style.css'), 'fontawesome_css' => base_url('assets/css/fontawesome-all.min.css'), 'your_ip' => $this->input->server('REMOTE_ADDR'), 'assets_ver' => mdate('%Y%m%d' ,now()) ]; return $procAssets; } private function _procJoinValidation() { // $joinData = $this->_getJoinData(); // CI 폼검증 라이브러리를 활용한 검증 메서드 $joinRules = [ [ 'field' => 'mn-userId', 'label' => 'mn-userId', 'rules' => 'required|min_length[5]|max_length[20]' ], [ 'field' => 'mn-userPw', 'label' => 'mn-userPw', 'rules' => 'required|min_length[10]|max_length[20]' ], [ 'field' => 'mn-userPwConfirm', 'label' => 'mn-userPwConfirm', 'rules' => 'required|matches[mn-userPw]' ], [ 'field' => 'mn-userPhone', 'label' => 'mn-userPhone', 'rules' => 'required|min_length[9]|max_length[11]' ], [ 'field' => 'mn-userCountry', 'label' => 'mn-userCountry', 'rules' => 'required' ] ]; $this->form_validation->set_rules($joinRules); // 폼 검증 규칙을 배열에 담고 set_rules() 메서드의 인자로 전달하는 방법이다. // $this->validationStatus = $this->form_validation->run(); // $this->validationStatus = is_bool($this->validationStatus); // return $this->validationStatus; return $this->form_validation->run(); } private function _setJoinData() { $joinData = $this->input->post(); // $joinData['userId'] = $this->input->post('mn-userId'); // $joinData['userPw'] = $this->input->post('mn-userPw'); // $joinData['userPwc'] = $this->input->post('mn-userPwConfirm'); // $joinData['userPhone'] = $this->input->post('mn-userPhone'); // $joinData['userCountry'] = $this->input->post('mn-userCountry'); // $this->input->post(); 에서 인자가 없을 경우 모든 post를 배열로 리턴되므로, // $data = $this->input->post(); 면, // $data['mn-userId'] 와 같이 연관배열의 키로써 접근할 수 있다. return $joinData; } private function _getJoinData() { return $this->_setJoinData(); } private function _procJoin() { $joinData = $this->_getJoinData(); $this->UserRegister->joinUser($joinData); } // private function _joinRedirect() { // // $this->_procJoin(); // // if($this->UserRegister->_getStatus()) { // // redirect(base_url('index.php/register')); // // } else { // // redirect(base_url()); // // } // if($this->_procJoinValidation()) { // if($this->UserRegister->_getStatus()) { // redirect(base_url('index.php/register')); // } else { // redirect(base_url()); // } // } else { // echo '폼 검증 에러'; // } // } public function index() { $this->load->view('register', $this->_procAssets()); // echo $this->validationStatus; if($this->input->method() == 'post' && $this->_procJoinValidation() == TRUE && $this->UserRegister->_getStatus() == TRUE) { $this->_procJoin(); // if($this->UserRegister->_getStatus()) { // $this->_procJoin(); // } // $this->_joinRedirect(); } } }
모델 코드 <?php defined('BASEPATH') OR exit('No direct script access allowed'); class User_model extends CI_Model { private $_resultStatus = null; private $_encryptKey = 'saltKey'; public function __construct() { parent::__construct(); $this->load->database(); } private function _procEncrypt($data) { $enc = md5($data.$this->_encryptKey); return $enc; } private function _setStatus($resultStatus) { return $this->_resultStatus = $resultStatus; } public function _getStatus() { return $this->_resultStatus; } public function joinUser($data) { $joinData = [ 'id' => $data['mn-userId'], 'password' => $this->_procEncrypt($data['mn-userPw']), 'phone' => $data['mn-userPhone'], 'email' => null, //'last_at' => 'NOW()', 'ip' => ip2long($this->input->server('REMOTE_ADDR')), 'nationality' => $data['mn-userCountry'] ]; $this->db->set('last_at', 'now()', false); // set(필드, now(), false); // set() 메서드로 MySQL 의 NOW()로 인식시키는 방법 // TIMESTAMP 가 0000-00-00 00:00:00 으로 들어가는 걸 해결할 수 있다. $resultStatus = $this->db->insert('accounts', $joinData); // insert() 메서드는 insert query를 생성하고 바로 실행한다. // 그 후 $resultStatus 에 담는데, $resultStatus = is_bool($resultStatus); // PHP Native is_bool() 로 boolean 형으로 $resultStatus에 저장한다. $this->_setStatus($resultStatus); // _setStatus() setter 메서드로 boolean type 데이터를 보내주고, 이것을 field $resultStatus에 저장한다. // 마지막으로, 컨트롤러에서 접근할 수 있게 public _getStatus() getter 메서드를 이용해 보내준다. } }
문제는 컨트롤러 index() 의 if($this->input->method() == 'post' && $this->_procJoinValidation() == TRUE && $this->UserRegister->_getStatus() == TRUE) { $this->_procJoin(); } 에서 발생하는데index() if 의 $this->UserRegister->_getStatus() == TRUE 에서 문제인 걸로 확인이 되었습니다.
$this->UserRegister->_getStatus() 는 insert가 제대로 되었는지의 여부를 $_resultStatus 필드를 통해 boolean 으로 리턴해주고자 했고,이걸 이용해서 쿼리가 성공일 경우에만 이라는 검증만 넣으면 문제가 발생합니다.
어떻게 해야 좋을까요? 더불어, 질문글을 보기 좋게 작성했는지와 CI를 잘 활용하고 있는지 평가도 부탁드립니다. CI 는 2일차, PHP 2주차 초보가 질문 올립니다. 감사합니다. |
|||
다음글 | 하나도 안건드렸는데, welcome 페이지가 404에러... (12) | ||
이전글 | controller 백그라운드 진행 (2) | ||
변종원(웅파)
/
2018/02/22 09:25:03 /
추천
0
|
Chris Ray
/
2018/02/22 09:34:27 /
추천
0
@변종원(웅파) 답변 감사합니다. AR에 대해서는 말씀주신 메서드를 메뉴얼에서 참고해보겠습니다. 지적해주신 boolean 비교에 대해서 말인데, 1. $is == TRUE 2. $is === TRUE 1번은 값 비교에 가깝고(스트링 TRUE 일수도 있으므로), 2번은 비교하되, 객체까지 일치한지를 좀 더 엄격한 확인을 한다고 이해해도 되는건가요? |
kaido
/
2018/02/22 09:40:47 /
추천
0
특별한 이유가 없다면 getter setter 설정 안하셔도 됩니다. 프레임워크안에서 자동으로 맵핑을 제공하지 않는이상 습관적인 겟터셋터는 지양해야 하는것이 맞습니다 ^^ 자바진영도 불필요한 겟터셋터는 줄여야 한다고 말이 나오고 있구요. is_boolean() 하지 않아도 true , false 으로 제공 합니다. echo 상에는 0,1 로 찍히지만 이는 php auto casting 에 의한것입니다. (int) 0 , false , null , (string) 0 if 비교문에서는 전부 동일하게 처리됩니다. 또한 문자 0 이라도 숫자와 비교문이 들어가면 php는 에러를 뱉지 않고 문자 0을 숫자 0으로 바꿔서 비교합니다. null , false가 대상이면 null, false으로 바꿔서 비교하구요. mysql db 필드가 숫자 형태일때 문자 0 을 넣으면 숫자 0 으로 자동으로 바뀌어서 들어갑니다. 어느 언어에도 없는 php 만의 특수한 형변환 입니다. 그래서 타입 선언에 대해서 크게 골머리 썩지 않아도 됩니다 ㅎㅎㅎ
그래서 boolean 비교에는 === 이렇게 비교하셔야합니다. [좀더 정확하게는 숫자만 인지, 문자만인지, 빈값인지, 공백인지 비교하는 함수들이 전부 있습니다.]
단순하게 비교하실거면 모델에서 바로 return 해버리면 성공 실패여부를 간단히 알수 있고, 좀더 세밀하게 컨트롤 하실거면 웅파님 조언대로 affected_rows() 이라는 함수가 ci 에서 제공하고 있습니다. |
Chris Ray
/
2018/02/22 09:51:55 /
추천
0
@kaido 님 답변 감사합니다. 제 코드 수준이 낮은 것 같아서 올리기가 망설여졌었는데, 실력자분들께서 친절히 답변해주시니 감사할 뿐입니다.
|
이제다시
/
2018/02/22 10:01:14 /
추천
0
$this->UserRegister->_getStatus() == TRUE 위 상태값을 받아오는 부분은 $this->UserRegister->joinUser($joinData); 여기에서 셋팅하는데 먼저 받아오면 초기값인 null 을 받아올 수 밖에 없어 보입니다.
그리고 is_bool() 함수는 변수값이 boolean 타입인지 아닌지를 판단하는 함수인데 실행한다면 true 든 false 든 true 를 반환합니다.
또 $this->db->insert 문은 true/ false 를 반환하는데 바로 return 해서 비교하는게 좋을거 같습니다.
index 페이지를 뷰페이지와 처리페이지로 동시에 사용할려는 의도 같은데 시작부분에 뷰파일을 렌더하고 처리하지말고 validate 를 통과할 경우 처리 / 실패일 경우 뷰렌더링
전체적으로 코드를 너무 쪼개놓은 느낌인데 공통파일은 config 를 이용하고, 불필요한 메소드를 줄이고 코드 진행 순서만 잘 생각한다면 좋을거 같습니다. |
Chris Ray
/
2018/02/22 10:19:31 /
추천
0
@이제다시 님 답변 감사드립니다. if($this->input->method() == 'post' && $this->_procJoinValidation() === TRUE && $this->_procJoin() === TRUE) {
redirect(base_url('index.php/register'));
}
위와 같이 수정하면 흐름이 의도대로 됩니다. 정확히 좋은 방법인지는 모르겠네요 |
Chris Ray
/
2018/02/22 10:42:05 /
추천
0
public function index()
{
$this->load->view('register', $this->_procAssets());
if($this->input->method() == 'post' && $this->_procJoinValidation() === TRUE && $this->_procJoin() === TRUE) {
redirect(base_url());
}
}
방금 발견한 문제점입니다. 검증 3개 거치고, redirect() 가 먹히질 않네요 |
변종원(웅파)
/
2018/02/22 11:36:56 /
추천
0
로직도 좀 이상합니다. 뷰를 먼저 출력하고 post 전송이 있고 입력이 성공하면 다른 주소로 리다이렉트.. 보통은 if(포스트 전송이 있는지) { //있다면 입력 처리후 리다이렉트 } else { //없으면 뷰 출력 } 이렇게 처리합니다. 뷰와 post 처리 메소드를 분리하는 방식도 있구요.
|
insert는 insert_id()로, update, delete는 affected_rows()로 검증하시면 됩니다. 매뉴얼 참고하세요
그리고 boolean 비교는 === 로 하시는게 좋습니다.