I am creating an ecommerce, which can have Men’s Fashion, Women’s Fashion or Children’s Fashion, it could also have more in the fure like Sports, Electronics, etc.
But I don’t know if I have, for example, to repeat the categories clothes, etc for each one or not, I don’t know if there is a better way. Since I must also create the dynamic menu
My table structure is like this:
CREATE TABLE `category`( `category_id` smallint(3) unsigned not null auto_increment primary key, `category_name` VARCHAR(40) NOT NULL, `category_url` VARCHAR(40) NOT NULL, `icon`varchar(150) default null, `gender` enum('Men','Woman','Baby') default null, `parent` INT DEFAULT NULL )engine=InnoDB default charset=utf8mb4 collate=utf8mb4_spanish_ci;
Some posible inserts what i want:
INSERT INTO `category` (`category_id`, `category_name`, `category_url`, `icon`, `gender`, `parent`) VALUES -- Mens section (1, 'Mens Fashion', 'mens-fashion', null, null, null), -- Mens fasion -- clothes mens (2, 'Clothing', 'clothing', 'clothing.svg', null, 1), -- (level 2) (3, 'Shoes', 'Shoes', 'shoes.svg', null, 1), -- (level 2) (4, 'Complements', 'complements', 'complements.svg', null, 1), -- (level 2) (5, 'Shirts', 'shirts', null, null, 2), -- (level 3) (6, 'Casual shirts', 'casaul-shirts', null, null, 5), -- (level 4) (7, 'Suit shirts ', 'suit-shirts', null, null, 5), --(level 4) (8, 'Jeans', 'jeans', null, null, 2), -- (level 3) (9, 'Jeans skinny', 'jeans-skinny', null, null, 8), -- (level 4) (10, 'Jeans slim fit', 'jeans-slim-fit', null, null, 8), -- (level 4) (11, 'Underwear', 'Underwear', null, null, 2), -- (level 3) (12, 'Socks', 'socks', null, null, 11), -- (level 4) -- Woman section (13, 'Woman Fashion', 'woman-fasion', null, null, null), -- (level 1) -- Clothes woman (14, 'Clothing', 'clothing', 'clothing.svg', null, 13), -- (level 2) (15, 'Shoes', 'Shoes', 'shoes.svg', null, 13), -- (level 2) (16, 'Complements', 'complements', 'complements.svg', null, 13), -- (level 2) (17, 'Shirts', 'shirts', null, null, 13), -- (level 3) (18, 'Casual shirts', 'casaul-shirts', null, null, 17), -- (level 4) (19, 'Suit shirts', 'suit-shirts', null, null, 17), -- (level 4) (20, 'Top shirt', 'top-shirt', null, null, 17), -- (level 4) (21, 'Jeans', 'jeans', null, null, 13), -- (level 3) (22, 'Jeans skinny', 'jeans-skinny', null, null, 21), -- (level 4) (23, 'Jeans slim fit', 'jeans-slim-fit', null, null, 21), -- (level 4) (24, 'Underwear', 'Underwear', null, null, 13), -- (level 3) (25, 'Socks', 'socks', null, null, 24), -- (level 4) -- Childeren section (13, 'Childerens Fasion', 'childeren-fashion', null, null, null), -- (level 1) -- Clothes childeren etc..
It’s that ok what I’m doing, repeat for each section the same categories as clothes, Jeans, etc.?
I really do this because otherwise I don’t know how to create the menu gives the image that I leave below
Another question i have.
I am creating this menu, with said table, which is what I want to obtain.
Is there any way to get the url in this way:
mens-fashion/clothing/shirts
because for example shirts would be the url above.
So what i mean, if the category is level 4, the url would be: level1/level2/level3/level4.
What would be better:
To add it directly to my table the absolute path or
can i do that with PHP, i leave the code that I am using.
$categories = $db->query('SELECT category_id, category_url, parent, category_name FROM category ORDER BY category_id'); $cat = $categories->fetchAll(PDO::FETCH_ASSOC); $arrayMenu = array(); foreach($cat as $row){ $arrayMenu[$row['category_id']] = array("parent" => $row['parent'], "category_name" => $row['category_name'], "category_url" => $row['category_url']); } function createTree($array, $curParent, $currLevel = 0, $prevLevel = -1) { foreach ($array as $categoryId => $category) : if ($curParent == $category['parent']) : if($category['parent']==0) $class="dropdown"; else $class="sub_menu"; if ($currLevel > $prevLevel) echo " <ul class='$class'> "; if ($currLevel == $prevLevel) echo " </li> "; echo '<li id="'.$categoryId.'" ><a href="'.$category['category_url'].'">'.$category['category_name'].'</a>'; if ($currLevel > $prevLevel) { $prevLevel = $currLevel; } $currLevel++; createTree ($array, $categoryId, $currLevel, $prevLevel); $currLevel--; endif; endforeach; if ($currLevel == $prevLevel) echo " </li> </ul> "; } ?> <div class="nav"> <?php if ($cat != null) createTree($arrayMenu, 0); ?>
I tried to add this line to get, for example, the level 1 url, but it doesn’t:
$url_level1 = ($row['parent'] == 0) ? $row['category_url'] : '';
Edit:
The css with which I was testing: (It doesn’t really have styles and it’s outdated)
nav ul li { background:#f1f1f1; list-style: none; } ul.dropdown { position:relative; width:auto; font:12px Arial, Helvetica, sans-serif; } ul.dropdown li { float:left; zoom:1; height:auto; min-height: 30px; padding:6px 2px 0 2px; } ul.dropdown li li { border-right:1px solid #ccc; border-left:1px solid #ccc; margin-left:-30px; } ul.dropdown a:hover { color:#000; } ul.dropdown a:active { color:#ffa500; } ul.dropdown li a { display:block; padding:4px 8px; color:#000; text-decoration:none; font:bold 12px Arial, Helvetica, sans-serif; } ul.dropdown li:last-child a { border-right:none;} /* Doesn't work in IE */ ul.dropdown li:hover { color:#000; background:#e7e7e7; position:relative; } ul.dropdown li.hover a { color:#000; } ul.dropdown ul { text-align:left; visibility: hidden; position: absolute; left:-10px; top:36px; } ul.dropdown ul li { background:#f1f1f1; border-bottom:1px solid #ccc; float:none; width:120px; height:auto; min-height: 25px; } ul.dropdown ul li a { border-right:none; width:100%; display:inline-block; color:#000; } ul.dropdown ul ul { left:100%; top:0; } ul.dropdown li:hover > ul { visibility:visible; }
Note: What I realy was creating was something like this:
// Tab header /////// function openPage(pageName, elmnt, color) { // Hide all elements with class="tabcontent" by default */ var i, tabcontent, tablinks; tabcontent = document.getElementsByClassName("tabcontent"); for (i = 0; i < tabcontent.length; i++) { tabcontent[i].style.display = "none"; } // Remove the background color of all tablinks/buttons tablinks = document.getElementsByClassName("tablink"); for (i = 0; i < tablinks.length; i++) { tablinks[i].style.background = ""; } // Show the specific tab content document.getElementById(pageName).style.display = "block"; // Add the specific color to the button used to open the tab content elmnt.style.background = color; } // Get the element with id="defaultOpen" and click on it document.getElementById("defaultOpen").click(); // Accordion /////// var acc = document.getElementsByClassName("accordion"); var i; for (i = 0; i < acc.length; i++) { acc[i].addEventListener("click", function() { this.classList.toggle("active"); var panel = this.nextElementSibling; if (panel.style.maxHeight) { panel.style.maxHeight = null; } else { panel.style.maxHeight = panel.scrollHeight + "px"; } }); }
/* TAB HEADER MENU */ #wrapper-tablink { display: flex; flex-flow: row nowrap; justify-content: center; align-items: center; } /* Style tab links */ .tablink { background-color: #555; color: white; border: none; outline: none; cursor: pointer; padding: 14px 16px; font-size: 17px; width: 25%; } .tablink:hover { background-color: #777; } .tablink .active { color: #000; } /* Style the tab content (and add height:100% for full page content) */ .tabcontent { color: white; display: none; padding: 100px 20px; height: 100%; overflow-y: auto; } /* #moda-mujer {background-color: var(--secundary-color);} #moda-hombre {background-color: #00cc99;} #electronica {background-color: #3399ff;} #cursos {background-color: #9933ff;} */ .wrapper-icons-bars { display: flex; flex-flow: row nowrap; justify-content: center; align-items: center; margin: 10px 0 20px 0; } .wrapper-icons-bars a { display: block; position: relative; background-color: #FFFFFF; border-bottom: 3px solid var(--body-color); border-right: 1px solid #F1F1F1; padding: 20px; transition: all 0.3s ease; } .wrapper-icons-bars a:hover { display: block; position: relative; border-bottom: 3px solid var(--secundary-color); padding: 25px; transition: all 0.3s ease; } /* ACCORDIAN CONTENT */ .wrapper-accordion { display: flex; justify-content: center; width: 100%; margin-bottom: 80px; } .accordion { display: flex; position: relative; justify-content: center; align-items: center; background-color: #eee; color: #444; cursor: pointer; padding: 18px; width: 100%; max-width: 500px; min-width: 500px; border: none; text-align: left; outline: none; font-size: 15px; transition: 0.4s; } .active, .accordion:hover { background-color: #ccc; } .accordion:after { content: '02B'; color: #777; font-weight: bold; display: block; position: absolute; right: 25px; margin-left: 5px; } .active:after { content: "2212"; } .panel { background-color: white; color: var(--body-color); max-height: 0; width: 100%; overflow: hidden; transition: max-height 0.2s ease-out; } .inner-panel { padding: 20px 20px; width: 100%; max-width: 500px; } .wrapper-accordion a { color: var(--body-color); }
<!-- Create Tab links header (Table: controllers) --> <div id="wrapper-tablink"> <button class="tablink" onclick="openPage('mens-fashion', this, 'blue')" id="defaultOpen">Mens Fashion</button> <button class="tablink" onclick="openPage('womans-fashion', this, 'red')" id="defaultOpen">Womans Fashion</button> </div> <div id='mens-fashion' class='tabcontent' style='blue'> <article class='wrapper-accordion'> <div> <h2><a href='mens-fashion/clothes'>Clothes</a></h2> <div class='wrapper-icons-bars'>icons</div> <button class='accordion active'>Clothes</button> <div class='panel' style='max-height: 1000px;'> <div class='inner-panel'> <h5><a href='mens-fashion/clothes'>Clothes</a></h5> <a>Tshirt </a> </div> </div> <button class='accordion'>Shoes</button> <div class='panel'> <div class='inner-panel'> <h5><a href='mens-fashion/shoes'>Shoes</a></h5> <a>Deport shoes </a> </div> </div> <button class='accordion'>Complements</button> <div class='panel'> <div class='inner-panel'> <h5><a href='mens-fashion/complemnts'>Shoes</a></h5> <a>Clock </a> </div> </div> </div> </article> </div> <div id='womans-fashion' class='tabcontent' style='red'> <article class='wrapper-accordion'> <div> <h2><a href='womans-fashion/clothes'>Clothes</a></h2> <div class='wrapper-icons-bars'>icons</div> <button class='accordion active'>Clothes</button> <div class='panel' style='max-height: 1000px;'> <div class='inner-panel'> <h5><a href='womans-fashion/clothes'>Clothes</a></h5> <a>Tshirt </a> </div> </div> <button class='accordion'>Shoes</button> <div class='panel'> <div class='inner-panel'> <h5><a href='womans-fashion/shoes'>Shoes</a></h5> <a>Deport shoes </a> </div> </div> <button class='accordion'>Complements</button> <div class='panel'> <div class='inner-panel'> <h5><a href='womans-fashion/complemnts'>Shoes</a></h5> <a>Clock </a> </div> </div> </div> </article> </div>
Advertisement
Answer
It’s that ok what I’m doing, repeat for each section the same categories as clothes, Jeans, etc.?
Yes, It’s perfectly okay to do that. Personally, that is what I prefer.
What would be better: To add it directly to my table the absolute path or can i do that with PHP
You can easily achieve it with PHP.
Kindly use these functions to generate the markup for the nested categories. You can modify the HTML to achieve your desired results.
// convert the categories array to parents with nested children function convertToLevels ($array) { // First, convert the array so that the keys match the ids $reKeyed = array(); foreach ($array as $item) { $reKeyed[$item['category_id']] = $item; } // Next, use references to associate children with parents foreach ($reKeyed as $id => $item) { if (isset($item['parent'], $reKeyed[$item['parent']])) { $reKeyed[$item['parent']]['children'][] =& $reKeyed[$id]; } } // Finally, go through and remove children from the outer level foreach ($reKeyed as $id => $item) { if (isset($item['parent'])) { unset($reKeyed[$id]); } } return $reKeyed; } // create menu li function createMenuItem($item, $url){ $html = ''; $html .= '<li class="menu-item '.(!empty($item['children']) ? 'has-child' : '').'">'; $html .= '<a href="'.$url.'" class="menu-link">'; if(!empty($item['icon'])): $html .= '<i class="'.$item['icon'].'"></i>'; endif; $html .= $item['category_name']; $html .= '</a>'; if(!empty($item['children'])): $html .= createMenu($item['children'], $url); endif; $html .= '</li>'; return $html; } // menu function createMenu($menu, $url_prefix=''){ $html = ''; $html .= '<ul class="menu">'; foreach($menu as $item): $html .= createMenuItem($item, $url_prefix.'/'.$item['category_url']); endforeach; $html .= '</ul>'; return $html; }
You can use it like so
$categories = $pdo->query('SELECT category_id, category_url, parent, category_name FROM category ORDER BY category_id'); $cat = convertToLevels($categories->fetchAll(PDO::FETCH_ASSOC));
Then in the HTML
<?= createMenu($cat); ?>
To get part of the menu example Mens Fashion, you just have to filter the $cat
array to get it. Example
$men_cat = array_values(array_filter($cat, function($val){ return strtolower($val['category_name']) === 'mens fashion'; }))[0]['children'] ?? [];
Then in the HTML
<?= createMenu($men_cat, '/mens-fashion'); ?>