첫째 주, 마지막 주에 비는 날짜는 저번 달, 다음 달 날짜로 채워야 하는 PHP 달력 코드 입니다.
<div>
<div>
<div>
<div>
<h4>달력</h4>
<h3>Program</h3>
</div>
</div>
<div class="calendar">
<dl>
<dt class="sun">일</dt>
<dt>월</dt>
<dt>화</dt>
<dt>수</dt>
<dt>목</dt>
<dt>금</dt>
<dt class="sat">토</dt>
</dl>
<?
$year = date('Y');
$month = date("m");
//$month = date("m",strtotime('2024-06-01')); 테스트 코드
$firstDayOfMonth = 1;//첫 날
$lastDayOfMonth = date("t",strtotime("$year-$month"));//마지막 날
$firstDayOfWeek = date('w',strtotime("$year-$month-01"));//첫날 요일(0~6)
$lastDayOfWeek = date('w',strtotime("$year-$month-$lastDayOfMonth"));//마지막 날 요일(0~6)
$lastDiff = 6-$lastDayOfWeek; //다음 달 날짜 표시 해야 될 수
$prev_last_day=date('t',strtotime("-1 month",strtotime("$year-$month-01")));//지난달 마지막 날
$prev_count = $prev_last_day - $firstDayOfWeek+1; //첫째 주 저번 달 날짜 표시
$totalCnt = $firstDayOfWeek+$lastDayOfMonth+$lastDiff;//첫째 주 표시 해야 할 수 + 이번 달 표시 해야 될 수 + 마지막 주 표시 해야 할 수
$day=1; // 이번 달 날짜 표시
$last_cnt = 1; //마지막 주 다음 달 날짜 표시
for($i=1;$i<=$totalCnt;$i++){
if($i<=$firstDayOfWeek){
if($i==1){
echo "<dl class=\"body\">";
}
echo "<dd class=\"block\"><em>{$prev_count}</em></dd>";
$prev_count++;
}else if($i>$lastDayOfMonth+$firstDayOfWeek){
echo "<dd class=\"block\"><em>{$last_cnt}</em></dd>";
$last_cnt++;
if($i==$totalCnt){
echo "</dl>";
}
}
else{
if(date("w", strtotime("$year-$month-$day")) == 0){//주 시작(일요일)
echo "<dl class=\"body\">";
}
echo "<dd><em>{$day}</em></dd>";
if(date("w", strtotime("$year-$month-$day")) == 6){// 주 종료(토요일)
echo "</dl>";
}
$day++;
}
}
?>
</div>
</div>
</div>
위의 사진 처럼 프로젝트를 선택 후 왼쪽 메뉴 탭을 펼쳐서 OAuth 동의 화면을 클릭 한다.
OAuth 동의 화면2
프로젝트에 맞게 내부, 외부를 선택 후 만들기 클릭
2-1.앱 등록 하기.
항목에 맞게 써주는데 홈페이지 URL은 이때 안 써도 된다.
범위 추가 또는 삭제 버튼을 클릭 해서 필요한 범위를 체크 해준다.
테스트를 할 사용자의 계정을 추가 해준다.
추가 후 OAuth 동의 화면 메뉴를 클릭 후 앱 게시 버튼을 클릭 해준다.
3.OAuth 클라이언트 ID를 생성
사용자 인증 정보 메뉴 클릭 -> +사용자 인증 정보 만들기 클릭 -> OAuth 클라이언트 ID 클릭
웹 어플리케이션으로 선택 후 이름, URL, 리다이렉트 URL을 설정해준다.
4.코드
php 코드
<?php
$google_redirect_url = "등록한 리다이렉트 주소(파일명 제거)";
$client_id = '발급한 클라이언트 ID';
$client_secret = '발급한 시크릿 키';
$scope = 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile';
function curl($url,$parameters){
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
curl_setopt($ch,CURLOPT_POSTFIELDS,$parameters);
$data = curl_exec($ch);
return $data;
}
function getCallbackUrl(){
global $google_redirect_url;
return urlencode($google_redirect_url.'login_google.php?google=callback');
}
function getLoginUrl(){
global $client_id,$scope;
return "https://accounts.google.com/o/oauth2/auth?response_type=code&redirect_uri=".getCallbackUrl()."&client_id=".$client_id."&scope=".$scope;
}
function getAccessToken(){
global $client_id,$client_secret;
if(isset($_GET['code'])){
// get access token from authorization code
$url = "https://accounts.google.com/o/oauth2/token";
$parameters="code=".$_GET['code']."&client_id=".$client_id."&client_secret=".$client_secret."&redirect_uri=".getCallbackUrl()."&grant_type=authorization_code";
return json_decode(curl($url,$parameters),true)['access_token'];
}else if(isset($_SESSION['access_token'])){
// get access token from session
return $_SESSION['access_token'];
}else{
// redirect to login url
header("Location: ".getLoginUrl());
exit;
}
}
function getUserInfo(){
// get user info from google api
$url="https://www.googleapis.com/oauth2/v1/userinfo?alt=json&access_token=".getAccessToken();
return json_decode(file_get_contents($url),true);
}
if(isset($_GET['google']) && $_GET['google']=='callback'){
// store access token in session
$_SESSION['access_token']=getAccessToken();
// redirect to index page
header("Location: ".$google_redirect_url."login_google.php");
}else{
$res = getUserInfo();
//여기서 로그인된 정보를 갖고 회원 가입 및 로그인 연동
exit;
}
redirect_url 변수 사용하는 곳을 보면 파일명을 따로 쓰기 때문에 처음 선언시 파일명을 제외한 URL로 입력 시켜야 한다.
또한 getcallbackUrl() 함수를 보면 ?google=callback 이렇게 파라미터를 보내기 때문에 애플리케이션 설정 페이지에서
redirect url을 저장시 기존 파일명에 ?google=callback 파라미터를 보내는 url도 저장시켜야 한다.
const arr = Array(1000000).fill().map((v,i)=> i+1);
console.time('for-type1');
const cnt = arr.length;
for(let i =0; i<cnt;i++){}
console.timeEnd('for-type1');
console.time('for-type2');
for(let i =0; i<arr.length;i++){}
console.timeEnd('for-type2');
console.time('for-type3');
for(var i =0; i<arr.length;i++){}
console.timeEnd('for-type3');
console.time('forEach');
arr.forEach(function(item,index){});
console.timeEnd('forEach');
console.time('for-in');
for(let idex in arr){}
console.timeEnd('for-in');
console.time('for-of');
for(let idex of arr){}
console.timeEnd('for-of');
결과
//for문 변수 선언
for-type1: 1.610107421875 ms
//for문 let 사용
for-type2: 1.657958984375 ms
//for문 var 사용
for-type3: 1.68798828125 ms
forEach: 9.888916015625 ms
for-in: 145.38818359375 ms
for-of: 24.77001953125 ms
var v; //초기화를 안해도 된다.
var v = 'var'; //중복선언 가능
let l; //초기화를 안해도 된다.
let l = 'let'; //중복선언 불가능(Uncaught SyntaxError: Identifier 'l' has already been declared)
const c; //Error(Uncaught SyntaxError: Missing initializer in const declaration)
const c = 'const'; //중복선언 불가능(Uncaught SyntaxError: Identifier 'c' has already been declared)
2. 재할당
var v = 'var';
console.log(v); //output : var
v='var2';
console.log(v); //output : var2
let l = 'let';
console.log(l); //output : let
l = 'let2';
console.log(l); //output : let2
const c = 'const';
c= 'const2'; //Error(Uncaught TypeError: Assignment to constant variable.)
3. 호이스팅
호이스팅이란?
javascript 엔진이 작동할 때(실행 컨텍스트 단계) var, function 등 선언 한 변수, 함수 등을 메모리에 저장하는 걸 의미합니다.
아래의 코드를 예를 들어보겠습니다.
example();
function example() {
console.log('Test');
}
한 줄씩 차례대로 진행하면 위와 같은 코드는 오류가 발생해야 정상이지만 호이스팅이 발생하면서 example 함수를 메모리에 저장했기 때문에 오류가 발생하지 않습니다.
var와 let, const 호이스팅 차이
아래의 코드를 보면 var는 에러가 안 나고 let, const는 Uncaught ReferenceError가 발생하는 걸 확인할 수 있습니다.
console.log(v)
var v = 'var';
//output : undefined
console.log(l)
let l = 'let';
//output : Uncaught ReferenceError: Cannot access 'l' before initialization
console.log(c)
const c = 'const';
//output : Uncaught ReferenceError: c is not defined
변수는 선언, 초기화, 할당의 단계를 걸쳐 선언되는데 이때 var와 let, const 차이가 발생합니다.
var의 경우 선언 시 선언과 초기화를 동시에 진행하고 (이때 undefined로 초기화 됩니다)
let, const의 경우 선언 시에 선언 단계만 진행합니다.(선언 단계에만 있을 때 TDZ 영역에 있다고 말합니다)
(※TDZ란? 초기화되지 않은 변수가 있는 영역)
호이스팅이 발생할때 TDZ에 있는 영역을 제외 하고 발생하기 때문에 위와 같은 차이가 발생합니다.
let g = 1; // 전역 스코프
function print() {
let l = 1; //지역 스코프
}
//변수 g는 어디서든 접근이 가능하지만 변수 l은 print 함수 안에서만 접근이 가능합니다.
//만약 변수 l을 print 함수 밖에서 접근시 ReferenceError가 발생합니다.
-var : function 스코프
-let, const : 블럭{} 스코프
if(true) {
var v = "var";
}
console.log(v);
//output : var
if(true) {
let l = "let";
}
console.log(l);
//output : Uncaught ReferenceError: l is not defined
if(true) {
const c = "const";
console.log("{} scope :"+c)
}
console.log("function scope"+c);
//output :
//{} scope :const
//Uncaught ReferenceError: c is not defined
위의 코드를 보면 var는 function 스코프 let, const는 {}스코프 단위로 변수에 참조할 수 있단 걸 알 수 있습니다.
이렇게 var, let, const 차이를 알아보았습니다.
var 변수로 선언된 변수는 for문 같은 반복문이 끝나고도 접근이 가능하기고 중복 선언 등과 같은 문제점이 있기 때문에 let, const를 사용하시는 걸 추천드립니다.