Здравствуйте! Столкнулся с проблемой: Код (Text): Call to a member function query() on null in /home/home/web/site.ru/public_html/classes/user.class.php on line 40, referer: http://site.ru/index.php?do=register Разобрался в чем дело, в той функции, где ошибка идет на функцию запроса: PHP: public function register($username, $password, $ip, $email) { $db->query("INSERT INTO users SET user_login='".htmlspecialchars($username)."', user_password='".htmlspecialchars($password)."', user_ip='".$ip."', user_email='".htmlspecialchars($email)."'"); return true; } //Это метод регистрации в классе юзеров Не ссылается $db->query на объект. У меня пока что существует 2 класса, для работы с бд и юзерами. Так вот в классе с юзерами, как Вы видите, используются методы из класса бд. Вопрос, как подключить класс бд к классу юзеров? Вид index страницы у меня сейчас такой: PHP: include_once "classes/head/mysql.php"; $db = new db(); include_once "classes/user.class.php"; include_once "engine/register.php"; //В нем метод на регистрацию класса юзеров
Где тут глобальные переменные? Ещё вообще ничего не читал по этому поводу. Пытаюсь как-то ООП пока хоть немного понять. Есть хорошая литература на эту тему? А что, уязвимостей много?
$db у тебя глобальная переменная, судя по второму листингу, а в первом ты её не указываешь как global. Кстати, сообщение об ошибке с английского ты перевёл неверно --- Добавлено --- По поводу уязвимостей - традиционный, кем-то распространённый по рунету идиотизм, что нужно перед вставкой делать htmlspecialchars. Спрашивается, зачем, если база html не понимает? Экранировать надо те символы, которые база понимает и может понять ошибочно, а это функции типа mysqli_escape_string, PDO::quote, а также подготовленные запросы
Я не переводил ошибку, лишь погуглил причину её появления. И да, $db - не глобальная переменная, а объект, принадлежащий классу db --- Добавлено --- Спасибо за mysqli_escape_string
Вот тут ты не прав. $db - это глобальная переменная, содержащая ссылку на объект класса db. Доступ к объектам тоже осуществляется через переменные. В некоторых языках (C++, к примеру), объекты могут храниться прямо в переменных, а в других, как PHP, в переменных сохраняется только ссылка на объект
Советую поискать книги по PHP для начинающих, про ООП так же. Главное по свежее книги читать. http://phpfaq.ru/mysql/slashes
Не лучше ли через конструктор передавать объект БД. А то создавать такую зависимость не хорошо. PHP: class MyClass{ private $db; function __construct(\PDO $db){ $this->db = $db; } $db = new \PDO(); $class = new MyClass($db); Или воспользоваться паттерном проектирования Registry, Singleton
@mahmuzar, лучше. Хотя вы тоже создали зависимость. И с синглтоном или Registry зависимость всё равно будет. Но, лично я считаю, что если глобальных переменных 1-2, то это тоже не самое страшное. А челу тут не до паттернов. Я не буду рассказывать про паттерны человеку, который не знает, как пользоваться global.
Дополню ссылкой: http://ru.stackoverflow.com/questions/92217/Паттерн-singleton p.s. если в коде появляется global, то надо выкинуть его к чертям, обломать себе руки и уйти из профессии. Спорить на эту тему не буду )
@romach, не в качестве спора, но просто: в чём принципиальная разница между f1() и f2() PHP: function f1() { global $app; $app["db"]->query(/* ... */); } function f2() { \Yii::$app->db->createCommand(/* ... */)->execute(); } По мне, по барабану. --- Добавлено --- Первый подход, кстати, постоянно в Silex нужно использовать. В том или ином виде.
Короче с глобальными переменными тоже не хорошо делать? Придется разбираться в том, что Вы только что написали
@Stairdeck если глобальная переменная только одна, то это не так страшно, на мой взгляд. если больше 5 - то караул. romach дпугого мнения придерживается, но это мнение. Но можешь почитать про паттерны. Мэтт Зандстра. "PHP: объекты, шаблоны и методики программирования". Только боюсь, что для начала надо про язык ещё раз прочитать
@mkramer в данном примере - ни чем, кроме как лишней строчкой на каждом углу. В первом примере мы имеем контейнер с хорошо документированным интерфейсом доступа и юзекейсами. Кстати, я не любитель silex, но когда писал на нем, то обернул это дело, во имя удобства, автоподстоновок и отсутствия глобалов ) Может я резко выразился, речь шла про создание объекта класса, которое ты таскаешь за собой везде и всюду, пока где-нибудь он не затрется. Думаю ты и сам в курсе, в какой адский геморрой это может вылиться.
@romach мне лишь нужно, чтобы методы работы с базами данных работали в методах класса работы с пользователями. Как это можно реализовать с помощью синглотона?
хм... вообще, для работы с хранилищами данных нужно делать модели, которые в свою очередь не будут делать ничего, кроме предоставления интерфейса доступа. Сами действия и прочую бизнес-логику лучше выносить в сервисный слой, к которому и будет обращаться ваше приложение для выполнения нужных задач. Гуглить на тему "сервисный слой" / "service layer". p.s. тут нужно учитывать, что подходы бывают разные, спорные, со своими недостатками, достоинствами и областью применения. Лучше для начала займитесь синтаксисом языка, почитайте книжку, которую порекомендовал @mkramer и просто сделайте так что бы работало. Остальное придет с опытом.
Я понял, почему нужно использовать синглтон. Однако, я планирую только 1 раз вызывать $bd = new bd(); Не грешно использовать Глобал или все-таки попытаться реализовать через паттерн? И да, на счёт работоспособности. Все работает
На твоём уровне сойдёт и global. Хотя твой db легко можно и в синглтон преобразовать. С тобой тяжело говорить о таких вещах, поскольку ты ещё не настолько знаешь. Вон, @romach уже стал о моделях и сервисном слое говорить, я ты путаешься в простых вещах, типа что является переменной, а что нет. Короче, в этом проекте оставь как есть, а на будущее - почитай и про язык, и про паттерны, чтоб уже с тобой можно было на одном языке говорить.