PHP/WAMP2019. 1. 12. 20:37

WAMP 다운로드 및 설치

https://sourceforge.net/projects/wampserver/files/

설치 중에 웹브라우저, 에디터를 선택하는 창에서 [아니오]를 선택하고 설치를 진행한다


WAMP 서버 실행

윈도우 시작 > wampserver64 선택

작업표시줄 우측에 local server 아이콘이 보이는지 확인

아이콘 클릭 > Start All Services 선택 > 아이콘이 초록색으로 변하면 실행완료

웹브라우저 주소창에 http://localhost 입력 > 엔터

웹브라우화면에 wamp 서버 초기화면이 표시되는지 확인한다

phpMyAdmin 링크를 클릭하여 데이터베이스 로그인 화면에서 다음과 같이 입력한다

아이디 :  root,      암호: 비어둔다

데이터베이스 관리화면에서 데이터베이스나 테이블을 생성하고 관리할 수 있다

참고로, wamp의  MySQL root 계정 암호는 설정되지 않은 상태로 설치된다


MySQL Workbench 설치 및 실행

MySQL Workbench 를 설치하고 실행하면 자동으로 로컬 MySQL root 계정 접속을 생성하여 첫화면에서 제시하므로 해당 접속을 클릭하여 바로 데이터베이스 관련 작업을 할 수 있다


PHP 에디터로 Apache NetBeans 설치하기

http://netbeans.apache.org/

Download

Downloading 항목 아래에서 

Binaries: incubating-netbeans-10.0-bin.zip ( SHA-512, PGP ASC)


넷빈즈 설치 후 실행/프로젝트 생성

화면 왼쪽 컬럼에서 [Projects] 탭에서 마우스 우측 > New Project >

 PHP > PHP Application > Project Name > 

Sources Folder : wamp/www

PHP Version : 5.6

Run As : Local Web Site

Project URL : http://localhost

PHP Frameworks:지정안함

Finish

프로젝트가 생성되면 왼쪽 [Projects] 탭에 소스폴더의 모든 내용이 표시된다


넷빈즈에서 웹브라우저 지정하기

넷빈즈 툴바에서 지구본 모양의 웹브라우저 아이콘을 선택하면 웹브라우저를 선택할 수 있다

여기서는 [Chrome] 을 선택한다

프로젝트 Source Files 안에 마우스 우측 > New > PHP File 선택 > 파일이름 지정 > Finish

생성된 파일명을 더블클릭하여 에디터를 열고 다음과 같이 내용을 입력한다


hello.php

<html>

    <head>

        <title>PHP로 나만의 웹사이트 만들기</title>

        <meta charset="UTF-8">

        <meta name="viewport" content="width=device-width, initial-scale=1.0">

    </head>

    <body>

    <?php

        echo "Hello World<br>";

        echo "안녕하세요?<br>"

    ?>

    </body>

</html>




넷빈즈에서 PHP 파일을 웹브라우저로 확인하기

PHP파일은 아파치 웹서버에서 실행되므로 먼저 wamp 서버를 실행한다

넷빈즈 프로젝트에 작성된 파일명 위에서 마우스 우측 > Run 선택

지정된 웹브라우저가 실행되고 웹서버에 해당파일을 요청하여 웹브라우저에 표시되는지 확인한다



Sublime Text 3 다운로드/설치/실행 (필요하다면 설치)

File > Open Folder > 를 누르고 WAMP/www 폴더를 선택

에디더 왼쪽에 루트폴더가 표시되면 마우스 우측을 누르고 New File, New Folder등을 선택하여 작업을 할 수 있다



CodeIgniter 다운로드/압축해제/ 복사

Download https://codeigniter.com/download

WAMP/www/ 아래에 ciBoard 폴더를 생성한다 (임의의 폴더명)

CodeIgniter 압축해제 후 application폴더와 함께 있는 다른 폴더와 파일들을 모두 복사하여 WAMP/www/ciBoard/ 폴더 안에 붙여넣는다

웹브라우저에서 http://localhost/ciBoard 으로 접속하여 화면에 아래와 같은 환영 메시지가 출력되는지 확인한다

Welcome to CodeIgniter!


Posted by cwisky
PHP/CI Login2019. 1. 12. 13:00

CodeIgniter를 이용한 로그인 예제


https://www.webslesson.info/2016/10/codeigniter-simple-login-form-with-sessions.html


application/config/autoload.php 파일에서 다음과 같은 부분을 편집한다


autoload.php

$autoload['libraries'] = array('database', 'session');



.htaccess 파일 생성 및 편집

요청 URL 중간에 들어가는 index.php를 제거하기 위함

base_url 이 http://localhost/ciBoard 라면...


wamp/www/ciBoard/.htaccess

RewriteEngine On

RewriteBase /ciBoard/

RewriteCond %{REQUEST_FILENAME} !-f

RewriteCond %{REQUEST_FILENAME} !-d

RewriteRule ^(.*)$ index.php?/$1 [L]


데이터베이스 테이블 생성


users ( id, pass, name )



서버측 폼검증 참조 : https://codeigniter-kr.org/user_guide_2.1.0/libraries/form_validation.html



Login 콘트롤러 클래스 생성


application/controllers/Login.php 생성 (클래스이름과 파일이름은 동일해야 함)

콘트롤러 이름은 첫자를 대문자로 한다.

요청 URL에 콘트롤러 이름이 들어갈 때는 첫자를 소문자로 표시한다


예를 들어, 콘트롤러 이름이 Login 이라면 파일명은 Login.php 이어야 하고 요청 URL을 사용하여 Login 콘트롤러를 실행하려면, http://localhost/ciBoard/login/함수명/param1/param2/.... 와 같이 하면 된다 



콘트롤러 이름을 URL에서 사용할 때 전혀 다르게 지정하려는 경우

우선, 콘트롤러 클래스 이름과 파일명은 항상 동일해야 한다


application/config/routes.php 파일에 등록하고 사용하면 된다

$route['sample'] = 'SampleController';

위와 같이 지정한 경우, URL은 http://localhost/ciBoard/sample 으로 하여 SampleController를 요청할 수 있다



Login.php

<?php  

 defined('BASEPATH') OR exit('No direct script access allowed');


 class Login extends CI_Controller 

 {  

    public function __construct() {

         parent::__construct();

         $this->load->helper('url'); // redirect(), base_url() 사용하기 위함

    }


    function login_form()  

    {  

        $data['title'] = '로그인 폼';  

        $this->load->view("login_form", $data);  

    }  


    function login_validation()  

    {  

        $this->load->library('form_validation');  

        $this->form_validation->set_rules('id', '아이디', 'required');  // 필드명, 이용자가 읽기쉬운 이름, 검사규칙

        $this->form_validation->set_rules('pass', '암호', 'required');  

        if($this->form_validation->run())  //입력 데이터 유효성검사 통과

        {  

            $id = $this->input->post('id');  

            $pass = $this->input->post('pass');  

            //model function  

            $this->load->model('LoginModel');  

            if($this->LoginModel->login($id, $pass))  //로그인 성공

            {  

                $session_data = array(  

                          'id'=>$id

                );  

                $this->session->set_userdata($session_data);  

                redirect(base_url() . 'login/enter');  //enter 함수로 이동

            }  

            else  //로그인 실패

            {  

                 $this->session->set_flashdata('error', '로그인에 실패했습니다');  

                 redirect(base_url() . 'login/login_form');  

            }  

        }  

        else  //입력데이터 유효성검사 실패한 경우

        {  

            $this->session->set_flashdata('validation_error', '아이디와 암호를 입력해주세요');

            $this->login_form();    // 폼으로 이동

        }  

    }  


    function enter() {  // 로그인 성공시

        if($this->session->userdata('id') != '')  

        {  

            echo '<h2>환영합니다 - '.$this->session->userdata('id').'님</h2>';  

            echo '<label><a href="' .base_url(). 'login/logout">로그아웃</a></label>';  //로그아웃

        }  

        else  

        {  

            redirect(base_url() . 'login/login_form');   // 폼으로 이동

        }  

    }  


    function logout()  

    {  

        $this->session->unset_userdata('id');  

        redirect(base_url() . 'login/login_form');  // 폼으로 이동

    }  

 }



