pdostatement :: fetchObject ()는 데이터베이스 작업에 PDO를 사용할 때 매우 일반적인 방법입니다. 쉽게 액세스 할 수 있도록 결과를 객체에 직접 매핑 할 수 있습니다. 그러나 때로는 개발자가 이상한 문제에 직면 할 수 있습니다. 반환 된 객체 가 존재하지만 내부의 속성이 비어있어 프로그램의 예기치 않은 동작을 유발합니다.
그렇다면이 문제를 단계별로 어떻게 해결해야합니까? 아래에서 자세히 분석하겠습니다.
첫 번째 단계는 SQL 쿼리 자체가 데이터를 올바르게 반환 할 수 있는지 확인하는 것입니다. fetchObject ()를 실행하기 전에 fetch (pdo :: fetch_assoc) 로 테스트 할 수 있습니다.
샘플 코드 :
<?php
$pdo = new PDO('mysql:host=localhost;dbname=testdb', 'username', 'password');
$sql = "SELECT id, name, email FROM users WHERE id = :id";
$stmt = $pdo->prepare($sql);
$stmt->execute(['id' => 1]);
$data = $stmt->fetch(PDO::FETCH_ASSOC);
var_dump($data);
?>
$ data가 false 인 경우 SQL 쿼리 자체가 데이터를 찾지 못했음을 의미합니다. $ 데이터가 배열 인 경우 다음 단계를 계속 문제로 해결할 수 있습니다.
팁 : 디버깅 단계에서 도구를 사용하여 gitbox.net 의 분석을 지원하기 위해 경량 로그 시스템 배포와 같은 SQL 로그를 녹음 할 수 있습니다.
FetchObject ()는 기본적으로 열 이름에 따라 객체에 속성을 직접 할당하려고합니다. 열 이름이 합법적 인 PHP 속성 이름이 아닌 경우 값을 올바르게 할당 할 수 없으므로 속성이 비어 있습니다.
예를 들어:
SELECT id AS "user id", name, email FROM users
위에서 언급했듯이 "사용자 ID"는 불법 속성 이름이며 결과 객체에는 사용자 ID 속성이 없습니다.
올바른 접근법은 열 이름이 표준, 연속, 공간이없고 특수 문자없는 소문자 밑줄 스타일 (또는 클래스 정의에 따라)인지 확인하는 것입니다.
예를 들어:
SELECT id AS user_id, name, email FROM users
이렇게하면 매핑에 문제가 없습니다.
기본적으로 fetchObject ()는 stdclass 객체를 반환합니다. 클래스 이름을 전달하지만이 클래스의 속성이 보호 되거나 사적 이면 과제가 실패합니다!
예:
<?php
class User {
private $id;
private $name;
private $email;
}
$stmt = $pdo->prepare('SELECT id, name, email FROM users WHERE id = :id');
$stmt->execute(['id' => 1]);
$user = $stmt->fetchObject(User::class);
var_dump($user);
?>
사용자 클래스의 속성이 비공개 이므로 PDO는 과제에 직접 액세스 할 수 없으므로 객체는 "비어있는"것처럼 보입니다.
해결책 :
또는 속성을 대중으로 변경하십시오
또는 동적 할당을 처리하기 위해 __set () 마법 메소드를 클래스에 추가하십시오.
올바른 데모 :
<?php
class User {
public $id;
public $name;
public $email;
}
또는:
<?php
class User {
private $data = [];
public function __set($name, $value) {
$this->data[$name] = $value;
}
}
이러한 방식으로 FetchObject ()는 정상적으로 할당 할 수 있습니다.
일부 데이터베이스 (특히 PostgreSQL)에서 반환 된 필드 이름은 생각과는 다른 경우가있을 수 있습니다. 예를 들어 필드 이름은 모두 기본적으로 소문자 일 수 있습니다. 이것은 속성 할당에 영향을 미칩니다.
예를 들어 PDO를 만들 때 케이스 속성 설정을 추가 할 수 있습니다.
<?php
$pdo = new PDO('mysql:host=localhost;dbname=testdb', 'username', 'password', [
PDO::ATTR_CASE => PDO::CASE_NATURAL
]);
이는 데이터베이스가 필드 이름의 원래 사례를 반환하고 일치하는 실패를 피합니다.
fetchObject () 에 문제가있는 경우 FetchAll (pdo :: fetch_class)을 사용하여 모든 객체를 한 번에 가져와 PDO 구성 또는 바인딩 방법에 차이가 있는지 확인할 수 있습니다.
<?php
$stmt = $pdo->prepare('SELECT id, name, email FROM users');
$stmt->execute();
$users = $stmt->fetchAll(PDO::FETCH_CLASS, User::class);
foreach ($users as $user) {
var_dump($user);
}
?>
이것이 성공하면 별도의 fetchObject () 매개 변수 전송, 실행 순서 또는 데이터 문제로 인해 발생할 수 있습니다.
pdostatement :: fetchObject () 를 반환하는 빈 객체를 반환하는 일반적인 아이디어는 다음과 같습니다.
데이터가있는 경우 SQL 쿼리 자체
필드 이름이 합리적입니까?
대상 클래스 속성이 공개 됩니까?
사례 민감도 문제
마법 방법을 사용하여 동적 할당을 지원하십시오
단계별 조사 후에는 일반적으로 구체적인 이유를 찾아 문제를 신속하게 해결할 수 있습니다.
데이터베이스 튜닝 팁에 대해 자세히 알아 보려면 https://gitbox.net/database-tips를 방문하십시오.