@gachkydxvbgd

Как безопаснее PDO?

echo $db->insert("INSERT INTO test (gaga) VALUES (:gaga)" , array('gaga'=>'test'));
        public function insert($query, $params){
            try{ 
                $stmt = $this->datab->prepare($query); 
				    while (list($key, $value) = each($params)) { 
                    unset($arr[$key + 1]); 
	                $stmt->bindValue(":$key", $value);
                } 
				$stmt->execute();
                return $this->datab->lastInsertId();
                }catch(PDOException $e){
                throw new Exception($e->getMessage());
            }
        }


или

$db->insert("INSERT INTO user (login, password, email) VALUES (?, ?, ?)", array($_POST['login'], $pw->gen($_POST['password']), $_POST['email']));
        public function insert($query, $params){
            try{ 
                $stmt = $this->datab->prepare($query); 
                $stmt->execute($params);
                return $this->datab->lastInsertId();

                }catch(PDOException $e){
                throw new Exception($e->getMessage());
            }
        }
  • Вопрос задан
  • 274 просмотра
Пригласить эксперта
Ответы на вопрос 2
index0h
@index0h
PHP, Golang. https://github.com/index0h
Ни первое, ни второе.

0. SQL запросу ну вот ни как не место в аргументах, это то, что должен делать ваш insert метод. Все что он должен получать - это аргументы которые будут вставляться в ваш запрос!
1. Вы не проверяете аргументы. Что произойдет, если я вызову insert:
$db->insert(new \Exception(), []);
Или так
$db->insert("DELETE FROM user", []);
Или так (тут lastInsertId вернет не id вставки)
$db->insert("SELECT CURRENT_TIMESTAMP", []);
2. Никогда, слышите? НИКОГДА! Не используйте при работе с БД суперглобальные переменные. Их удел - в самом начале index.php собрать объект Request, далее про их существование можно забыть.
3. datab обычно называются connection, либо по типу класса
4. В следующем коде нет смысла, от слова "совсем"
}catch(PDOException $e){
                throw new Exception($e->getMessage());

Вы просто обрубаете стектрейс, который далее стоит использовать для поиска ошибок.
5. У вас ключи строковые, зачем вот это?
unset($arr[$key + 1]);
6. Если в params передать [[]], как себя поведет ":$key"?
7. lastInsertId возвращает строку, кастовать в ваш тип не помешает.
8. Ради всего святого: прочитайте и следуйте PSR

Вот вам пример безопасного кода. Проверок в реальном коде должно быть на много больше:
* логин стоит прогнать по регулярке на допустимые символы
* почту стоит прогнать по регулярке, или через filter_var
* что пароль таки хэш (смотря какой алгоритм используете)
* если будут еще поля не строковых типов - их подключаем через bindValue с указанием типа
Тут сделано допущение, что подключение PDO уже настроен на бросание ошибок. В задачи репозитория не входит конфигурирование коннекшна.
По хорошему это дело еще и в транзакцию обернуть.
<?php
declare(strict_types = 1);

class UserRepository
{
    /** @var \PDO */
    private $pdo;

    /**
     * @param PDO $pdo
     */
    public function __construct(\PDO $pdo)
    {
        $this->pdo = $pdo;
    }

    /**
     * @param string $login
     * @param string $email
     * @param string $password
     * @return int
     * @throws \InvalidArgumentException
     * @throws \PDOException
     */
    public function insert(string $login, string $email, string $password): int
    {
        if (empty($login)) {
            throw new \InvalidArgumentException('Argument "$login" must be not empty');
        } elseif (empty($email)) {
            throw new \InvalidArgumentException('Argument "$email" must be not empty');
        } elseif (empty($password)) {
            throw new \InvalidArgumentException('Argument "$password" must be not empty');
        }

        $sql = '
        INSERT INTO `user`(
            `login`,
            `email`,
            `password`
        ) VALUES (
            :login,
            :email,
            :password
        )';

        $this->pdo->prepare($sql)->execute(
            [
                ':login' => $login,
                ':email' => $email,
                ':password' => $password
            ]
        );
        
        return (int) $this->pdo->lastInsertId();
    }
}
Ответ написан
Комментировать
@Jekshmek
кодер штродер
Могу добавить.Подготавливать запрос на каждую вставку не совсем экономично.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы