728x90

http://link2me.tistory.com/1128 에서 작성했던 테이블을 부트스트랩 기반으로 변경을 해봤다.


=== index.php ===

<?php
require_once 'dbconnect.php'; // db접속 성공
require_once 'phpclass/dbClass.php';
require_once 'phpclass/boardiClass.php';

$c = new MySQLiDbClass();

$link_url = $_SERVER['PHP_SELF']; // 현재 실행중인 파일명 가져오기
$rowsPage = 12;

// 화면에 출력할 칼럼 발췌
$flddata ="uid,ItemName,Price,Quantity";
$where ="";
$curPage = isset($_GET['p']) ? $_GET['p'] : 1;
$result = $c->getDbArray('items',$where,$flddata,'',$rowsPage,$curPage);
$totalcnt = $c->getDbRows('items',$where);

$b = new boardiClass();
?>
<!DOCTYPE html>
<head>
    <meta charset="UTF-8" />
    <meta name="robots" content="noindex,nofollow"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no"/>
    <meta http-equiv="X-UA Compatible" control="IE=edge,chrome=1" />
    <link rel="stylesheet" href="bootstrap/css/bootstrap.min.css" />
    <link rel="stylesheet" type="text/css" href="css/table.css" />
    <script src="http://code.jquery.com/jquery.min.js" ></script>
    <script src="bootstrap/js/bootstrap.min.js"></script>
    <script type="text/javascript" src="js/display.js"></script>
</head>
<body>
<div class="container">
    <div class="table-responsive">
        <table class="table table-hover">
            <thead>
                <tr>
                    <th class="header" width="30"><input type="checkbox" id="checkall" /></th>
                    <th class="header" width="100">No</th>
                    <th class="header" width="250">아이템</th>
                    <th class="header" width="250">가격</th>
                    <th class="header" width="200">수량</th>
                </tr>
            </thead>
            <?php
                // 테이블 리스트
                $b->tablelistView_checkbox($result);
            ?>
            <td colspan="5" style="text-align:left;">
            <button type="button" class="btn btn-success btn-sm" id="optdel">선택삭제</button>
            <button type="button" class="btn btn-success btn-sm" id="optmp3">선택듣기</button>
            </td>
        </table>
       
        <a class="btn btn-default pull-right">글쓰기</a>       
        <?php $b->PageLinkView($link_url,$totalcnt,$rowsPage,$curPage);?>
    </div>
</div>

</body>
</html>


=== table.css ===

th.header {
    background:#F4F9FF;
    color:#444444;
    vertical-align:middle;
    border-bottom:1px solid #E6E6E6;
    font-size:1em;
    height:2em;
    }


=== display.js ===

$(function(){
    // class td1 중에서 짝수번째 요소만 선택해서 배경색을 지정색으로 표시
    // $(".tr1:odd").css("background-color","#F4F9FF"); // 부트스트랩 클래스에서 설정가능하므로 불필요

    $('.tr1').click(function() {
        var idx=$(this).attr('id');
    }).mouseover(function() {
        $(this).children('.td2').css({'backgroundColor':'#DCDCDC','cursor':'pointer'});
    }).mouseout(function() {
        $(this).children('.td2').css({'backgroundColor':'#FFFFFF','cursor':'default'});
    });

    // 전체 선택, 전체 해제
    $("#checkall").change(function () {
        $("input:checkbox").prop('checked', $(this).prop("checked"));
    });

    $('#optdel').click(function(){
        var chkdata = new Array();
        // 헤더에 있는 체크박스는 제외
        //$('.chkbox:checked').each(function() {
        $('input:checkbox[name="uid[]"]:checked').each(function() {
            // 체크한 아이템 배열로 저장
            chkdata.push($(this).val());
            //alert($(this).val());
        });
        if(chkdata.length != 0){ // 배열의 길이가 0 이 아니면
            alert(chkdata);
            $.post('ajax.php',{chkdata:chkdata}, function(response) {
                alert(response);
            });
        } else {
            alert('선택한 항목이 없습니다.');
        }
    });

    $('#optmp3').click(function(){
        var chkdata = new Array();
        $('input:checkbox[name="uid[]"]:checked').each(function() {
            // 체크한 아이템 배열로 저장
            chkdata.push($(this).val());
        });
        if(chkdata.length != 0){ // 배열의 길이가 0 이 아니면
            //alert(chkdata);
            $.post('ajax.php',{chkdata:chkdata}, function(response) {
                alert(response);
            });
        } else {
            alert('선택한 항목이 없습니다.');
        }
    });

});


=== boardiClass.php 에서 발췌 ===

페이지네이션 표시를 아래 그림처럼 해주기 위해서는

<div class="text-center">

<ul class="pagination">
  <li><a href="#">1</a></li>
  <li><a href="#">2</a></li>
  <li><a href="#">3</a></li>
  <li><a href="#">4</a></li>
  <li><a href="#">5</a></li>
</ul>

</div>

과 같이 해주면 된다.

http://www.w3schools.com/bootstrap/bootstrap_pagination.asp 를 테스트 해볼 수 있다.


    function PageLinkView($link_url,$totalcnt,$rowsPage,$curPage){
        echo '<div style="position:relative;vertical-align:top;padding-top:0;margin-top:0">';
            echo "<span style='position:absolute;top:10px;'>[전체 글수:".$totalcnt."]</span>";
            echo '<div class="text-center">';
            echo '<ul class="pagination">';
                $Info = $this->PageList($totalcnt,$rowsPage,$curPage,'');
                if($Info['current_block'] > 2){
                    echo "<li><a href='".$link_url."?p=1'>◀</a></li> ";
                }
                if($Info['current_block'] > 1){
                    echo "<li><a href='".$link_url."?p=".$Info['prev']."'>◁</a></li> ";
                }
                foreach($Info['current'] as $w) {
                    if($curPage == $w){
                        echo "<li><a href='".$link_url."?p=".$w."'><span style='color:red;'>".$w."</span></a></li> ";
                    } else {
                        echo "<li><a href='".$link_url."?p=".$w."'>".$w."</a></li> ";
                    }
                }
                if($Info['current_block'] < ($Info['total_block'])){
                    echo "<li><a href='".$link_url."?p=".$Info['next']."'>▷</a></li> ";
                }
                if($Info['current_block'] < ($Info['total_block']-1)){
                    echo "<li><a href='".$link_url."?p=".$Info['totalPage']."'>▶</a></li> ";
                }
            echo '</ul>';
            echo '</div>';
        echo '</div>';
    }


블로그 이미지

Link2Me

,
728x90

부트스트랩에서 사용하는 테이블은 모두 반응형(responsive) 테이블이다.

따라서 브라우저의 길이에 맞춰 테이블의 크기 및 내용 부분 또한 가변적으로 변하게 된다.

테이블 태그 부분에 class="table" 을 적용해주면 width 가 100%인 테이블이 생성된다.


<table class="table">

각 행의 아래에 테두리(border)가 있는 테이블이 만들어진다.


<table class="table table-bordered">

모든 셀에 테두리가 만들어 진다.


<table class="table table-striped">

한 줄 건너 배경색이 달라지는 스트라이프 형태의 테이블이 된다.


<table class="table table-hover">

