Могу ли я заставить PDOStatement-> fetchObject не использовать переменные, не являющиеся членами? - PullRequest
4 голосов
/ 29 мая 2010

Допустим, у меня есть такой класс:

Class User {
  var $id
  var $name;
}

И я запускаю запрос с использованием PDO в php следующим образом:

$stm = $db->prepare('select * from users where id = :id');
$r = $stm->execute(array(':id' => $id));
$user = $r->fetchObject('User');

Если я изменяю свой пользовательский объект, в нем есть все другие поля, которые я не определил в классе User. Очевидно, что я мог бы сделать свой запрос конкретным, чтобы он возвращал мне только те поля, которые мне нужны / нужны. Но если я не хочу этого делать, есть ли способ заставить эту работу работать так, как я хочу?

Мне нравится идея fetchObject, потому что это одна строка кода для создания этого объекта и установки переменных-членов для меня. Я просто не хочу, чтобы он устанавливал переменные, которые я не определил в своем классе.

EDIT:

Ну, кажется, что karim79 прав, и fetch или fetchObject не будут работать так, как я хочу. Я добавил следующий фрагмент кода после выполнения выборки, чтобы получить желаемые результаты.

$valid_vars = get_class_vars('User');
foreach (get_object_vars($user) as $key => $value) {
    if (!array_key_exists($key, $valid_vars)) {
        unset($user->$key);
    }
}

Очевидно, что это не самое элегантное решение: / Я собираюсь расширить класс PDOStatement и добавить свой собственный метод fetchIntoObject или что-то в этом роде и автоматически делать эти сбросы. Надеюсь, не должно быть слишком много накладных расходов, но я хочу иметь возможность легко извлечь объект с 1 строкой кода:)

СУПЕР РЕДАКТИРОВАНИЕ:

Благодаря комментарию Мамаара я снова вернулся к документации. Я нашел в чем проблема. http://us.php.net/manual/en/pdo.constants.php и прокрутите вниз до PDO :: FETCH_CLASS, и это объясняет, что магический метод __set () используется, если свойства не существуют в классе. Я переписал метод в моем целевом классе и тада, работает. Опять же, не самое элегантное решение. Но теперь я понимаю ПОЧЕМУ, и это важно для меня: D

Ответы [ 4 ]

2 голосов
/ 07 ноября 2010

PDOStatement->execute() не возвращает объект - он возвращает TRUE / FALSE.

Измените строки 2 и 3 на

if ( $stm->execute( array( ':id' => $id ) ) ){    
    $user = $stm->fetchObject( 'User' );
}

, и это будет работать

1 голос
/ 29 мая 2010

Возможно, вы могли бы использовать метод PDOStatement-> fetch с PDO :: FETCH_CLASS или PDO :: FETCH_INTO в качестве параметра $ fetch_style

Редактировать: Итак, я попробовал себя и заставил работать с PDOStatement-> setFetchMode

class User
{
    public $id;
    public $name;
}

$db = new PDO('mysql:host=127.0.0.1;dbname=test', 'username', 'password');

$stmt = $db->prepare("select * from users where id=:userId");
$stmt->setFetchMode(PDO::FETCH_CLASS, 'User');
$stmt->execute(array(':userId' => 1));

$user = $stmt->fetch();
var_dump($user);
1 голос
/ 29 мая 2010

Я не думаю, что это возможно.fetchObject создаст экземпляр имени класса, указанного как $class_name параметр fetchObject (по умолчанию используется stdClass).Он не будет проверять существующие классы с тем же именем и создавать экземпляр, назначая значения только переменным-членам, которые соответствуют именам столбцов в результате.Я бы посоветовал полагаться на что-то более скучное, например:

$user = new User($result['id'], $result['name']);

Что, конечно, означало бы предоставление вашему классу User конструктора:

Class User {
  var $id
  var $name;

  public function __construct($id, $name)
  {
     $this->id = $id;
     $this->name = $name;
  }

}
0 голосов
/ 29 мая 2010

В качестве альтернативы, вы можете, конечно, просто получить массив и просто ввести его самостоятельно:

$user = (User) $r->fetch();

Кстати, я не видел такого поведения. Возможно, вы активировали PDO :: FETCH_LAZY, что может создать дополнительные данные. Вы можете проверить это с помощью -> fetchObject ("stdClass"), иначе причина находится в вашем классе User или его Parent?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...