@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());
            }
        }
  • Вопрос задан
  • 273 просмотра
Пригласить эксперта
Ответы на вопрос 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
кодер штродер
Могу добавить.Подготавливать запрос на каждую вставку не совсем экономично.
Ответ написан
Комментировать
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы
19 апр. 2024, в 20:43
20000 руб./за проект
19 апр. 2024, в 20:11
500 руб./за проект