'2017/11/17'에 해당되는 글 2건

728x90

대체 MVC가 뭐지?

MVC(Model-View-Controller)는 소프트웨어 공학에서 사용하는 아키텍쳐 패턴이다.

PHP 코드를 작성할 때 Data 와 Design, Controller 를 분리시켜 만드는 것이다.

개발하는데 복잡하고 어려워도 확장성이 좋고 수정/유지보수하기가 편하다.

 

Framework(프레임워크)는 Web 애플리케이션을 개발할 때 많이 사용하는 기능이나 일상적인 구조를 정리한 것이다. 대부분의 프레임워크는 MVC의 구조를 채용한다.

 

뭐 대충 이렇게 정의하고 있다.

- Model : application 의 정보(데이터) → 데이터의 생성, 접근, 수정, 삭제하는 부분

             데이터의 값과 상태 및 각종 기능을 처리하는 Business Logic 부분과 사용되는 데이터 부분으로 구성

             Controller 에서 건네준 요청을 처리하고 다시 돌려준다.

             모델은 데이터의 가공이나 저장, 비즈니스 로직 등의 프로그램 처리를 담당한다.

- View : User Interface (HTML, CSS 로 만든 정적인 페이지 부분)

            화면 UI 부분이며 사용자게게 응답 처리 결과를 보여준다.

            뷰는 필요에 따라 모델의 데이터 내용을 참조하고 사용자에게 화면을 보여준다.

- Controller : Data 와 Business Logic 사이의 상호동작을 관리한다.

                   Model 과 View 사이에서 request 와 response를 관리하며 동작한다.

                   컨트롤러는 사용자가 조작하면 모델이나 뷰에 필요한 지시를 보낸다.

 

 

PHP MVC Frmaework 의 대표적인 것이 Laravel(라라벨), CodeIgniter(코드이그나이터) 라는데 아직 사용해본 적은 없다.

그누보드, 제로보드, KIMSQRB 는 프레임웍이라기 보다는 CMS툴에 가깝다고 봐야 한다.

 

프레임웍을 만들정도까지 실력을 키우려면 한참 배워야 한다.

이제 그런 구조(패턴)을 고려해서 PHP 코드 작성을 해보고 있는 중이다.

 

게시글 http://link2me.tistory.com/1398 , http://link2me.tistory.com/1399 에 첨부된 파일과 비교해서 수정된 부분이 어떤 것인지 살펴보면 도움될 것이다.

본 코드는 테스트용도이므로 Class를 더 세분화해서 분리하고 Class 이름을 정해서 추가해나가면 된다.

 

아래 코드와 login.php, register.php 파일이 포함된 압축파일을 첨부한다.

pdo.zip
다운로드

 

 

 

 

 

<?php
//****************
// DB 정보 입력
//****************
define('_DBHOST','localhost');
define('_DBUSER','android'); // DB 사용자
define('_DBPASS', '!android@'); // DB 패스워드
define('_DBNAME','android'); // DB 명
define('_DBTYPE','mysql'); // 데이터베이스 종류
define('_DSN',_DBTYPE.':host='._DBHOST.';dbname='._DBNAME.';charset=utf8');

//*****************************
// 파일 디렉토리
//*****************************
define('_CONFIG_DIR',__DIR__);
define('_CLASS_DIR',_CONFIG_DIR.'/Class/');

//***************************
//클래스 파일 불러오기
//***************************
require_once _CLASS_DIR.'DBConClass.php'; // DB 연결 클래스
require_once _CLASS_DIR.'MemberClass.php';

?>

<?php
class DBConClass{
    protected $db; // 변수를 선언한 클래스와 상속받은 클래스에서 참조할 수 있다.

    public function __construct(){
        $this->dbConnect();

        // construct 메소드는 객체가 생성(인스턴스화)될 때 자동으로 실행되는 특수한 메소드다.

    }