테이블에 마우스를 올렸을 때 마우스 커서가 있는 행이 다른 색으로 변한다.


<table class="table table-condensed">

셀 패딩이 반으로 감소돼 작은 크기의 테이블이 된다.


테이블에 적용된 클래스 선택자의 경우 혼합해서 사용 가능하다.

<table class="table table-bordered table-hover">


테이블 행 또는 셀에 색상 지정

클래스 설명
.active 특정 행이나 셀에 마우스 오버 색상 적용
색상은 회색
.success 성공 또는 긍정적인 작업 표시
색상은 연두색 계열 #d0e9c6
.info

중립적인 정보 변경이나 작업 표시

.warning 주의를 필요로 하는 경고를 표시
색상은 겨자색 계열 #faf2cc
.danger 위험 또는 잠재적으로 부정적인 작업 표시
색상은 붉은색 계열 #ebcccc


<div class="table-responsive"></div>

부트스트랩에서는 화면 폭이 좁을 때(768px 이하) 하단에 스크롤바가 나타나며 수평으로 스크롤해서 테이블을 볼 수 있게 했다. <table> 태그 외곽에 <div> 태그로 감싸서 table-responsive 클래스를 추가하면 반응형 테이블로 사용할 수 있다.

블로그 이미지

Link2Me

,
728x90

부트스트랩으로 버튼을 꾸미는 방법



기본 버튼과 부트스트랩 버튼의 차이는 class="btn btn-default" 과 같이 부트스트랩에서 제공하는 class 속성을 추가해주는 것이다.


<div>
    <button type="button">기본</button>
    <button type="button" class="btn btn-default">기본</button>
    <button type="button" class="btn btn-primary">Primary</button>
    <button type="button" class="btn btn-success">성공</button>
    <button type="button" class="btn btn-info">정보</button>
    <button type="button" class="btn btn-warning">경고</button>
    <button type="button" class="btn btn-danger">위험</button>
</div>
<div>
    <button type="button">기본</button>
    <button type="button" class="btn btn-default btn-sm">기본</button>
    <button type="button" class="btn btn-primary btn-sm">Primary</button>
    <button type="button" class="btn btn-success btn-sm">성공</button>
    <button type="button" class="btn btn-info btn-sm">정보</button>
    <button type="button" class="btn btn-warning btn-sm">경고</button>
    <button type="button" class="btn btn-danger btn-sm">위험</button>
</div>
<div>
    <button type="button">기본</button>
    <button type="button" class="btn btn-default btn-xs">기본</button>
    <button type="button" class="btn btn-primary btn-xs">Primary</button>
    <button type="button" class="btn btn-success btn-xs">성공</button>
    <button type="button" class="btn btn-info btn-xs">정보</button>
    <button type="button" class="btn btn-warning btn-xs">경고</button>
    <button type="button" class="btn btn-danger btn-xs">위험</button>
</div>
<div>
    <button type="button">기본</button>
    <button type="button" class="btn btn-default btn-lg">기본</button>
    <button type="button" class="btn btn-primary btn-lg">Primary</button>
    <button type="button" class="btn btn-success btn-lg">성공</button>
    <button type="button" class="btn btn-info btn-lg">정보</button>
    <button type="button" class="btn btn-warning btn-lg">경고</button>
    <button type="button" class="btn btn-danger btn-lg">위험</button>
</div>


블로그 이미지

Link2Me

,
728x90

DB 암호를 강력하게 만들기 위해서 SHA384를 적용하는 코드를 작성해봤다.


<?php
$userpw = "admin1234"; // 사용자 입력 암호
function createSalt()
{
    $text = md5(uniqid(rand(), TRUE));
    return substr($text, 0, 34);
}

$salt = createSalt(); // 랜덤하게 생성
$password = hash('sha384', $userpw.$salt);
echo $salt.'<br />';
echo $password.'<br />';
echo strlen($password);
?>


DB 패스워드를 다른 키($salt)와 조합하여 저장하도록 하는 로직이다.

여기서 $salt 값이 계속 변하므로 이 키값도 같이 DB에 저장하지 않으면 다음번에 로그인할 때 문제가 생긴다.

따라서 테이블에 key 값을 저장하는 테이블도 하나 추가하는게 좋다.

블로그 이미지

Link2Me

,
728x90

자바스크립트로 하면 여러줄을 적어줘야 하는데 jQuery 로 하면 심플해진다.

// Assumes element with id='button'
var button = document.getElementById('button');

button.onclick = function() {
    var mydiv = document.getElementById('tabName');
    if (mydiv.style.display === 'block' || mydiv.style.display === '') {
        mydiv.style.display = 'none';
    }
    else {
        mydiv.style.display = 'block';
    }
};

$("#button").click(function() {
    // assumes element with id='button'
    $("#tabName").toggle();
});


메뉴만들기

열심히 이 자료 저자료 테스트해보면서 이해하고 내것으로 만들어가고 있는 중이다.

아래 코드를 연습한 소스코드 파일 첨부한다.

이미지 파일은 http://blog.naver.com/hyoyeol/70177051041 블로그에 올려진 파일 이미지 파일을 활용했다.

하지만 코드 내용은 완전 다르다.


topmenu-01.zip

=== index.php ===

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="robots" content="noindex,nofollow"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>메뉴만들기</title>
    <link rel="stylesheet" href="css/bootstyle.css" />
    <link rel="stylesheet" href="css/topmenu.css" />
    <link href="bootstrap/css/bootstrap.min.css" rel="stylesheet">
    <script src="http://code.jquery.com/jquery.min.js" ></script>
    <script src="bootstrap/js/bootstrap.min.js"></script>
    <script type="text/javascript">
        var currentName = null;
        $(document).ready(function(){
            tabSetting(); // 탭 초기화 및 설정
        });
       
        function tabSetting() {
            $('.tabPage').hide();
            $('.topmenu a').on('click', function() {
                var tabName = $(this).attr('href');
                if(currentName != tabName){
                    $('.tabPage').hide();
                    currentName = tabName;
                }
                $(tabName).toggle();
            });
        }
    </script>
</head>
<body>
<header>
     <nav class="navbar navbar-fixed-top navbar-full navbar-light">
        <div class="topmenu">
            <a href="#home">Home</a>
            <a href="#tab01">News</a>
            <a href="#tab02">Contact</a>
            <a href="#tab03">About</a>
            <a href="#tab04">Support</a>
            <a href="#tab05">Blog</a>
            <a href="#tools">Tools</a>
            <a href="#base">Base</a>
            <a href="#custom">Custom</a>
            <a href="#more">More</a>
            <a href="#logo">Logo</a>
            <a href="#friends">Friends</a>
            <a href="#partners">Partners</a>
            <a href="#people">People</a>
            <a href="#work">Work</a>
        </div>
     </nav>
</header>
<main class="container-fluid">
     <div id="contents">
        <div id="tab01" class="tabPage">
            <img src="./images/img_01.jpg">
        </div>
        <div id="tab02" class="tabPage">
            <img src="./images/img_02.jpg">
        </div>
        <div id="tab03" class="tabPage">
            <img src="./images/img_03.jpg">
        </div>
        <div id="tab04" class="tabPage">
            <img src="./images/img_04.jpg">
        </div>
        <div id="tab05" class="tabPage">
            <img src="./images/img_05.jpg">
        </div>
    </div>

