29 Dec 2019
|
Laracast
PHP
Laracasts - The PHP Practitioner 강의를 듣고 정리한 포스팅 입니다.
1. Config.php
database/Connection.php
에는 현재 DSN, 아이디, 비밀번호가 전부 노출되어있음. 보안상의 문제가 발생할 수 있으므로, 이러한 데이터들을 따로 일괄적으로 관리하는 것이 더 적합함. => config.php
생성
options
은 PDO 객체를 생성할 때 지정할 수 있는 옵션으로, 에러가 발생 시, 어떠한 에러가 발생하는지를 알기 위해서는 PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
를 사용
<?php
return [
'database' => [
'name' => 'mytodo',
'username' => 'root',
'password' => '111111',
'connection' => 'mysql:host=localhost',
'options' => [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
]
]
];
2. config.php 호출
bootrap.php
에서 config.php
를 호출한 후, 데이터를 Connection::make
의 인자로 넘겨준다.
<?php
$config = require 'config.php';
require 'database/Connection.php';
require 'database/QueryBuilder.php';
return new QueryBuilder(
Connection::make($config['database'])
);
Connection.php
에서 PDO 객체의 파라미터로, 넘어온 연관배열의 값을 입력해준다.
<?php
class Connection
{
public static function make($config)
{
try {
return new PDO(
$config['connection'].';dbname='.$config['name'],
$config['username'],
$config['password'],
$config['options']
);
} catch (PDOException $e) {
die($e->getMessage());
}
}
}
29 Dec 2019
|
Laracast
PHP
Laracasts - The PHP Practitioner 강의를 듣고 정리한 포스팅 입니다.
1. PDO Refactoring
앞 포스팅 코드를 기반으로 refactoring을 진행할 수 있음. 데이터베이스에 연결 & 쿼리 실행 + 데이터 갖고오기의 코드를 database라는 디렉토리 내에 각각 세분화 시킬 수 있음.
- Connection.php - 데이터 베이스 연결
- QueryBuilder.php - 쿼리 실행 + 데이터 갖고오기
Static method는 인스턴스를 생성하지 않고도 전역으로 접근할 수 있게 함. ::
는 static method임을 지칭함
// Connection.php
class Connection
{
# way to make a method accessible globally without requiring instance
public static function make()
{
try {
return new PDO('mysql:host=localhost;dbname=mytodo;', 'root', '111111');
} catch (PDOException $e) {
die($e->getMessage());
}
}
}
// general method
$connection = new Connection();
$connection->make();
// static method
$Connection::make();
2. QueryBuilder.php
PDO
객체를 외부로부터 받아 생성자 메서드인 __construct
의 인자로 할당시킴. 모든 데이터를 가지고오는 selectAll
함수를 QueryBuilder
의 메서드로 생성
// QueryBuilder.php
<?php
class QueryBuilder
{
protected $pdo;
public function __construct(PDO $pdo)
{
$this->pdo = $pdo;
}
public function selectAll($table)
{
$statement = $this->pdo->prepare("select * from {$table}");
$statement->execute();
return $statement->fetchAll(PDO::FETCH_CLASS);
}
}
3. Bootstrap.php
Connection.php & QueryBuilder.php는 데이터베이스를 다루는 코드로 index.php에서 해당 파일들을 require
로 호출하는 것은 선호되는 모습은 아님.
따라서 behind the scence 을 관장하는 bootstrap.php 파일을 생성하여 Connection.php와 QueryBuilder.php를 연결시키는 로직을 작성
<?php
# bootstrap: responsible for behind the scene
require 'database/Connection.php';
require 'database/QueryBuilder.php';
// option 1.
//$pdo = Connection::make();
//$query = new QueryBuilder($pdo);
// option 2.
//$query = new QueryBuilder(Connection::make());
// option 3.
return new QueryBuilder(
Connection::make()
);
4. index.php
- bootstrap.php
Connection::make
: 스태틱 메서드인 make
가 호출되며 make
는 PDO 객체를 반환함.
- bootstrap.php는
make
로 부터 반환된 PDO 객체를 바탕으로 QueryBuilder
인스턴스 객체를 반환하여 반환 값을 $query
변수에 저장
$query
(QueryBuilder
인스턴스 객체가 저장된 변수) 에서 모든 데이터를 갖고오는 메서드 selectAll
을 호출하며, 이때 테이블명에 해당하는 todos
를 파라미터로 넘김.
- 해당 로직의 값을
$tasks
에 저장시키며, 렌더링된 값이 index.view.php 를 통해 표시됨.
<?php
$query = require 'bootstrap.php';
$tasks = $query->selectAll('todos');
require 'index.view.php';
29 Dec 2019
|
Laracast
PHP
Laracasts - The PHP Practitioner 강의를 듣고 정리한 포스팅 입니다.
1. PDO
PHP Database Object의 약자로, 데이터베이스에 접근하는 공통 API를 제공하는 것을 목적으로 만들어 짐. Prepared statement를 제공하므로 SQL Injection 방어에 사용될 수 있음.
2. PDO 조작
PDO를 통해 데이터베이스에 연결하기
new PDO(DSN-Data Source Name, 아이디, 비밀번호)
- 데이터베이스 연결에 실패할 경우
PDOException
을 발생시키도록 try-catch
로 예외처리가능
try {
$pdo = new PDO('mysql:host=localhost;dbname=mytodo;', 'root', '111111');
} catch (PDOException $e) {
die($e->getMessage());
}
데이터베이스 접근 & 조회하기: 쿼리문 작성(prepare
) - 실행(execute
) - 가져오기(fetch
)
# SQL 실행
$statement = $pdo->prepare('select * from todos'); # SQL문 작성
$statement ->execute(); #실행
# 데이터 갖고오기
var_dump($statement->fetchAll()); #모든 데이터 갖고오기
# fetch result override: 결과를 오브젝트(제너릭 클래스의 인스턴스)로 fetch해옴
var_dump($statement->fetchAll(PDO::FETCH_OBJ));
# 응용
$results = $statement->fetchAll(PDO::FETCH_OBJ);
var_dump($results[0]->description);
결과를 커스텀 클래스의 인스턴스에 저장하여 호출도 가능함.
#index.php
require 'Task.php';
$tasks = $statement->fetchAll(PDO::FETCH_CLASS, 'Task');
var_dump($tasks[0]->foobar());
#Task.php
<?php
class Task
{
public $description;
public $completed;
public function foobar()
{
return 'foobar';
}
}
3. 최종 리팩토링
동작하는 부분을 함수로 만들어 function.php으로 옮긴 후 require
로 index.php에서 호출하여 사용
# index.php
<?php
require 'Task.php';
require 'function.php';
$pdo = connectToDb();
$tasks = fetchAllTasks($pdo);
require 'index.view.php';
#function.php
<?php
function connectToDb()
{
try {
return new PDO('mysql:host=localhost;dbname=mytodo;', 'root', '111111');
} catch (PDOException $e) {
die($e->getMessage());
}
}
function fetchAllTasks($pdo)
{
$statement = $pdo->prepare('select * from todos');
$statement ->execute();
//$tasks = $statement->fetchAll(PDO::FETCH_OBJ);
return $statement->fetchAll(PDO::FETCH_CLASS, 'Task');
}
29 Dec 2019
|
Laracast
PHP
Laracasts - The PHP Practitioner 강의를 듣고 정리한 포스팅 입니다.
1. Class의 기본 구성
property와 method로 구성되어있음.
- 생성자 메서드:
__construct
: Automatically triggered on instantiation
$this
: 인스턴스 객체
$this->프로퍼티명 = 변수
: 객체의 프로퍼티에 변수(데이터) 할당
<?php
class Task {
// property
protected $description;
protected $completed = false;
// method
public function __construct($description)
{
// Automatically triggered on instantiation
// current instance(object)에
// description(property)에 $description을 할당
$this->description = $description;
}
public function complete()
{
$this->completed = true;
}
public function isComplete()
{
return $this->completed;
}
}
2. 클래스 호출
객체 생성 및 프로퍼티 할당. 배열로 여러개의 인스턴스를 한꺼번에 생성할 수 도 있음.
$task = new Task('Go to the store'); // a new task object
$task-> complete(); // complete the task
var_dump($task-> isComplete());
//var_dump($task);
$tasks = [
new Task('Go to the store'),
new Task('Finish my screencast'),
new Task('Clean my room')
];
var_dump($tasks);
3. 응용
HTML과 결합하여 사용할 경우
- 프로퍼티를
protected
로 정의 할 경우에는 외부로의 호출이 불가능함. => 프로퍼티를 public
으로 변경
<ul>
<?php foreach ($tasks as $task) : ?>
<li><?= $task->description; ?></li>
<?php endforeach ?>
</ul>
complete된 task는 <strike></strike>
옵션 적용
$tasks = [
new Task('Go to the store'),
new Task('Finish my screencast'),
new Task('Clean my room')
];
$tasks[0]->complete();
<ul>
<?php foreach ($tasks as $task) : ?>
<li>
<?php if ($task->completed) : ?>
<strike><?= $task->description ?></strike>
<?php else: ?>
<?= $task->description; ?>
<?php endif; ?>
</li>
<?php endforeach ?>
</ul>