application/models/ 안에 LoginModel 클래스 생성

<?php  

 class LoginModel extends CI_Model  

 {  

     public function __construct() {

         parent::__construct();

         // autoload.php에 $autoload['libraries'] = array('database') 설정이 없다면 아래 행이 필요함

         $this->load->database(); // application/config/database.php에서 설정된 DB정보 사용됨

     }


    function login($id, $pass)  

    {  

        $this->db->where('id', $id);  

        $this->db->where('pass', $pass);  

        $result = $this->db->get('users');  //Query 실행

        //SELECT * FROM users WHERE id = '$id' AND pass = '$pass'  

        if ( $result->num_rows() > 0)  { return true; }

        else  { return false; }

        

        /* SQL문장을 직접 사용하는 예

        $sql = "SELECT id FROM users WHERE id=? AND pass=?";

        $result = $this->db->query($sql, array($id, $pass)); //Query 실행

        if ( $result->num_rows() > 0)  { return true; }

        else  { return false; }

         */

    }  

}  



application/views/  안에 뷰 생성

login_form.php

<!DOCTYPE html>  

 <html>  

 <head>  

      <title><?php echo $title; ?></title>  

 </head>  

 <body>  

      <div>  

        <h3>로그인 폼</h3>

           <br />

           <?php  

                echo '<label>'.$this->session->flashdata("validation_error").'</label>';  

           ?>  

           <form method="post" action="<?php echo base_url();?>/login/login_validation">  

                <div>  

                     <label>아이디</label>  

                     <input type="text" name="id"/>

                </div>  

                <div>  

                     <label>암 호</label>  

                     <input type="password" name="pass"/>

                </div>  

                <div>  

                     <button type="submit">로그인</button>  

                     <?php  

                          echo '<label>'.$this->session->flashdata("error").'</label>';  

                     ?>  

                </div>  

           </form>  

      </div>  

 </body>  

 </html>


Posted by cwisky
MySQL/Transaction2019. 1. 5. 18:57

MySQL Transaction


MySQL의 저장엔진

MyISAM : MySQL 5.1까지의 기본 저장엔진. Transaction 지원안됨

InnoDB : MySQL 5.5까지의 기본 저장엔진. Transaction 지원함. 

MySQL 5.5 이후에는 테이블을 디폴트로 설정으로 생성하면 저장엔진은 InnoDB 으로 설정된다



지원하는 모든 저장엔진 확인하기 ( MySQL8 )

SHOW ENGINES;




현재 생성된 테이블에 적용된 저장엔진의 종류 확인하기

SHOW CREATE TABLE [테이블 이름];


'emp', 

'CREATE TABLE `emp` (\n

  `id` int(11) NOT NULL AUTO_INCREMENT,\n

  `ename` varchar(255) COLLATE utf8_bin DEFAULT NULL,\n

  `parent_id` int(11) DEFAULT \'0\',\n

  PRIMARY KEY (`id`)\n

) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8 COLLATE=utf8_bin'



자동커밋 설정

SET AUtOCOMMIT=1;   // 각 SQL 문장 실행시 마다 즉시 영구반영

SET AUTOCOMMIT=0;   // 각 SQL 문장 실행시에 즉시 반영 안되고 COMMIT, ROLLBACK 명령시에 영구반영됨



MySQL은 디폴트로 SET AUTOCOMMIT=1; 상태이기 때문에 모든 문장마다 자동으로 COMMIT 이 실행되어 영구적으로 반영이 되고 있는 상태이다



현재의 AUTOCOMMIT 설정 상태 확인

SELECT @@AUTOCOMMIT;