</main>

</body>
</html>


/// nav 설명

<nav class="navbar navbar-fixed-top navbar-full navbar-light">

.navbar-fixed-top : 상단에 고정

.navbar-fixed-bottom : 하단에 고정


/// 설명 : 화면 부드럽게 나오고 사라지게 하기

$(tabName).toggle(); 는 화면이 부드럽게 나오고 부드럽게 사라지지 않는다.

화면을 부드럽게 나오고 부드럽게 사라지게 하고 싶으면

$(element).is(":visible"); // 화면이 보이는 상태인지 체크

를 사용해서 코드를 변경해주면 된다.


if($(tabName).is(":visible")){
    $(tabName).slideUp();
}else{
    $(tabName).slideDown();
}



=== topmenu.css ===

charset "utf-8";
@import url(http://fonts.googleapis.com/earlyaccess/nanumgothic.css);

body, div, ul, li, table, tr, td, th{margin:0px; padding:0px;}

ul, li{list-style:none;}

body {
    font-family: NanumGothic, '나눔고딕', NanumGothicWeb, "Malgun Gothic",Gulim,sans-serif;
    background: #ddd;
    font-size:10px;
}

div.topmenu {
    border: 1px solid #ccc;
    background-color: #f1f1f1;
    margin:auto;
    overflow: auto;
    white-space: nowrap;
}

div.topmenu a {
    display: inline-block; /* 자동으로 줄바꿈되지 않고 크기를 지정할 수 있음 */
    color: black;
    text-align: center;
    padding: 14px;
    text-decoration: none;
    transition: 0.1s;
}

div.topmenu a:hover {
    background-color: #ddd;
    color:#0000ff;
    cursor:pointer;
    font-weight:bold;
}

/*컨텐츠*/
#contents{
    width:900px;
    margin:auto;
}

#contents div{
    margin:0 0px;
}

/* 화면 해상도에 따른 글자 크기 변경 */
@media only screen and (max-width: 768px) {
    div.topmenu a {
        padding: 12px;
    }
}
@media only screen and (min-width: 768px) and (max-width: 1024px) {
    div.topmenu a {
        padding: 13px;
    }
}
@media only screen and (min-width: 1025px) {
        body { background-color: blue; }
        h1 { color: white; }
}

블로그 이미지

Link2Me

,
728x90

foreach문은 배열에서만 동작한다.
키(key)와 값(value)로 분리, 변수로 지정 가능하다.
배열이 아니면 php코드 내에 오류메시지를 출력하고, 다차원 배열이나 중첩도 가능하다

<?php
$A = array (
    '2017-01-25' => '가가가',
    '2017-01-26' => '나나나'
);

// 배열에만 동작하는 반복문 foreach문
foreach($A as $key => $value){
    if($key !== date("Y-m-d")) continue;
    echo $value.'<br />';
}

$colors = array("red","green","blue","yellow");
foreach($colors as $key => $value){
    //echo $value.'<br />';
    echo $value.'-'.$colors[1].'<br />';
}


$numItems = count($colors); // 배열 개수 카운트
$i = 0;
foreach($colors as $key=>$value) {
  if(++$i === $numItems) {
    echo "last index!";
  }
}

?>


// 중첩 foreach 문

foreach($samplearr as $key => $item){
   echo $key;
    foreach($item as $detail){
       echo $detail['value1'] . " " . $detail['value2']
     }
 }

'Web 프로그램 > PHP 문법' 카테고리의 다른 글

HTML Entity List (특수문자 용어)  (0) 2021.11.27
[PHP] PHP 문자열 찾기  (0) 2017.11.14
PHP Class 개념 이해 ★★  (0) 2017.01.10
PHP isset 과 empty 설명  (1) 2016.04.27
PHP 대체 문법  (0) 2016.04.05
블로그 이미지

Link2Me

,
728x90

설치환경

AutoSet9 on Windows10 64bit


설치파일 구하기

https://xdebug.org/download.php  에서 AutoSet9 설치된 버전을 다운로드 한다.


php.ini 환경설정 파일에서 아래 코드를 추가한다.


[xdebug]
zend_extension = "C:\AutoSet9\server\bin\ext\php_xdebug-2.5.0-5.6-vc11-nts-x86_64.dll"
;zend_extension = "C:\AutoSet9\server\bin\ext\php_xdebug-2.5.0-5.6-vc11-nts.dll"


zend_extension 의 윗줄은 64bit 용으로, 아래 줄은 32bit 용으로 받은 거다.

윗줄로 설정을 했을 때는 에러없이 동작한다.


phpstorm과 xdebug 연동하기 URL http://codeigniter-kr.org/bbs/view/tip?idx=8346 에 예시가 잘 나와있다.

breaking point 지정해서 하는 걸 코드를 하나 선택해서 동작 여부를 테스트해봐야겠다.


https://opentutorials.org/course/692/3758 동영상도 보면서 파악을 해봐야겠다.

블로그 이미지

Link2Me

,
728x90

'도깨비' 라는 제목 자체가 어릴적 추억이 떠올라 보게 된 드라마다.

어릴적 산골 고향에 살 때 밤에 물을 대기 위해 논에 나가면 도깨비 불이라고 해서 반딧불처럼 돌아다니는 기억이 새록새록 떠오른다.

타다남은 빗자루가 도깨비가 된다는 둥 이런 저런 어릴적 얘기...


태어나서 죽는 생이 4번이라는 건 어디에서 나온 것일까 하는 궁금증부터 생긴다.

인도영화를 보게되며 힌두교에서 결혼식을 할 때 7번 불 주위를 도는 것은 7번 태어나서 죽어도 당신과 결혼하고 싶다는 의미라고 한다.


도깨비 드라마는

불멸의 삶을 사는 도깨비, 귀신을 보는 소녀, 삼신할머니, 인간에 빙의된 신, 자살로 자신의 생을 마감하면 저승사자가 된다. 저승사자와 입맞춤을 하면 본인의 전생을 알게 되며, 저승사자와 손을 잡으면 저승사자 본인의 전생이 보인다는 설정으로 소설을 쓴 작가의 창작 상상력에 감탄했다.

찾아보니 이 드라마를 쓴 이은숙 작가다. 드라마를 거의 안봐서 이은숙 작가가 대단한 분인지도 몰랐다.


전생에 큰 죄를 짓고 스스로 생을 버린 죄로 저승사자가 된다.

스스로 생을 버린자를 저승사자로 눈뜨게 하여 이름도 없고 기억도 없게 살아가며 수많은 죽음을 인도하며, 산자도 죽은자도 아닌 존재로 산다. 우리가 포기한 것들이, 이름이, 우리가 버린 생이 갖고 싶어지는 것은 아닐까? 그렇게 생이 간절해지면 우리의 벌이 끝나는 것은 아닐까? 망자들의 마지막을 잘 배웅하며 속죄하고 살아.  신이 우리에게 바라는 것은 자신을 용서하여 생이 간절함을 깨닫는 것일테니...


인간에겐 4번의 생이 있다는데 저는 몇번째 생이예요?

너는 첫번째 생이다.

다행이다. 아직 3번 남았다.


뱃속에서 죽을 운명의 지은탁은 도깨비의 도움으로 태어났고 도깨비 신부가 될 운명이었다.

