Добрый день. Начал осваивать ООП стиль, и вместе с этим переводить свой код в этот стиль. Возникла проблема с $mysqli->fetch_assoc. Выводит вот такую ошибку: Fatal error: Call to a member function fetch_assoc() on a non-object in. Надеюсь вы поможете решить проблему. Вот мой код: Код (Text): <?php abstract class db{ protected $table_name; function __construct(){ $mysqli = new mysqli("localhost","admin","pass","basa"); $res = $mysqli->query("SELECT * FROM `".$this->table_name."`"); } abstract function show(); } class indexNews extends db{ public function __construct(){ $this->table_name = 'contentindex'; parent::__construct(); } public function show(){ while($row = $res->fetch_assoc()){ echo" <div id='text-div'> <p class='content-tittle'>".$row['tittle']."</p> <p class='content-text' style='margin-bottom:0px;'>".$row['text']."</p> <p class='content-text' style='margin-left:450px;font-style:oblique;color:#898989;margin-bottom:5px;'>".$row['datatime']."</p> </div> ";} } } ?> И да скажите пожалуйста, говнокод ли это? Дабы знать как делать нельзя, спасибо. =)
Рано вам код на ООП переводить, освойте, для начала, чем локальная переменная отличается от глобальной Функция indexNews::show() ну никоим образом не может обратиться к переменной, определённой внутри функции db::__construct(). Про бредовость вашей иерархии классов даже и не говорю
Если вы только начали осваивать ООП, вам совершенно незачем сразу создавать абстрактный класс и его наследника. Сделайте сначала нормальный работающий класс для работы с конкретной БД, а потом, если уж захотите, можете его экстраполировать на всякое.
Ну о чём вообще может быть речь? Тут наследованием вообще не пахнет. Наследование - это отношение "частное-общее", к примеру, круг является фигурой. А что тут? Новости являются базой данных? Не являются. Тут отношение использования должно быть - indexNews использует базу данных, чтоб получить данные. Но прежде чем о таких вещах говорить, надо усвоить базу - переменные, типы данных (хотя бы в том виде, в каком они в нашем любимом PHP), функции, области видимости и т.п.
Насколько я понял, в итоге получилось, что классы не правильно спроектированы, и надо побольше почитать про ООП? Если так то, не могли бы вы поточнее рассказать, что надо переделать. Спасибо. Добавлено спустя 11 минут 36 секунд: Спасибо, попробую.
In_The_Real, ну вот сейчас в одном посте перескажу вам Гради Буча Да, ООП - это отдельная тема. Надо читать не только про ключевые слова, которые в языке позволяют более удобно использовать ООП (кстати, если бы их и не было, всё равно можно было бы написать ОО-программу). Надо понять, зачем разделять программу на объекты, зачем используется наследование и т.п. Прежде всего, объекты должны браться из предметной области задачи, затем разрабатываются всякие чисто сервисные объекты, типа работы базами данных. Потом выделяются классы, являющиеся своеобразными шаблонами для объектов. Короче, это тема для большой книги, а не поста на форуме. Но судя по вашему вопросу, вы не только ООП не понимаете, а куда более простые вещи
Нет простые вещи мне ясны. Просто вы назвали бредовыми наследования, т.е весь код =) Ну вот я и хотел бы узнать что не так, дабы не наступать на одни и те же грабли. Добавлено спустя 2 минуты 54 секунды: И да, я так понял вы очень хорошо разбираетесь в этом всем. Не могли бы вы мне сказать годная ли информация про ООП на этом сайте http://true-coder.ru/oop-v-php/oop-v-php-vvedenie.html ? XD Добавлено спустя 7 секунд: И да, я так понял вы очень хорошо разбираетесь в этом всем. Не могли бы вы мне сказать годная ли информация про ООП на этом сайте http://true-coder.ru/oop-v-php/oop-v-php-vvedenie.html ? XD
У тебя новости наследуются от БД-адаптера. Зачем? Хочешь использовать методы БД-адаптера в ноаостях? Создай его экземпляр и дергай методы из него. Это логика обычная.
Вот классика по ООП: http://rutracker.org/forum/viewtopic.php?t=3343958. Гради Буч - один из создателей UML, языка проектирования объектных систем. Я не считаю, что я хорошо разбираюсь в ООП, но, по меньшей мере, знаю, к чему стремиться. Про то, что вы не очень понимаете простые вещи, я решил, поскольку вы серьёзно пытаетесь дёргать значение локальной переменной, созданной в одной функции, из другой.
скачал, отличная книга, но есть термины которые непонятны, буду гуглить Добавлено спустя 10 минут 35 секунд: Упростил как мог. Код (Text): class general{ public $table_name; public $row; function teach(){ $mysqli = new mysqli("localhost","admin","pass","basa"); $result = $mysqli->query("SELECT * FROM `contentindex`"); $row = $result->fetch_assoc(); echo $row['tittle']; } } И как мне теперь ПРАВИЛЬНО прикрутить наследования? =) многомилионный раз извиняюсь за тупые вопросы
Ну вот почитайте книгу. Сначала надо понять, какую задачу вы пытаетесь решить классами. Наследование - не самоцель. Иногда, для не слишком сложных задач, оно вообще не требуется. Вот я недавно сделал модуль фотоконкурса для Instant CMS, вот там наследование практически не используется, поскольку всё укладывается в другие типы отношений - агрегирование (объекты одного класса являются частью объектов другого класса), использование. Вообще, наследование - это самая сильная связь между классами, поэтому злоупотреблять им тоже нельзя. Лакмусовую бумажку наследования я вам уже написал - если можно сказать, что класс B является разновидностью класса A, тогда и только тогда класс B нужно наследовать от класса А. Самый яркий пример - геометрические фигуры. От класса Figure наследуются Circle, Rectangle и т.п. Потому что в принципе, со объектами этих классов можно обращаться как с фигурами. Вот пример ближе к нашей тематике - многие фреймворки, некоторые CMS позволяют работать с базами данных через разные расширения php (mysql, mysqli, PDO). Но в любом случае, через какое бы расширение они не работали с базой, делать они будут с ней одно и тоже - посылать запросы, получать данные. Поэтому делается базовый класс DB_Adapter, который ничего не умеет, зато декларирует, как именно можно с ним обращаться, и ряд классов для работы с конкретными расширениями, типа Mysqli_DB_Adapter, PDO_DB_Adapter и т.п., которые наследуются от DB_Adapter, и реализуют описанное в нём поведение. И с экземпляром каждого из них можно обращаться как с DB_Adapter, поскольку все они являются адаптарами базы. Таким образом теперь можно просто прописать в конфиге этого фреймворка или CMS, через какое расширение предпочитаешь работать с базой, и, фреймворк сам будет использовать нужный класс, а код менять не нужно. Теоретические, можно даже написать что-то совершенно своё, например XML_DB_Adapter, и использовать базы на XML файлах... То, что вы сейчас пытаетесь делать, к ООП никакого отношения не имеет - вы обычные функции оборачиваете в классы, не используя ни один из принципов ООП.
Внимание вопрос - а зачем тебе тут вообще наследование? Наследовение ради наследования, шоб було? Чтобы код был на 13% ООПешнее? Избегай использования технологий ради самих технологий. Тебе тут никакое наследование просто не нужно. Будет нужно - тогда и используй.
Наследование нужно мне потому что помимо класса indexNews будет еще один класс который тоже ифу но немного другую. То есть главный класс с подключением, и выборкой из неизвестной таблицы неизвесто чего, другие производные классы, подключаются и выбирают что то определенное, но каждый вывод немного другое и немного подругому. И вот мне кажется что так и надо делать в ООП. Наверное, я ошибался? =) Добавлено спустя 13 минут 6 секунд: Хмм, я правильно понял ваше объяснение агрегирования? Что что-то базовое (DB_Adapter) состоит из (Mysqli_DB_Adapter, PDO_DB_Adapter)?
Вообще-то, я целый пост вам написал про наследование... Там даже везде написано "наследуется". Ещё там жирным выделено является. PDO_DB_Adapter является одной из разновидностей DB_Adapter. Агрегирование - это один объект имеет другие. Например, у окна есть элементы управления, являющиеся его частью. Может ещё быть использование - что в вашем случае как раз должно быть - indexNews использует db, чтоб получить новости из базы. ПРо агрегирование только в начале поста написано, что я сделал проект, в котором не было наследования, поскольку у классов и их объектов не было отношение "частное-общее". По поводу вашего вопроса - расскажите подробнее, что за задачу вы пытаетесь решить? Может вам вашем примере удастся объяснить, раз вы книжку не читаете... Добавлено спустя 10 минут 44 секунды: Т.е. вы хотите объединить ряд классов по принципу, что все они используют БД, так что-ли?
"По поводу вашего вопроса - расскажите подробнее, что за задачу вы пытаетесь решить? Может вам вашем примере удастся объяснить, раз вы книжку не читаете..." - Книжку то я читаю. Просто я её читаю с самого начала и понемногу (так получается). А задача такова, я делаю сайт для игрового сервера, естественно не обойтись без взаимодействия с БД. И я хочу сделать, на index.php вывод новостей, на страницы забаненых вывод списка забаненых из БД + хочу сделать админ панель. Вот так. И я думал что нашел решение немного прочитав про полиморфизм. Но оказалось это не так. Добавлено спустя 5 минут 28 секунд: Почти. Но каждый будет это делать немного по-своему и выводить немного другое. Охх, чувствую я что вообще не так делать начал =)
Да, видимо, куда-то не туда. Ну вот один из хрестоматийнейших вариантов - метод, который по переданной строке запроса лезет в базу, выполняет запрос и возвращает данные в виде массива. Создаете класс, например, db, создаете в нем такой метод, например, fetchAll, а потом в index.php вызываете: $db = new db(); $news = $db->fetchAll('select * from news'); А на странице забаненных: $db = new db(); $banned = $db->fetchAll('select * from banned_users'). Как-то так, архитектура тоже не идеальна, но уже ближе к истине. Кстати говоря, для работы с БД обычно создают класс-синглтон, это позволяет обращаться к функциям класса без создания непосредственно экземпляра класса.
Я понял лишь то что это такой класс который не разрешает повторное создание своего экземпляра. И все.
Ну в этом суть синглтона, да. Иногда полезно - позволяет избежать нужной в противном случае глобальной переменной. Хотя использовать его для базы данных не всегда интересно - у меня были проекты, в которых я работал с несколькими базами единовременно. Я примерно представляю, что вы хотите сделать, такая архитектура действительно имеет место быть во фреймворках и т.п. Я её не люблю, кстати. Что-то вроде этого: Код (PHP): class repository { private $db; protected $table_name = ''; public function __construct($db) { $this->db = $db; } public function get_all() { $res = $this->db->query("select * from $this->table_name"); $elems = $res->fetch_all(); $res->free(); return $elems; } } class news_repository extends repository { protected $table_name="news"; } $db = new mysqli(HOST, USER, PASS, DB_NAME); $news = new news_repository($db); foreach ($news->get_all() as $news) var_export($news);
Слава богу, хоть со мной еще не все потеряно =) Код (Text): class repository { private $db; protected $table_name = ''; public function __construct($db) { $this->db = $db; } public function get_all() { $res = $this->db->query("select * from $this->table_name"); $elems = $res->fetch_all(); $res->free(); return $elems; } } class news_repository extends repository { protected $table_name="news"; } $db = new mysqli(HOST, USER, PASS, DB_NAME); $news = new news_repository($db); foreach ($news->get_all() as $news) var_export($news); Я так понимаю, это примерный код который мне следует использовать?
Один из вариантов, да. Естественно, очень сильно упрощённый. Так иногда делают. Тут развить конечно надо будет класс абстрактного репозитория, дабы он умел добавлять к запросам where, limit и прочее.