| 제목 | 쿼리 성공여부를 검증하는 로직 적용되었을 때, 작동이 되지 않습니다. | ||
|---|---|---|---|
| 카테고리 | 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 비교는 === 로 하시는게 좋습니다.