9살 되던 해에 저승사자가 찾아오고 19살에도 저승사자가 찾아온다.

수없이 찾아오는 죽음의 기회에서 도깨비는 은탁을 구하면서 알 수 없는 전개가 계속된다.

그리고 29살에 생을 마감한다. 브레이크가 풀려서 언덕에서 내려오는 트럭을 막아서 희생으로 어린애를 구하면서 생을 마감한다.

지은탁은 이승의 기억을 지우는 망각의 차를 마시지 않겠다고 하며 저승으로 가며 빨리 돌아오겠다고 한다.

한명의 희생으로 많은 사람의 생명을 살린 덕을 쌓아서인지 지은탁은 10년뒤에 다시 태어난 거 같고 전생의 기억을 지우지 않아서 퀘벡에서 다시 만날 수 있었다.



멋진 퀘벡의 도시 전경에서 도깨비와 지은탁은 다시 만나면서 드라마가 엔딩된다.


공유의 연기력과 지은탁의 연기력이 좋아서, 기분이 즐거워서, 드라마가 탄탄해서, 재미있어서 계속 본 드라마다.

저승사자가 어떻게 되는지에 대한 설정이 마음 깊이 와닿는다.

생을 어떻게 살아야 하는지 되새겨 보게 한다.

불멸의 삶을 사는 자는 신, 삼신할머니, 도깨비다. 이런 삶을 살면 하고 싶은 걸 이루며 많은 걸 이룰 수 있어 좋기도 할 거 같다.

'드라마' 카테고리의 다른 글

명불허전 - 조선제일침 허임  (1) 2017.08.27
블로그 이미지

Link2Me

,
728x90

Eclipse 는 한번 설치하고 나면 PC를 변경해도 설치된 디렉토리 파일을 그대로 복사해서 사용하면 된다.

설치할 폴더가 C 드라이브에 설정된 것인지 D 드라이브에 설치된 것인지 확인하는 방법이다.



설정된 경로를 변경하고 싶다면...



workspace 경로를 변경해주면 된다.

블로그 이미지

Link2Me

,
728x90

Aptana Studio 3 에서 선택한 파일을 실행하는 테스트를 하려고 한다.

외부 서버 설정 등을 해서 해당 파일을 찾아서 실행하는 것이 생각보다 쉽지 않다.




위와 같이 설정을 하고 파일을 선택해서 실행하니까 해당 파일이 실행이 바로 바로 된다.

EditPlus 로 코딩을 하는 것은 에러가 날 확률도 높은데다가 매번 파일명을 일일이 지정하는게 너무 너무 귀찮아서 이런 편리한 방법을 좀 찾고 있었다.



위 화면처럼 파일 선택하고 실행하면 바로 해당 파일이 Firefox 브라우저에서 실행되어 결과를 보여준다.


http://localhost/workspace 로 경로를 지정한 이유는 이미 http://localhost 디렉토리 하단에 여러 디렉토리를 만들어서 테스트를 하던 상태라서 Aptana Studio 3 에서 workspace 경로를 localhost 경로로 지정했더니 에러가 발생해서다.

하지만 처음부터 Aptana Studio 3를 설치하고 테스트를 했다면 이런 문제는 없었을 것이다.



http://localhost/workspace 를 바로 http://localhost 로 만드는 방법은

http.conf 환경설정에서 경로를 변경하면 된다.

DocumentRoot "C:/AutoSet9/public_html"
<Directory "C:/AutoSet9/public_html">
    Options FollowSymLinks
    AllowOverride All
    Require all granted
</Directory>

를 찾아서

DocumentRoot "C:/AutoSet9/public_html/workspace"
<Directory "C:/AutoSet9/public_html/workspace">
    Options FollowSymLinks
    AllowOverride All
    Require all granted
</Directory>
로 변경하고 Apache를 재시작하면 홈디렉토리 경로는 변경된다.


이렇게 변경하면 다시 Run Configuration 을 다시 설정해줘야 한다.


이렇게 변경해주면 문제없이 동작된다.


블로그 이미지

Link2Me

,
728x90

Pivot 을 엑셀에서 일일이 매번 지정하려니까 너무 귀찮아서 피벗 VBA 를 아예 만들었다.

어떻게 만드는지 감이 오지 않으면 매크로를 실행해서 만들어진 코드를 분석하면 쉽게 이해할 수 있다.


Sub pivot_make()
    Dim endRow As Long
    Dim CurrentPosition
    Dim C As Range
    Dim rngAll As Range
    Dim wSheet As Worksheet
    Dim wkSht As Worksheet

    On Error Resume Next
    Set wkSht = ThisWorkbook.Worksheets("B_Sheet")
    If Err.Number = 0 Then
        ' Application.DisplayAlerts = False
        ' Worksheets("B_Sheet").Delete
        ' Application.DisplayAlerts = True
    Else
    Worksheets("A_Sheet").Activate
    Worksheets("A_Sheet").Copy after:=Worksheets("A_Sheet")
    ActiveSheet.Name = "B_Sheet"
    End If

    Sheets("B_Sheet").Select
    endRow = Cells(Rows.Count, "A").End(3).Row '// 셀의 마지막 위치가 계속 변하므로

    Cells(1, 1).Select
    If Cells(3, 1) <> "등록일" Then
        Selection.EntireRow.Insert
        Selection.EntireRow.Insert
    End If
    Cells(3, 1).Select
    ActiveSheet.AutoFilterMode = False
    If ActiveSheet.AutoFilterMode = False Then
        Selection.AutoFilter
    End If
    Cells(3, "C").Select

    ActiveSheet.AutoFilter.Sort.SortFields.Clear
    ActiveSheet.AutoFilter.Sort.SortFields.Add Key:= _
    Range("C3:C" & endRow), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
    With ActiveSheet.AutoFilter.Sort
        .Header = xlYes
        .MatchCase = False
        .Orientation = xlTopToBottom
        .SortMethod = xlPinYin
        .Apply
    End With
    ActiveCell.Select
    Cells(3, "C").Select

    '###### 분류 작업 #######
    Set rngAll = Range([C3], Cells(Rows.Count, "C").End(3))

    Application.ScreenUpdating = False
    rngAll.Replace "회사", vbNullString
    rngAll.Offset(0, 1).Replace "기술부", vbNullString

    '##### 피벗테이블 생성 #####
    Sheets("B_Sheet").Select

    Application.DisplayAlerts = False
    On Error Resume Next
    Sheets("Pivot_New").Delete '// 기존 피벗테이블 삭제
    Sheets.Add(after:=Sheets(8)).Name = "Pivot_New" '새로운 피벗시트를 생성

    Set rngData = Sheets("B_Sheet").Range("A3").CurrentRegion
    Set rngB = ActiveWorkbook.Worksheets("Pivot_New").Range("A3")

    ActiveWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:=rngData, _
    Version:=xlPivotTableVersion14).CreatePivotTable TableDestination:=rngB, _
    TableName:="PVR", DefaultVersion:=xlPivotTableVersion14

    '// 보고서 필터
    With ActiveSheet.PivotTables("PVR").PivotFields("부서")
        .Orientation = xlPageField
        .Position = 1
    End With
    With ActiveSheet.PivotTables("PVR").PivotFields("지역")
        .Orientation = xlPageField
        .Position = 2
    End With

    '// X축
    With ActiveSheet.PivotTables("PVR").PivotFields("분류")
        .Orientation = xlRowField
        .Position = 1
    End With
    With ActiveSheet.PivotTables("PVR").PivotFields("고객")
        .Orientation = xlRowField
        .Position = 2
    End With
    ActiveSheet.PivotTables("PVR").PivotFields("분류").LayoutForm = xlTabular
    ActiveSheet.PivotTables("PVR").PivotFields("고객").LayoutForm = xlTabular

    '// Y축
    With ActiveSheet.PivotTables("PVR").PivotFields("팀")
        .Orientation = xlColumnField
        .Position = 1
    End With

    '// 화면에 표시될 값(결과)
    ActiveSheet.PivotTables("PVR").AddDataField ActiveSheet.PivotTables( _
    "PVR").PivotFields("고객수"), "합계 : 고객수", xlSum

    '// 화면에서 보이지 않게 처리
    ActiveSheet.PivotTables("PVR").PivotFields("지역").CurrentPage = "(All)"
    With ActiveSheet.PivotTables("PVR").PivotFields("지역")
        .PivotItems("서울").Visible = False
        .PivotItems("대구").Visible = False
        .PivotItems("부산").Visible = False
        .PivotItems("전남").Visible = False
        .PivotItems("전북").Visible = False
        .PivotItems("충남").Visible = False
        .PivotItems("충북").Visible = False
        .PivotItems("제주").Visible = False
        .PivotItems("강원").Visible = False
    End With

    ActiveSheet.PivotTables("PVR").PivotFields("담당").EnableMultiplePageItems = True

    MsgBox "피벗 생성완료"
