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