Разделение SQL, PHP и представления при перечислении категорий и продуктов в Kohana
-
19-09-2019 - |
Вопрос
Я хочу перейти на Kohana со своими небольшими веб-сайтами, и я пытаюсь разделить SQL, PHP и view, но с этим у меня возникли некоторые проблемы.
Мне нужно поговорить со столами.В каждой категории может быть несколько товаров.
Таблица категорий
- ID
- Категория
Таблица продуктов
- ID
- идентификатор категории_id
- продукт
Это был мой предыдущий код (преобразованный в конструктор запросов Kohana).:
$categories = DB::select('id', 'category')
->from('categories')
->as_object()
->execute();
foreach ($categories as $category)
{
echo '<b>'.$category->category.'</b><br />';
$products = DB::select('product')
->from('products')
->where('category_id', '=', $category->id)
->as_object()
->execute();
foreach($products as $product)
{
echo $product->product.'<br />';
}
echo '<hr />';
}
Я хочу сделать то же самое, только в файле просмотра, который я не хочу использовать, кроме повторения переменных.
Обновить: Я бы предпочел решение без использования модуля ORM от Kohana.Кстати, я использую Kohana 3.0
Обновление 2:
Я принял последнее решение Лукаша, но необходимо внести несколько изменений, чтобы сделать именно то, что я хотел (обратите внимание, что это для Kohana 3.0, в то время как Лукаш работал с более старой версией):
SQL - код:
$products = DB::select(array('categories.category', 'cat'), array('products.product', 'prod'))
->from('categories')
->join('products','RIGHT')
->on('products.category_id','category.id')
->as_object()
->execute();
Код в файле просмотра (см. Комментарии для пояснения):
// Let's define a new variable which will hold the current category in the foreach loop
$current_cat = '';
//We loop through the SQL results
foreach ($products as $product)
{
// We're displaying the category names only if the $current_cat differs from the category that is currently retrieved from the SQL results - this is needed for avoiding the category to be displayed multiple times
// At the begining of the loop the $current_cat is empty, so it will display the first category name
if($curren_cat !== $product->cat)
{
// We are displaying a separator between the categories and we need to do it here, because if we display it at the end of the loop it will separate multiple products in a category
// We avoid displaying the separator at the top of the first category by an if statement
if($current_cat !== '')
{
//Separator
echo '<hr />';
}
// We echo out the category
echo '<b>'.$product->cat.'</b><br />';
// This is the point where set the $current_cat variable to the category that is currently being displayed, so if there's more than 1 product in the category the category name won't be displayed again
$current_cat = $product->cat;
}
// We echo out the products
echo $product->prod.'<br />';
}
Я надеюсь, что это было полезно и другим, если у кого-нибудь есть решение получше, продолжайте, поделитесь им!
Решение
Это должно сработать:
$categories = ORM::factory('category')->find_all();
foreach ($categories as $category)
{
echo '<b>'.$category->category.'</b><br />';
$products = ORM::factory('product')->where('category_id',$category->id)->find();
foreach($products as $product)
{
echo $product->product.'<br />';
}
echo '<hr />';
}
Я предполагаю, что вы создали модели для каждой таблицы?Если нет, прочитайте здесь.
Лучше если вы разделяете слои данных и просмотра.И создайте связи между категориями и продуктами в файлах моделей.Затем в контроллере вы должны вызывать только это:
$categories = ORM::factory('category')->find_all();
$view = new View('yourView');
$viem->categories = $categories;
И в файле просмотра:
foreach ($categories as $category)
{
echo '<b>'.$category->category.'</b><br />';
foreach($category->products as $product)
{
echo $product->product.'<br />';
}
echo '<hr />';
}
Вам не придется вызывать 2-й запрос для каждой строки.Кохана ОРМ сделает это за тебя.Все, что вам нужно сделать, это создать соответствующие модели:
class Category_Model extends ORM {
protected $has_many = array('products');
}
class Product_Model extends ORM {
protected $belongs_to = array('category');
}
Другой подход: вы можете объединять таблицы категории и продукты
$products = DB::select('categories.category AS cat','products.product AS prod')
->from('categories')
->join('products','products.category_id','category.id')
->as_object()
->execute();
И тогда:
$current_cat = '';
foreach($products as $product)
{
if($current_cat != $products->cat)
{
echo '<b>'.$products->cat.'</b><br />';
$current_cat = $products->cat;
}
echo $product->prod.'<br />';
}
Другие советы
Просто короткая мысль:
При использовании ORM-подхода, я думаю, вы могли бы добиться того же, что и запрос соединения, используя метод with():
$products = ORM::factory('product')
->with('category')
->find_all();
$view = new View('yourView');
$viem->products = $products;
У меня не было достаточно времени, чтобы возиться с этим, но это то, что я бы попробовал.