End Sub



블로그 이미지

Link2Me

,
728x90

PHP 코드를 입력하고 제대로 동작하는지 테스트를 해보자.


<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script>
    window.open("http://google.co.kr");
</script>
</head>   
<body>
   
</body>
</html>


이 코드는 PHP는 한줄도 없다. 네이버지식인에 올라온 질문을 보고서 그대로 연습해서 작성한 코드다.

코드 자동완성 기능 연습을 했다.


이 코드를 웹서버에서 제대로 실행되는지 테스트 해보자.


Run As 를 한번만 하고 나면 다음부터는 버튼만 누르면 이 파일이 실행된다.


테스트를 하고 보니 eclipse 에서 Android 폰 개발할 때와 같은 개념으로 동작한다.

단지 환경만 Web Server 환경으로 변경되었다는 것만 다르다.


연습으로 실행을 한 것이라서 ex-01.php 파일로 생성했지만

실제로는 디렉토리 단위로 프로젝트를 생성한다고 가정해야 하므로

index.php 파일이 있어야 하고 연관된 파일들을 생성해서 코드를 작성해야 한다.


그런 환경이라고 가정하면...



처럼 생성해야 맞다.


PHP Web Page 에 프로젝트 단위로 계속 추가되고, 프로젝트 단위로 inital Script 를 설정하면 된다.


블로그 이미지

Link2Me

,
728x90

Aptan Studio 3 기본 설치와 workspace 경로를 변경했다.

이제 본격적으로 PHP Project 를  생성해보려고 한다.


프로젝트 그룹 생성



생성된 그룹에 파일 추가




PHP Interpreters 설정



내장된 Web 서버 설정



Web Server 를 설정해보자.



Base URL : 마지막에 / 는 절대 붙이지 말라. 테스트 해보니 붙이면 안된다.



Aptana 라는 이름으로는 workspace 경로까지 포함해서 추가했다.




화면 글꼴 변경

화면 글꼴이 너무 작아보여서 16으로 수정했다.



PHP Server 환경 설정




기본적인 환경설정은 끝났다.


블로그 이미지

Link2Me

,
728x90

Aptana 를 설치하고 나서 보니 AutoSet9 Document Root 디렉토리 밖에 있다보니 테스트를 하는데 애로사항이 계속 발생한다.

그래서 Workspace를 변경했다.




httpd.conf 파일에 설정된

DocumentRoot "C:/AutoSet9/public_html"

하위 디렉토리에 workspace를 변경했다.


다음에는 실제 PHP Project 를 생성하고 환경설정하는 법에 대해 기술하련다.


블로그 이미지

Link2Me

,
728x90

윈도우버전 Aptana Studio 3.6.1 에서는 아래 과정은 시도하지 않아도 된다는 걸 확인했다.


aptana eclipse plugin installation

http://www.aptana.com/products/studio3/success_plugin.html 에서

http://download.aptana.com/studio3/plugin/install 를 복사(Ctrl + C) 한다.



최신버전이 설치되었다고 나오면서 설치가 안된다.

유투브 동영상 보면서 이런 과정으로 설치된다는 걸 확인해봤다.

블로그 이미지

Link2Me

,
728x90

책을 다시 보면서 기본 지식을 다시 정리해보고 있다.

하다가 막히면 다시 원점에서 흘려버린 걸 다시 되짚어 가면서 시작하는 것이 도움이 될 수도 있기 때문이다.


모든 언어의 기본은 데이터 타입을 파악하는 것부터 시작한다.

자바스크립트에서는 기본 타입을 제외한 모든 값은 객체다.


자바스크립트는 변수를 선언할 때 var 라는 한가지 키워드를 사용한다.

 - 선언부에 Data Type을 기재하지 않는다.

 - var 선언문이 위치한 영역에 따라 전역/지역변수 결정

 - var 를 사용하지 않으면 전역(global)변수로 선언

var 로 변수를 선언하기 때문에 데이터 타입이 무엇인지 몰라서 헤매는 경우도 생기더라.

+ 는 숫자연산과 문자열 연결에 사용되므로 잘못된 결과가 나올 수 있으니 주의해서 봐야 한다.