    private function dbConnect() {
        try{
            // MySQL PDO 객체 생성
            $this->db = new PDO(_DSN, _DBUSER, _DBPASS);
            $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            $this->db->setAttribute(PDO::ATTR_EMULATE_PREPARES, FALSE);
        } catch(PDOException $ex){
            die("오류 : ".$ex->getMessage());
        }
    }
}
?>

<?php
class MemberClass extends DBConClass {
    // 회원 정보 신규 입력
    public function storeUser($userID, $userNM, $email, $password, $telNO, $mobileNO) {
        $hash = $this->hashSSHA($password);
        $encrypted_password = $hash['encrypted']; // encrypted password
        $salt = $hash['salt']; // salt

        try{
            $this->db->beginTransaction();
            $sql = "INSERT INTO members(userID, userNM, email, passwd, salt, telNO,mobileNO,created_at) VALUES(:userID,:userNM,:email,:passwd,:salt,:telNO,:mobileNO,:created_at)";
            $stmt = $this->db->prepare($sql);
            $stmt->bindValue(':userID',$userID,PDO::PARAM_STR);
            $stmt->bindValue(':userNM',$userNM,PDO::PARAM_STR);
            $stmt->bindValue(':email',$email,PDO::PARAM_STR);
            $stmt->bindValue(':passwd',$encrypted_password,PDO::PARAM_STR);
            $stmt->bindValue(':salt',$salt,PDO::PARAM_STR);
            $stmt->bindValue(':telNO',$telNO,PDO::PARAM_STR);
            $stmt->bindValue(':mobileNO',$mobileNO,PDO::PARAM_STR);
            $stmt->bindValue(':created_at',date("YmdHis"));
            $result = $stmt->execute();
            $this->db->commit();
        } catch (PDOException $pex) {
            $this->db->rollBack();
            echo "에러 : ".$pex->getMessage();
        }
        // check for successful store
        if ($result) {
            $stmt = $this->db->prepare("SELECT * FROM members WHERE userID = :userID");
            $stmt->bindValue(':userID', $userID, PDO::PARAM_STR);
            $stmt->execute();
            $user = $stmt->fetch(PDO::FETCH_ASSOC);

            return $user;
        } else {
            return false;
        }
    }

    // 로그인 체크
    public function getUser($userID, $password) {
        $sql = "SELECT * FROM members WHERE userID=:userID";
        $stmt = $this->db->prepare($sql);
        $stmt->bindValue(':userID', $userID);
        $stmt->execute();

        if ($user=$stmt->fetch()) {
            // verifying user password
            $salt = $user['salt'];
            $encrypted_password = $user['passwd'];
            $hash = $this->checkhashSSHA($salt, $password);
            if ($encrypted_password == $hash) {
                // user authentication details are correct
                return $user;
            }
        } else {
            return NULL;
        }
    }

    // 안드로이드/아이폰 로그인 체크
    public function LoginUserChk($userID,$password,$deviceID){
        if(empty($userID) || empty($password)){
            return 0;
        } else {
            $user = $this->getUser($userID, $password);
            if($user['idx']>0){
                // 장치 일련번호 체크
                if($user['phoneSE'] == NULL){
                    // 신규 장비번호 입력(최초 로그인)
                    $this->LoginUserEquipInput($userID,$deviceID);
                    return $user['idx'];
                } else {
                    if($user['phoneSE'] === $deviceID){
                        return 1; // 일련번호 일치
                    } else {
                        return -1; //일련번호 불일치
                    }
                }
            } else {
                return 0; //계정오류
            }
        }

    }