MySQL에서 다수개의 SQL 문장으로 한개의 트랜잭션을 설정하려면 다음과 같이 할 수 있다


START TRANSACTION; 명령을 사용하는 경우

SET AUTOCOMMIT=1; 으로 설정된 디폴트 상태에서 아래처럼 특정 구간에서만 일시적인 트랜잭션을 설정할 수 있다

START TRANSACTION 이 실행되면,  SET AUTOCOMMIT=0 으로 자동설정되고 마지막에 COMMIT이나, ROLLBACK을 호출하면 다시 자동으로 SET AUTOCOMMIT=1 으로 설정된다

START TRANSACTION;      // 첫번째 트랜잭션

sql1, sql2, ...                    // 다수개의 SQL문장을 실행한다

COMMIT;                       // 혹은 ROLLBACK;                         // 첫번째 트랜잭션 완료


START TRANSACTION;     // 두번째 트랜잭션

sql1, sql2, ...                   // 다수개의 SQL문장을 실행한다

COMMIT;                       // 혹은 ROLLBACK;                         // 두번째 트랜잭션 완료

위의 방법을 사용하여 트랜잭선을 실행하고 나면(COMMIT, ROLLBACK 할 때) 다시 자동커밋으로 복원된다

그러므로 이후에는 SQL 한문장마다 커밋이 실행되어 실수로 COMMIT 깜박 잊더라도 모든 SQL 문장이 영구적으로 반영된다


START TRANSACTOIN; 명령을 사용하지 않는 경우

SETAUTOCOMMIT=0; 으로 설정을 변경하여 각 문장이 반영되지 않도록 한 경우

SET AUTOCOMMIT=0;     // 자동커밋을 해제한다

sql1 실행, sql2 실행, ...

COMMIT;                      // 혹은 ROLLBACK;                    // 첫번째 트랜잭션 완료

sql1 실행, sql2 실행, ...

COMMIT;                      // 혹은 ROLLBACK;                    // 두번째 트랜잭션 완료

SET AUTOCOMMIT=1;    // 원래의 자동커밋으로 복원한다

위의 방법을 사용할 때 주의할 점은 마지막에 SET AUTOCOMMIT=1; 부분을 설정하지 않으면 이후의 SQL문장이 반영되지 않기 때문에 작업을 끝내기 전에 반드시 COMMIT; 명령을 해야만 실수로 작업내용을 잃지 않게 된다

 


ROLLBACK으로 회복할 수 없는 작업(DDL)

ROLLBACK명령은 DML에 해당하는 SQL 문장을 취소하므로 아래와 같은 DDL에는 효과가 없으므로 주의해야 한다

CREATE ~

ALTER ~

DROP ~



START TRANSACTION 명령으로 트랜잭션을 설정하는 예

START TRANSACTION;                        // 트랜잭션 시작

DELETE FROM emp WHERE id != -100;   // 아이디가 음수가 아니면 모두 삭제, 다른 세션에서 emp 수정 불가

SELECT * FROM emp;                          // 모든 내용이 삭제된 것을 확인함

ROLLBACK;                                       // 트랜잭션 취소

SELECT * FROM emp;                          // 데이터가 다시 복원된 것을 확인함 



START TRANSACTION을 사용하지 않고 트랜잭션을 설정하는 예

SET AUTOCOMMIT=0;

DELETE FROM emp WHERE id != -100;

SELECT * FROM emp;

ROLLBACK;

SET  AUTOCOMMIT=1;

SELECT * FROM emp;



MySQL Workbench에서 트랜잭션 테스트

START TRANSACTION;


SELECT @num:=num, @title:=title, @regdate:=regdate, @hit:=hit

FROM bbs3 WHERE num=4;


DELETE FROM bbs3 WHERE num=4;


INSERT INTO delete_history VALUES(@num,@title,@regdate,NOW(),@hit);


SELECT * FROM bbs3;


ROLLBACK; # COMMIT;




PHP에서 MySQL 트랜잭션을 사용하는 예