숫자

 다른 언어와 달리 하나의 숫자형만 존재한다.

 모든 숫자를 64비트 부동 소수점 형태로 저장한다.

 모든 숫자를 실수로 처리하므로, 나눗셈 연산을 할 때는 주의해야 한다.

  ex) 1/2 = 0.5

 정수만 구하고 싶다면 Math.floor() 메서드를 사용한다.

 + 연산자는 숫자일 경우에는 더하기 연산이 수행된다.

 Number 형 변환 실패 결과는 NaN  

  ex) "abc" - 0 = NaN

 문자열

 작은 따옴표나 큰 따옴표로 생성한다.

 문자열은 문자 배열처럼 인덱스를 이용해서 접근할 수 있다.

 + 연산자는 문자열 연결 연산을 수행한다.

 boolean

 자바스크립트는 true 와 false를 나타내는 boolean 타입을 가진다.

 undefined

 자바스크립트에서 '값이 비어있음'을 나타낸다.

 typeof 연산자 결과는 undefined 이다. 즉, Data Type 이 정해지지 않은 타입

 null

 자바스크립트에서 '값이 비어있음'을 나타낸다.

 typeof 연산자 결과는 object 이다. null 이 아니다. 아무것도 참조하지 않는 값이다.

 객체

 자바스크립트 객체는 key:value 형태의 property들은 저장하는 컨테이너다.

  - 객체 내에서 변수는 속성(property)이라 부른다.

  - 객체 내에서 함수는 메서드(method)라 부른다.

  - 이름은 key라고 불린다.

 객체는 여러 개의 property들을 포함할 수 있다.

 객체 생성

   - 생성자 문법을 이용하여 객체 생성 :
     new 연산자 사용 var hotel = new Object(); // 객체를 위한 공간 생성

     this 키워드 -> window 객체를 나타냄

   - 객체 생성자 표기법을 이용하여 객체를 생성

 객체 property 삭제는 delete 연산자를 이용해서 삭제할 수 있지만 객체 자체는 삭제 못한다.

 상속이란 기존의 생성자 함수나 객체를 기반으로 새로운 생성자 함수나 객체를 쉽게 만드는 것

 비교

 기본 타입은 동등 연산자(==)를 이용해서 비교할 때 값을 비교한다.

 동등 연산자(==)는 피연산자의 타입이 다를 경우 타입 변환을 거친 다음 비교한다.
 참조 타입인 객체 비교는 참조값이 같아야 true 가 된다.

 일치 연산자(===)는 피연산자의 타입이 다를 경우 타입을 변경하지 않고 비교한다.

 배열

 자바스크립트에서 배열은 크기를 지정하지 않아도 된다.
 배열 리터럴은 []를 사용한다.
 동적으로 배열 원소를 추가할 수 있다.
 length 프로퍼티는 배열 내에서 가장 큰 인덱스에 1을 더한 값이다.

 실제 메모리는 length 크기처럼 할당되지 않는다.

 push() 메서드는 인수로 넘어온 항목을 배열의 끝에 추가한다.

 arr.length = 5;

 arr.push('english');

 생성자 함수로 배열을 생성할 때 new 연산자를 사용한다.

 delete arr[3]; // 배열 요소 삭제하라는 의미지만 실제는 해당 요소값을 undefined로 설정한다.


 배열도 객체이므로

  for(var i in arr) {

    console.log(i, arr[i]);

  }

  문을 사용해서 배열 내의 모든 프로퍼티를 열거할 수 있다. --> 불필요한 프로퍼티가 출력될 수 있다.

  for(var i=0; i<arr.length; i++) {

   console.log(i, arr[i]);

  }

  문을 사용하면 불필요한 프로퍼티가 출력되지 않는다.

 함수

 function 키워드로 함수를 선언한다.

 선언부에 Return Type 을 기재하지 않는다.

 자바스크립트에서는 함수도 하나의 값처럼 취급한다.

 함수도 숫자나 문자열처럼 변수에 할당하는 것이 가능하다.

 매개변수로 넘기는 값에 변수 타입을 기술하지 않는다.

 자바스크립트 함수 표현식에서 함수 이름은 꼭 붙이지 않아도 된다. (익명함수)

 함수 내부에서 정의된 매개변수는 var를 사용하여 정의한다.

 함수에 정의된 인자가 3개라고 가정하자.

   - 2개는 정의하나 나머지 하나를 정의하지 않으면 undefined 값이 할당된다.

   - 정의된 개수보다 많게 4개를 정의하면, 초과된 인수는 무시된다.


블로그 이미지

Link2Me

,
728x90

구글 아이디로 로그인하는 걸 해보려고 구글링해서 몇가지를 테스트해봤는데 이것은 동작된다.


https://www.sanwebe.com/2012/11/login-with-google-api-php

에 가면 파일을 데모를 실행해보고 다운로드 할 수 있다.


테이블 스키마는 변경해야 한다.

사진 경로 길이가 너무 길어서 위 사이트에 나온 스키마 구조로는 에러가 발생한다.