    // 장치번호 업데이트
    public function LoginUserEquipInput($userID,$deviceID){
        if(strlen($deviceID)>0 && is_numeric($deviceID)){ // 안드로이드폰
            $ostype = 2;
        } else if(strlen($deviceID)>30){ // 아이폰
            $ostype = 1;
        } else { // 기타
            $ostype = 0;
        }

        try{
            $this->db->beginTransaction();
            $sql='update members set phoneSE=:phoneSE, OStype=:OStype where userID=:userID';
            $stmt = $this->db->prepare($sql);
            $stmt->bindValue(':phoneSE',$deviceID,PDO::PARAM_STR);
            $stmt->bindValue(':OStype',$ostype,PDO::PARAM_INT);
            $stmt->bindValue(':userID',$userID,PDO::PARAM_STR);
            $status = $stmt->execute();
            $this->db->commit();
            if($status == true){
                return 1;
            } else {
                return 0;
            }
        }catch (PDOException $pex) {
            $this->db->rollBack();
            echo "에러 : ".$pex->getMessage();
        }
    }//end

    // 장치번호 초기화
    public function EquipReset($userID){
        try{
            $this->db->beginTransaction();
            $ostype = 0;
            $sql='update members set phoneSE=NULL,OStype=:OStype where userID=:userID';
            $stmt = $this->db->prepare($sql);
            $stmt->bindValue(':OStype',$ostype,PDO::PARAM_INT);
            $stmt->bindValue(':userID',$userID,PDO::PARAM_STR);
            $status = $stmt->execute();
            $this->db->commit();
            if($status == true){
                return 1;
            } else {
                return 0;
            }
        } catch (PDOException $pex) {
            $this->db->rollBack();
            echo "에러 : ".$pex->getMessage();
        }
    }//end

    // 회원 가입 여부 체크
    public function isUserExisted($userID) {
        $stmt = $this->db->prepare("SELECT userID from members WHERE userID=:userID");
        $stmt->bindValue(':userID',$userID,PDO::PARAM_STR);
        $stmt->execute();
        if ($stmt->rowCount() > 0) {
            return true;
        } else {
            return false;
        }
    }

    // 회원 정보 삭제
    public function deleteUser($userID){
        try{
            $this->db->beginTransaction();
            $stmt = $this->db->prepare("delete FROM members WHERE userID=:userID");
            $stmt->bindValue(':userID',$userID,PDO::PARAM_STR);
            $stmt->execute();
            $this->db->commit();
        }catch (PDOException $pex) {
            $this->db->rollBack();
            echo "에러 : ".$pex->getMessage();
        }
    }

    public function hashSSHA($password) {
        $salt = sha1(rand());
        $salt = substr($salt, 0, 10);
        $encrypted = base64_encode(sha1($password . $salt, true) . $salt);
        $hash = array("salt" => $salt, "encrypted" => $encrypted);
        return $hash;
    }

    public function checkhashSSHA($salt, $password) {
        $hash = base64_encode(sha1($password . $salt, true) . $salt);
        return $hash;
    }
}
?>

 

블로그 이미지

Link2Me

,
728x90

윈도우 기반 AutoSet9 에서 테스트를 하다보니 계속 driver 를 못찾는다는 에러 메시지를 출력한다.

원인은 PDO(PHP Data Object) 설정이 안되어 있어서다.

 

PHP에는 다양한 데이터베이스를 쉽게 이용할 수 있도록 PDO라는 확장모듈이 포함되어 있다.

PDO(PHP Data Object) 동작이 되도록 설정하는 방법은 간단하다.

 

1. conf/php.ini 파일을 열어서 아래와 같이 주석을 제거한다.

- php_pdo_mysql.dll 만 주석제거 해도 되는데 PostgreSQL 도 사용하게 될지 몰라서 같이 주석 제거를 했다.

 

 

 

2. php.ini 수정사항을 반영하기 위해서는 Apache Web서버를 재기동해야 한다.

 

 

웹서버 멈춤을 눌러서 웹서버를 종료시켰다가 웹서버 시작을 눌러서 재실행되도록 한다.

 

 

3. phpinfo(); 로 설정된 상태가 반영되었는지 확인한다.

 

이렇게 해주면 PDO 방식으로 코딩 테스트를 할 수 있다.

 

AutoSet10 (PHP 7.0 + MariaDB) 도 동일하게 설정하면 된다.

블로그 이미지

Link2Me

,