MySQL에서 테이블 생성

CREATE TABLE bbs3 

(

   num INT AUTO_INCREMENT PRIMARY KEY,

   title VARCHAR(50) NOT NULL,

   regdate DATETIME,

   hit INT DEFAULT 0

);

INSERT INTO bbs3 VALUES

(NULL, '1번째 글', '2005-10-24 12:25:12', 0),

(NULL, '2번째 글', '2006-11-23 13:24:24', 0),

(NULL, '3번째 글', '2007-12-22 14:23:36', 0),

(NULL, '4번째 글', '2008-01-21 15:22:45', 0),

(NULL, '5번째 글', '2009-02-20 16:21:58', 0);


SELECT * FROM bbs3;


CREATE TABLE delete_history 

(

   num INT AUTO_INCREMENT PRIMARY KEY,

   title VARCHAR(50) NOT NULL,

   regdate DATETIME,

   deldate DATETIME,

   hit INT DEFAULT 0

);



transaction01.php

<!doctype html>

<html>

<head>

<meta charset="utf-8">

<title>트랜잭션 테스트</title>

</head>

<body>

<?php


  $host='fdb24.awardspace.net';

  $user='2915954_sampledb';

  $pass='2915954_sampledb_pwd';

  $db='2915954_sampledb';


  $conn = mysqli_connect($host,$user,$pass,$db);

  if ($conn->connect_error) {

    die("Connection failed: " . $conn->connect_error);

  }

  if($conn) {

    echo "Connection successful"; 

    echo "<br>";

  }

   

  mysqli_query($conn, "set session character_set_connection=utf8;");

  mysqli_query($conn, "set session character_set_results=utf8;");

  mysqli_query($conn, "set session character_set_client=utf8;");

  

  

  // 트랜잭션 시작 (MYSQLI_TRANS_START_READ_ONLY 도 가능)

  // 데이터 읽기만 할 때와 수정, 삭제할 때를 구분하여 지정함

  mysqli_begin_transaction($conn, MYSQLI_TRANS_START_READ_WRITE);

  

  $sql1 = "SELECT @num:=num, @title:=title, @regdate:=regdate, @hit:=hit

        FROM bbs3 WHERE num=4";

  $sql2 = "DELETE FROM bbs3 WHERE num=4";

  $sql3 = "INSERT INTO delete_history VALUES(@num,@title,@regdate,NOW(),@hit)";

  

  $result1 = mysqli_query($conn, $sql1);

  $result2 = mysqli_query($conn, $sql2);

  $result3 = mysqli_query($conn, $sql3);

  

  if( mysqli_num_rows($result1) > 0 && $result2 && $result3

  {

       mysqli_commit($conn);

       echo "트랜잭션 성공<br>";

  }else

  {       

       mysqli_rollback($conn);

       echo "트랜잭션 실패<br>";

  }

  

  // 위에서 실행된 트랜잭션이 정상적으로 작동했는지 확인해본다

  

  $result_set = mysqli_query($conn, "SELECT * FROM bbs3");

  

  if (mysqli_num_rows($result_set) > 0) {

      while($row = mysqli_fetch_assoc($result_set)) { 

        echo $row["num"]."<br>"; 

      }

  } else {

    echo "0 results";

  }


  mysqli_close($conn);

?>

</body>

</html>



트랜잭션과 LOCK IN SHARE MODE, FOR UPDATE

# SELECT 문장 오른쪽에 LOCK IN SHARE MODE, FOR UPDATE 를 사용할 수 있다

# LOCK IN SHARE MODE : 트랜잭션이 종료할 때까지 다른 세션에서 현재 행을 변경하지 못하고 읽기만 가능

# FOR UPDATE : 트랜잭션이 종료할 때까지 현재행을 다른 세션에서는 읽을 수도 없고 변경할 수도 없다


SELECT col FROM player WHERE id=1 LOCK IN SHARE MODE

SELECT col FROM player WHERE id=1 FOR UPDATE;


Posted by cwisky