Я хотел бы отобразить группу элементов в строке в php из базы данных mysql. Я уже сделал это, но мои данные появляются в одной длинной колонке. Я хотел бы, чтобы каждый новый элемент появлялся один рядом с другим.
Вот скриншот, что я получаю. Я бы хотел, чтобы первый был рядом со вторым:
http://img.ruphp.com/database/Capture.PNG?dl=0
Вот мой код:
<?php require_once 'core/init.php'; include 'includes/navigation.php'; $sql = "SELECT * FROM interviews WHERE featured = 1"; $featured = $db->query($sql); <html>
enter code here
enter code here
<link href="http://localhost/menu/css/academy.css" rel="stylesheet" `enter code here`type="text/css" />
<?php while($product = mysqli_fetch_assoc($featured)) : ?> <table> <tr> <th> <div id="element1"></div> <div id="content1"> <img src="<?= $product['image']; ?>" alt="<?= $product['title']; ?>"> <h4><?= $product['title']; ?></h4> <hr> <p class="description"><?= $product['description']; ?></p> <!--------BUTTON 3--------> <div id="hovers"> <a href="#" class="button"> <span class="contentbut"> Read More</span> </a> </div> </th> </tr> </table> <?php endwhile; ?> </div> </div>
Пожалуйста помоги.
Спасибо!
Примечание . В этом ответе подробно описывается создание многозадачных записей . Тем не менее, этот ответ может быть изменен, чтобы обеспечить компоновку с одной записью на одну строку .
Разделение проблем поможет вам написать более чистый код. Разделение проблем упростит работу с вашим кодом. Чистый код слабо связан , не загружается встроенными зависимостями. Чистый код определяет его зависимости в сигнатурах функций и конструкторах классов с ожиданием того, что эти потребности будут выполнены извне. Чистый код имеет плотное сцепление . Это означает, что функции / методы имеют одну задачу, а классы имеют одну цель. Чистый код часто отражается в задаче, которая была разбита и уточнена (но не всегда). Чистый код идеален, к чему я стремлюсь, но никто не идеален.
Попытайтесь придумать, как получить SQL и PHP из ваших HTML- файлов. Интерполяция переменных и отображение результатов результатов только могут сделать ваш HTML намного легче читать. Хорошая структура HTML тоже.
Очень возможно выполнение задачи динамического построения <table>
на основе результатов SQL-запроса. В конце концов, вы можете использовать CSS и divs для определения стиля и реакции. Этот код может быть изменен для достижения этого (в конце концов, вы просто будете складывать ящики в строки).
В конечном итоге создание класса ООП (с пользовательскими пространствами имен) было бы прекрасно для модуляции кода и получения подавляющего большинства ваших символов (имена переменных и т. Д.) Из глобального пространства имен .
Вы хотите настроить логическую архитектуру каталога для своего проекта?
Установите include_path
внутри php.ini
.
Если вы ищете свой php.ini
для параметра include_path
, вы можете установить его в один каталог или любую группу соответствующих каталогов. Таким образом, вы можете упорядочить свои файлы в каталогах так, как вы этого хотите, и ваши инструкции include
, include_once
, require
и require_once
все равно найдут файлы, которые они хотят импортировать. Вам не нужно вводить абсолютные пути, такие как /dir/dir/file.php
или относительные пути, такие как ../../core/database.php
. В обоих случаях вы можете просто указать имя файла.
Пример:
include 'file.php'; //Finds the file if it is in the include_path. require 'database.php'; //Finds the file if it is in the include_path.
Примечание . Храните файлы библиотеки и другие чистые файлы кода PHP (и т. Д.) Из веб-сайта или любых общедоступных каталогов. Держите их логически над веб-корнем. Установите include_path
чтобы вам не приходилось постоянно делать ../../blah/foo
все время.
1 ) Сначала создайте функцию для получения экземпляра объекта mysqli_result
.
/** * Returns a string, or * throws an UnexpectedValueException, otherwise. */ function isString($string) { if (!is_string($string)) { throw new UnexpectedValueException("$string must be a string data type."); } return $string; } /** * Returns a mysqli_result object, or throws an `UnexpectedValueException`. * You can reuse this for other SELECT, SHOW, DESCRIBE or EXPLAIN queries. */ function getMySQLiResult(MySQLi $db, $sql) { $result = $db->query(isString($sql)); if (!($result instanceof mysqli_result)) { throw new UnexpectedValueException("<p>MySQLi error no {$db->errno} : {$db->error}</p>"); } return $result; }
2 ) Во-вторых, создайте функцию для размещения вашего SQL и вызовите getMySQLiResult ().
/** * Make sure you can get the data first. * returns a mysqli_result object. */ function getInterviews(MySQLi $db) { $sql = "SELECT * FROM `interviews` WHERE `featured` = 1"; return getMySQLiResult($db, $sql); }
3 ) Создайте функцию для создания ячейки таблицы ( <td></td>
) и ее содержимого. Поместите все HTML или данные, которые вам нужно повторить для каждой записи .
/** * Returns one database table record a table data cell. */ function buildCell(array $record) { return "<td>\n". '<img src="' .$record['image']. '" alt="' .$record['title']. '">' ."\n". '<h4>' .$record['title']. '</h4>' . "\n" . '<hr>' . "\n" . '<p class="description">' .$record['description']. '</p>' . "\n" . '<div id="hovers"> <a href="#" class="button"> <span class="contentbut">Read More</span> </a> </div>' . "\n </td>\n"; }
4 ) Создайте функцию для построения строк таблицы. Будьте осторожны с частичными рядами. 🙂
Во-первых , небольшая вспомогательная функция.
/** * Returns one <tr></tr> element. Helper. */ function makeTr($tds) { return "<tr>\n" .isString($tds). "\n</tr>"; }
Во-вторых , реальная сделка.
function buildTableRow (array $tableRow) { return makeTr(buildCell($tableRow)) . "\n"; //Done! } /** * Returns a string of multiple <tr></tr> elements, * $maxRecords per row. */ function buildTableRows(array $tableRows, $numRecords, $maxPerRow) { $rows = []; // Holds finished groups of <tr>s $row = ''; // Temporary variable for building row of <td>s $numCells = 0; // Number of cells currently in a row of <td>s. $numRows = (int)($numRecords / $maxPerRow); //Rows to make. $numStragglers = $numRecords % $maxPerRow; // Extra <td>s, partialRow. if ($numStragglers !== 0) { //Check if extra row is needed. $numRows += 1; } foreach ($tableRows as $record) { $row .= buildCell($record); ++$numCells; if ($numCells === $numRecords) { // Builds partial, last row, if needed. $rows[] = makeTr($row); break; // Done! } if ($numCells === $maxPerRow) { // Builds full row. $rows[] = makeTr($row); // Save the row. $numCells = 0; // Start cell counter over. $row = ''; // Start a new row. } } if(count($rows) !== $numRows) { //Verify all rows were created. throw new RuntimeException("Rows (<tr>) for all records were not created!"); } return implode("\n", $rows) . "\n"; //Return all rows as a string. }
5 ) Сделайте функцию, которая выплескивает HTML-код, который вам нужен на вашей странице. В этом случае вам нужна только одна (1) подстановка, которая появится в HTML.
/** * returns a set of HTML table rows (<tr></tr>) to fill a <tbody>. * or, returns an alternative message. */ function drawInterviews(MySQLi $db, $maxPerRow) //PDO is recommened. Dependency injection. { $defaultMessage = "<tr>\n<td>There are no featured interviewers.<td>\n<\tr>\n"; try { if (!is_int($maxPerRow) || $maxPerRow < 1) { throw new RangeException("The number of interviews per row must be an integer equal to 1, or greater than 1."); } //Make a robust connection sequence, or pass it in like above. //$db = new mysqli('host', 'user', 'password', 'dbname'); $result = getInterviews($db); $numRecords = result->num_rows; if ($numRecords < 1) { return $defaultMessage; } if ($numRecords === 1) { return buildTableRow($result->fetch_assoc()); } return buildTableRows($result->fetch_all(), $numRecords, $maxPerRow); } catch (Exception $e) //Something went wrong with the query. error_log($e->getMessage()); } finally { //PHP 5.5+ $result->free(); } return $defaultMessage; }
6 ) Теперь у вас хорошая структура HTML <table>
. Требуется только одна интерполяция. Предполагая три <td>
s (записи) в строке …
В любом случае, если вы хотите таблицу, поместите копию этой таблицы «скелет» внутри academytest.php
, где-то между заголовком и нижним колонтитулом (т. academytest.php
Основным <body>
документа HTML).
<table> <caption>Featured Interviewers</caption> <!-- Centers above table. --> <thead> <tr> <!-- If needed. --> <th>Heading1</th> <!-- If needed. --> <th>Heading2</th> <!-- If needed. --> <th>Heading3</th> <!-- If needed. --> </tr> </thead> <tfoot></tfoot> <!-- If needed. Yes, it goes after <thead>. --> <tbody> <!-- <div id="element1"></div> --> //What goes between here? <!-- <div id="content1"> --> //What's this? <?= drawInterviews($db, 3); ?> <!-- Dependency injection. --> </tbody> </table>
Все это можно сделать более модульным и многоразовым (объектно-ориентированным, четным).
Основываясь на вашем коде Dropbox …
1 ) Лучше всего создать отдельный PHP-файл с именем tbodyFiller.php
или что-то в этом роде. Поместите все функции в этот файл, за исключением getInterviews()
и drawInterviews()
которые войдут в academyLibray.php
, isString()
которые перейдут в getMySQLiResult()
и getMySQLiResult()
которые getMySQLiResult()
в database.php
(ранее init.php
).
Начало academytest.php
должно выглядеть так:
<?php // academytest.php require '../../includes/library.php'; //For now, put generic helper functions here. Group them, later. require_once '../../core/database.php'; //Formerly, init.php. Put getMySQLiResult() in here. require '../../includes/academyLibrary.php'; //Put the two "interview" functions here. $db = getMySQLi(); //Many things are dependent on this being here. require '../../includes/navigation.php'; /***************** DELETE THESE LINES *****************/ //$sql = "SELECT * FROM interviews WHERE featured = 1"; //$featured = $db->query($sql); /******************************************************/
В нижнем колонтитуле academytest.php
закройте соединение с вашей базой данных.
<!-- ------FOOTER------ --> <?php include '../../includes/footer.php'; $db->close(); //Ensures $db is available to use in the footer, if necessary. ?>
Начало library.php
должно выглядеть так:
<?php // library.php /** * Returns a string, or * throws an UnexpectedValueException, otherwise. */ function isString($string) { if (!is_string($string)) { throw new UnexpectedValueException("$string must be a string data type."); } return $string; }
Я думаю, что init.php
следует назвать database.php
. Вы можете научиться использовать объектно-ориентированный конструктор (используя new
) последовательность с проверкой ошибок на досуге. В конце концов, вы захотите узнать PDO .
Кроме того, создайте отдельный файл для хранения ваших учетных данных. Прямо сейчас, это лучше, чем жесткое их кодирование в функции getMySQLi()
.
<?php // dbCreds.php $host = ''; //IP or DNS name: string. $username = ''; //Your account: string. $passwd = ''; //The password: string. $dbname = ''; //The database you want to work with: string. //************************************************************************* //$port = '3306'; //Un-comment and change only if you need a differnt TCP port. //Also, you would need to add a $port as your last argument in new MySQLi(), //in the getMySQLi() function.
<?php // database.php /** * Returns a mysqli_result object, or throws an `UnexpectedValueException`. * You can reuse this for other SELECT, SHOW, DESCRIBE or EXPLAIN queries. */ function getMySQLiResult(MySQLi $db, $sql) { $result = $db->query(isString($sql)); if (!($result instanceof mysqli_result)) { throw new UnexpectedValueException("<p>MySQLi error no {$db->errno} : {$db->error}</p>"); } return $result; } function getMySQLi() //This can be improved, but that's not the issue right now. { require_once 'dbCreds.php'; //Choose your own file name. Do not put in public directory. $db = new mysqli($host, $username, $passwd, $dbname); //$port would be next. if(!($db instanceof MySQLi)){ throw new UnexpectedValueException("A MySQLi object was not returned during your connection attempt."); } if(isset($db->connect_error)){ throw new UnexpectedValueException("The database connection was not established. {$db->connect_errno} : {$db->connect_error}"); } return $db } //Using the object form of MySQLi object has side benenfits.
Начало academyLibrary.php
должно выглядеть так:
<?php // academyLibrary.php require 'tbodyFiller.php'; //Put all but four functions in here. function getInterviews(MySQLi $db) { $sql = "SELECT * FROM `interviews` WHERE `featured` = 1"; return getMySQLiResult($db, $sql); } /** * Comments //etc... */ function drawInterviews(MySQLi $db, $maxPerRow) { //The code, etc ... }
Если вы не настроили свой include_path
внутри php.ini
, убедитесь, что academyLibrary.php
и tbodyFiller.php
находятся в одном каталоге.
Мы собираемся заменить процедурные формы работы с MySQL объектно-ориентированными. Это просто, и нам не нужно сильно меняться. Я не буду заменять ваши циклы или запросы в настоящее время, но мой совет – выйти из привычки помещать петли PHP и SQL непосредственно в ваш HTML. Найдите способ использования функции или метода, например, для таблицы в academytest.php
. К этому времени у вас должно быть достаточно примеров. 🙂
Рефакторинг
Я потратил некоторое время на реорганизацию этого файла. Вот что у меня на вершине. Еще раз , возможно, вы захотите создать еще один PHP-файл, например navLibrary.php
, и поместить в него эти функции. В этом случае вы замените все функции, указанные ниже, на одну строку, для которой require 'navLibrary.php';
, Естественно, этот способ импорта кода может зависеть от настройки вашего include_path
внутри php.ini
.
<?php // navigation.php function getPqueryMainData(MySQLi $db) { $sql = "SELECT * FROM `mainmenu` WHERE `parent` = 0"; //pqueryMain return getMySQLiResult($db, $sql); } function getPqueryData(MySQLi $db) { $sql = "SELECT * FROM `categories` WHERE `parent` = 0"; //pquery return getMySQLiResult($db, $sql); } function getCquery1Data(MySQLi $db) { $sql = "SELECT * FROM `categories` WHERE `parent` = 1"; //cquery1 return getMySQLiResult($db, $sql); } function getCquery2Data(MySQLi $db, $int) { $sql = "SELECT * FROM `categories` WHERE `parent` = '$int'"; //cquery2 return getMySQLiResult($db, $sql); } //Consider doing at most 3 queries early on. //Consider using better names for your variables. //I get that 'p' means "primary", and 'c' means "child", but come on. :-) $pqueryMain = getPqueryMainData($db); $pquery = getPqueryData($db); $cquery1 = getCquery1Data($db); $cquery2 = null;
В коде есть несколько проблем, например:
while()
. Вы используете те же идентификаторы div , element1
и content1
для всех ваших строк таблицы. Вместо этого используйте class
. Однако, исходя из вашего вопроса,
Я хотел бы, чтобы каждый новый элемент появлялся один рядом с другим.
Вы можете использовать атрибуты id
там, но вы должны взять все <table> ... <div id="content1">
и <div id="hovers"> ... </table>
из while()
. И, конечно же, изменить id="hovers"
на class="hovers"
и соответствующий CSS соответственно.
Таким образом, код решения будет выглядеть так:
<table> <tr> <div id="element1"></div> <div id="content1"> <?php while($product = mysqli_fetch_assoc($featured)){ ?> <td> <img src="<?= $product['image']; ?>" alt="<?= $product['title']; ?>"> <h4><?= $product['title']; ?></h4> <hr> <p class="description"><?= $product['description']; ?></p> <!--------BUTTON 3--------> <div class="hovers"> <a href="#" class="button"> <span class="contentbut"> Read More</span> </a> </div> </td> <?php } ?> </div> </tr> </table>
Из комментария OP ,
Я пытаюсь провести 3 интервью подряд и несколько строк с интервью.
Решение состояло бы в том, чтобы иметь три ячейки таблицы в каждой строке,
<table> <div id="element1"></div> <div id="content1"> <tr> <?php $counter = 1; while($product = mysqli_fetch_assoc($featured)){ if($counter % 4 == 0){ echo '</tr><tr>'; } ++$counter; ?> <td> <img src="<?= $product['image']; ?>" alt="<?= $product['title']; ?>"> <h4><?= $product['title']; ?></h4> <hr> <p class="description"><?= $product['description']; ?></p> <!--------BUTTON 3--------> <div class="hovers"> <a href="#" class="button"> <span class="contentbut"> Read More</span> </a> </div> </td> <?php } ?> </tr> </div> </table>