CREATE TABLE IF NOT EXISTS `google_users` (
  `uid` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `google_id` varchar(60) NOT NULL,
  `google_name` varchar(60) NOT NULL,
  `google_email` varchar(60) NOT NULL,
  `google_link` varchar(150) NOT NULL,
  `google_picture_link` varchar(200) NOT NULL,
  PRIMARY KEY (`uid`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;


테이블 스키마는 회원테이블 정보에 가져올 정보를 표시하는 것이므로 굳이 이 테이블이 아니어도 된다.

이 테이블은 구글 회원정보를 가져온다는 걸 보여주는 것이라고 보면 된다.


첨부파일을 받으면 index.php 파일 내용을 수정해야 한다.

// https://console.developers.google.com/ 에서 client ID and secret 생성
$client_id = 'xxxxxxxxxxxxxxxxxx';  // 구글에서 생성한 id 입력
$client_secret = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxx'; // 비밀키 입력
$redirect_uri = 'http://abc.com/oauth/google/'; // 본인 도메인으로 수정하세요


$redirect_uri = 'http://localhost/oauth/google/';

localhost 로 설정하면 에러가 발생한다.

Error: redirect_uri_mismatch

The redirect URI in the request, http://localhost/oauth/google/, does not match the ones authorized for the OAuth client.

그러므로 반드시 도메인명을 기록해야 한다. (IP주소 입력한 것은 테스트 안해봤음)

Google OAuth 2.0 Client API Keys 생성방법

https://console.developers.google.com/

https://www.sanwebe.com/2012/10/creating-google-oauth-api-key 에도 설명은 나오고

http://phppot.com/php/php-google-oauth-login/ 에도 나온다.

내가 등록을 참조한 곳은 http://phppot.com/php/php-google-oauth-login/ 이다.

하지만 이 사이트에서 제공하는 소스로는 연동이 잘 안되었다.


생성된 결과 화면이다.


테스트에 사용했던 파일입니다.

MySQLi 가 아닌 MySQL 연동 테스트 입니다. MySQLi 연동방식은 블로그에 올려진 걸 찾아서 변경하면 됩니다.

받아서 도움되신 분은 공감 꾸욱 눌러주세요~~


google_oauth.zip



블로그 이미지

Link2Me

,
728x90

Class 란 객체(object)를 만들기 위한 설계도이다.

객체지향에 대한 개념을 잘 이해하고자 한다면, 유투브 강좌 "자바의 정석"을 추천한다.


PHP Class 를 이용하면 함수 이상으로 코드를 재사용할 수 있다.


PHP의 모든 함수와 클래스는 전역이다.
함수가 내부에서 정의되었더라도 외부에서 호출할 수 있으며, 반대도 성립한다.
PHP는 함수 오버로딩(overloading)을 지원하지 않으며, 함수 정의를 해제하거나 이미 선언된 함수를 다시 선언할 수 없다.


이중 밑줄(__) 로 시작하는 PHP 함수를 매직 메소드(Magic Method)라 부른다.

Magic Method 에는 __construct(), __destruct(), __call(), __callStatic(), __get(), __set(), __isset(), __unset(), __sleep(), __wakeup(), __toString(), __invoke(), __set_state() 그리고 __clone() 이 있다.


  __construct() : 클래스의 생성자
     새로운 오브젝트가 생성(인스턴스화)될때마다 이 메소드를 호출

  __destruct() : 클래스의 소멸자
     특정 오브젝트에의 모든 참조(레퍼런스)가 삭제된 직후 도는 오브젝트가 명시적으로 파기된 직후 호출
  __set() – 엑세스 할 속성에 데이터를 쓸 때 사용 (저장)
  __get() – 엑세스 할 속성에서 데이터를 읽을 때 사용 (출력)
  __isset() – 엑세스할 속성에 isset() 또는 empty() 를 호출하여 트리거 됨 (확인)
  __unset() – 엑세스 할 속성에 unset() 를 사용할 경우 호출 (삭제)


클래스 정의

class 를 정의하기 위해서는 class 키워드를 사용하여 정의하여야 한다.

Login 으로 클래스를 정의할 수도 있지만 클래스 라는 걸 인지하기 쉽도록 LoginClass 로 정의했다.


<?php

// 클래스명은 첫자는 대문자로 시작하고, 파일명과 동일하게 한다.

class LoginClass { // LoginClass 클래스 선언
    public $email, $name;  //public으로 변수 선언

    function __construct(){       // 클래스의 생성자 선언
        $this->name = "Link2me"; // 객체가 생성되면서 name 속성에 Link2me 대입
    }

    function __destruct(){
        echo "Login Class 객체 소멸";
    }

    function UserIDJoinCheck($userID) { // 함수(메소드) 선언
        if(!isset($userID) || empty($userID)) {
            return '-1';
        } else {
            global $db; //global 키워드를 사용하여 변수에 선언할 경우 함수 밖의 변수를 참조할 수 있다.          
            $userID = preg_replace("/[\s\t]+/","", $userID); // 공백이나 탭 제거(사용자 실수 방지)

            $sql = "select id, count(id)
from member ";
            $sql.= "where id= '".$userID."' ";
            if($result = mysql_query($sql,$db)) { //성공
                $row = mysql_fetch_row($result);
                if($row[1] == '0') return 0; // userID 미가입
                return $row[1];
            } else {
                return '-1';
            }
        }
    }


    static function MyName(){
        echo "My name is Link2me.";
    }

}
?>


접근 제한자

public  
- 클래스 안, 밖에서 접근이 가능하다.
- 키워드를 아무것도 적지 않았을 경우에는 public 이 기본 값으로 적용된다.

protected
- 클래스 안에서만 접근이 가능하지만 하위 클래스로 상속이 가능하다.
  하지만 하위 클래스 외부에선 접근이 불가하다.

private
- 클래스 안에서만 접근이 가능하며, 상속이 안된다.


객체 생성

객체를 생성하려면 new 키워드를 사용한다.

$object = new LoginClass;  // new 키워드로 LoginClass 객체 생성(객체화, 인스턴스화)


객체 접근

클래스 메서드 내에서 비정적 객체(object)의 속성(property)에 접근하는 방법은 객체연산자( -> )를 사용한다.

$data = $object->UserIDJoinCheck($id);

속성이나 함수(메소드)에 접근할 때에는 $ 를 붙이지 않도록 하라. $를 붙이면 해당 변수를 가리키기 때문에 엉뚱한 결과가 발생할 수 있음을 명심하자.


Class 내에서 다른 메소드(함수)에 접근할 때에는 $this 를 사용한다.

$this는 해당 클래스를 가리킨다.

$this->val 는  해당 클래스의 $val 변수에 접근한다는 것을 의미한다.


정적(static) 메소드의 호출은 객체 연산자(->) 가 아닌 더블콜론(::)으로 호출된다.

더블콜론은 static 이나 constant와, 클래스의 재정의된 프로퍼티나 메서드에 접근 할 수 있도록 해주는 토큰이다.

LoginClass::MyName();



객체 복제

new로 객체를 생성하여 매개 변수로 넘길 때는 참조로 넘어간다.
따라서 새로운 메모리를 할당하는 것이아닌 객체의 주소값을 전달하는 것이다.

$object1 = new LoginClass;

$boject2 = $object1;


객체 복사를 해서 적용하거나 테스트를 안해봐서 세부적인 사항은 나중에 추가할 생각이다.


접근 제한자 : 멤버변수나 메소드 앞에 지정하여 클래스 외부에서의 참조나 실행을 제한 할 때 사용한다.

 - 접근 제한자가 정의되어 있지 않으면, 기본으로 public 으로 가정한다.

 - public : 외부에서 참조할 수 있음.

 - private : 변수를 선언한 클래스 안에서만 참조할 수 있다.

 - protected : 변수를 선언한 클래스와 상속 받은 클래스에서 참조할 수 있다.

 - final 메소드 : 서브 클래스가 부모 클래스의 메소드를 대체하는 걸 원치 않을 경우에는 final 키워드를 사용한다.

   final function copyright(){

   echo "Copyright Link2me";

   }


상속(inheritance)
: 클래스를 정의할 때 다른 클래스의 내부 데이터(멤버변수)나 메소드를 이어받어 새로운 클래스를 작성할 수 있는 기능(코드의 재활용성)


extends 키워드를 사용하여 다른 클래스의 메소드와 멤버변수(속성)을 상속할 수 있다.

class 자식 클래스명 extends 부모클래스명 {

   처리 코드

}


class ParentClass {
    var $name = "개발자";
}

class SubClass extends ParentClass{
    function info(){
        echo "name : ".$this->name; // 부모 클래스의 변수를 상속 받는다.
    }
}

$childObject = new SubClass();
$childObject -> info();


// 부모 클래스의 public 키워드로 선언된 변수와 메소드를 final로 변경하면

// 자식클래스에서 오버라이딩이 제한된다.


부모 클래스의 접근 제한자가 public, protected, private 에 따라 출력 결과가 달라짐을 확인해보라.

<?php
    class ParentClass{
        public $name = "홍길동";
        
        protected function showInfo(){
            echo "name : ".$this->name;
        }
        
        public function output(){
            echo "ParentClass ";
            $this->showInfo();
        }
    }
    
    
    class SubClass extends ParentClass{
        public function output(){
            echo "subClass ";
            $this->showInfo();
        }
    }
    
    $parentObject = new ParentClass();
    $parentObjec->output();
    
    echo '<br />';
    
    $childObjec = new SubClass();
    $childObjec->output();
?>

생성자

 - 자식 클래스가 생성자를 가지고 있지 않은 경우, 자동으로 부모 클래스의 생성자를 호출한다.

 - 자식 클래스가 생성자를 가지고 있는 경우 부모 클래스의 생성자가 암묵적으로 호출되지 않는다.
 - 부모클래스의 생성자를 실행하기위해서는 자식 클래스내에서 parent::__construct() 를 호출하여야 한다.

 - 생성자는 2개(ex, 인자 있는것과 없는 것) 생성하면 에러가 발생한다.

<?php
class people {
    public $height;
    public $weight;
    public function __construct($height, $weight) {
        $this -> height = $height;
        $this -> weight = $weight;
    }
}

class subPeople extends people {
    public function __construct($height, $weight) {
        parent::__construct($height, $weight);
    }
}

$people = new people(170, 50);
$subPeople = new subPeople(180, 60);

print_r($people);
print_r($subPeople);
?>


'Web 프로그램 > PHP 문법' 카테고리의 다른 글

[PHP] PHP 문자열 찾기  (0) 2017.11.14
[PHP] 배열에만 동작하는 foreach 문  (0) 2017.01.26
PHP isset 과 empty 설명  (1) 2016.04.27
PHP 대체 문법  (0) 2016.04.05
[PHP] switch 문  (0) 2015.06.01
블로그 이미지

Link2Me

,
728x90

생활코딩 사이트 동영상 강좌를 보다가 Aptana 를 알게되어 설치를 시도했다.

Aptana Studio 3 를 알고 있을 때와 모르고 있을 때의 차이점은

Aptana Studio 3 를 알면 파워풀한 기능, 편리한 기능으로 코딩하기가 정말 쉬워진다.


http://www.aptana.com/products/studio3/download.html

에서 윈도우버전 3.6.1을 받아서 설치를 했다. (경고성 메시지 떠서 강제로 실행했음, 2019.8.27)

https://github.com/aptana/studio3/releases 에 최신 버전이 올라와 있다.


위 사이트에 가면 최신버전이 나온다.


알아야 할 사항

JDK 파일은 반드시 32비트 버전 8버전대를 받아야 한다.

64비트 용으로 받았다가 지우고 다시 32비트 버전으로 설정을 했다.



에러가 발생하면서 설치가 중단된다.

nodejs 파일을 설치해주면 된다고 해서 받아서 설치해도 안된다.

검색했더니 아래 파일을 설치해주라고 되어 있어서 받아서 설치를 했더니 설치도중에 나오는 에러메시지는 없어지고 잘 설치가 되었다.


node-v0.10.13-x86.msi


http://go.appcelerator.com/installer_git_windows.exe 파일을 받아서 설치하라고 구글 검색하면 나온다.


Aptana 프로그램을 실행했더니 또 에러가 나면서 실행이 안된다.

Failed to load the JNI shared library "C:\Program Files......\jvm.dll"

Aptana 3.6.1 이 기본적으로 x86 으로 설치가 되는거 같다.

eclipse 는 64비트로 잘 동작되는데도 불구하고 설치를 하면 에러가 발생한다.


http://www.oracle.com/technetwork/java/javase/downloads/jre8-downloads-2133155.html



받아서 설치하니까 자동으로 인식된다.

위 사이트에서 받지 않고 첨부한 이 파일을 받아서 설치해도 된다.


jre-8u111-windows-i586-iftw.exe



Aptana 도 eclipse 처럼 workspace 경로를 잡아주어야 한다.

그리고 AutoSet9 과 연동하여 Apache 환경설정 경로를 잡아주어야 제대로 사용하는 거다.

- 프로젝트 단위로  생성하여 관리한다. (eclipse 기능하고 동일한 개념)

- 파일에서 내용 검색이 쉽다.

- 코드를 입력하면 자동으로 검색되는 키워드를 보여줘 무척 편하다.

- 코드를 만들어 테스트할 때, Firefox 등 웹브라우저로 바로 연결되어 결과를 확인할 수 있어 편하다.



EditPlus

- Total Commander 에서 파일을 선택하면 자동으로 EditPlus 창이 뜨므로 코드 수정이 편하다.
-
리눅스 APM에 코드를 올려야 한다면 WinSCP 를 이용하면 편하다.
-
EditPlus 매크로 기능을 사용하면 단순작업이 편하다.

- 인터넷에 있는 코드를 복사해서 붙여넣기 한다음 간단하게 수정하기가 편하다.

블로그 이미지

Link2Me

,
728x90

Form 데이터를 jQuery submit 하면서 기초가 부족해서 삽질을 많이 한다.

http://hayageek.com/jquery-submit-form/ 사이트 예제, http://www.sqler.com/387921 를 보면 도움된다.


Form 전송시 필드(input box) 를 동적으로 추가해야 할 경우가 있다.

http://www.codexworld.com/add-remove-input-fields-dynamically-using-jquery/ 에서 소스를 받아서 코드를 보강하면서 테스트를 했다.


수정/추가한 부분 및 내역

- javascript:void(0); 대신에 #으로 수정하고 jQuery 코드 부분 수정(e.preventDefault() 추가)

- 용어 내 스타일로 변경

- form submit 부분 추가하고 ajax 형태로 처리하는 코드 추가

- 입력값이 없을 때 체크하는 코드 추가

※ DB에 저장하고 나서 다시 수정/삭제/추가할 경우까지 고려되어 있지는 않다.


=== index.php ===

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Add more fields using jQuery</title>
<style type="text/css">
input[type="text"]{height:18px;width:220px;vertical-align:top;}
.field_wrapper div{ margin-bottom:10px;}
.add_button{ margin-top:10px; margin-left:10px;vertical-align: text-bottom;}
.removeBtn{ margin-top:10px; margin-left:10px;vertical-align: text-bottom;}
</style>
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
    var maxCount = 5;
    var addButton = $('.add_button');
    var wrapper = $('.field_wrapper');
    var AddBox = '<div><input type="text" name="kordiv[]" value=""/><a href="#" class="removeBtn" title="제거"><img src="remove-icon.png"/></a></div>';
    var x = 1;
    $(addButton).click(function(e){
        e.preventDefault();
        if(x < maxCount){
            x++;
            $(wrapper).append(AddBox);
        }else{
            alert('최대 '+maxCount+'개까지 허용합니다');
            return false;
        }
    });
    $(wrapper).on('click', '.removeBtn', function(e){
        e.preventDefault();
        $(this).parent('div').remove();
        x--;
    });

    $("#submit1").click(function(){
        // 폼 요소 내부의 입력값만을 찾기 위해서 폼 요소에서 find()를 호출
        var xyz = $("#myform").find('[name=xyz]').val();
        if(xyz =='') {
            alert('xyz 값이 입력되지 않았습니다.');
            return false;
        }

        // 배열로 된 값이 제대로 입력되었는지 체크
        var cnt = 0;
        $('input[name^="kordiv"]').each(function() {
            //alert($(this).val());
            if($(this).val() === '') {
                cnt++;
            }
        });
        if(cnt > 0){
            alert('kordiv 에 입력되지 않는 필드가 '+cnt+'개 있습니다');
            return false;
        }

        var formData = $("#myform").serialize();
        var URL = $("#myform").attr("action");
        $.post(URL, formData, function(data, textStatus, jqXHR){
            alert(data);
            var data = jQuery.parseJSON(data);
            $.each(data, function(index, value) {
                alert(value);
            });

        }).fail(function(jqXHR, textStatus, errorThrown) {
            console(errorThrown);
        });

    });

});
</script>
</head>
<body>
<form name="frm" id="myform" action="frm_result.php" method="POST">
<input type="hidden" name="xyz" value="123" />
<div class="field_wrapper">
    <div>
        <input type="text" name="kordiv[]" value=""/>
        <a href="#" class="add_button" title="추가"><img src="add-icon.png"/></a>
    </div>
</div>
<input type="hidden" name="submit" value="true" />
</form>
<br/>
<input type="button" id="submit1" value="전송" />
</body>
</html>


=== frm_result.php ===

<?php
if(isset($_POST['submit'])){
    $kordiv_array = $_POST['kordiv']; // 배열

    /*
    print '<pre>';
    print_r($kordiv_array);
    print_r($_POST['xyz']);
    print '</pre>';
    // */

    $R = array();
    foreach($kordiv_array as $value){ // 배열로 받은 걸 분리 처리
        //echo $value;
        array_push($R,$value);
    }
    $Content = 'Hello world';
    echo json_encode(array('rs'=>$R,'Content' => $Content));
}
?>


블로그 이미지

Link2Me

,