How to add additional values in to array - php

I am trying to make nested categories in Laravel. I have created following models: Category.php, ItemsHelper.php (this one for displaying nested categories).
ItemsHelper.php:
class ItemsHelper {
private $items;
public function __construct($items) {
$this->items = $items;
}
public function htmlList() {
return $this->htmlFromArray($this->itemArray());
}
private function itemArray() {
$result = [];
foreach($this->items as $item) {
if ($item->parent_id == 0) {
$result[$item->title] = $this->itemWithChildren($item);
}
}
return $result;
}
private function childrenOf($item) {
$result = [];
foreach($this->items as $i) {
if ($i->parent_id == $item->id) {
$result[] = $i;
}
}
return $result;
}
private function itemWithChildren($item) {
$result = [];
$children = $this->childrenOf($item);
foreach ($children as $child) {
$result[$child->title] = $this->itemWithChildren($child);
}
return $result;
}
private function htmlFromArray($array) {
$html = '';
foreach($array as $k => $v) {
$html .= "<ul>";
$html .= "<li>" . $k . "</li>";
if(count($v) > 0) {
$html .= $this->htmlFromArray($v);
}
$html .= "</ul>";
}
return $html;
}
}
Then i am printing nested list of data in my index.blade.php:
{{ $itemsHelper->htmlList() }}
However this prints only plain titles and i need to convert them in to a links to my category, e.g. htmlFromArray() method:
$html .= "<li>" . $k . "</li>";
method itemArray():
$result[$item->title] = $this->itemWithChildren($item);
How can i add to this array id of each item?

You should probably change methods itemArray, itemWithChildren and htmlFromArray this way:
private function itemArray()
{
$result = [];
foreach ($this->items as $item) {
if ($item->parent_id == 0) {
$record['title'] = $item->title;
$record['id'] = $item->id;
$record['children'] = $this->itemWithChildren($item);
$result[] = $record;
}
}
return $result;
}
private function itemWithChildren($item)
{
$result = [];
$children = $this->childrenOf($item);
foreach ($children as $child) {
$record['title'] = $child->title;
$record['id'] = $child->id;
$record['children'] = $this->itemWithChildren($child);
$result[] = $record;
}
return $result;
}
private function htmlFromArray($array)
{
$html = '';
foreach ($array as $item) {
$html .= "<ul>";
$html
.=
'<li><a href="/category/' . $item['id'] . '">' . $item['title']
. "</a></li>";
if (count($item['children']) > 0) {
$html .= $this->htmlFromArray($item['children']);
}
$html .= "</ul>";
}
return $html;
}
Now you can store in your arrays id, title and list of element children so you can access iun htmlFromArray all those elements attributes.

Related

Yii2 recursion of the tree menu?

Good night all! Help please in the recursion, where I made a mistake, I need to output the categories, as in the last example!
Model:
protected function buildTree($data, $rootID = 0)
{
$tree = [];
foreach ($data as $id => $node) {
if ($node->parent_id == $rootID) {
unset($data[$id]);
$node->childs = $this->buildTree($data, $node->id);
$tree[] = $node;
}
}
return $tree;
}
public function getTree()
{
$data = Category::find()->all();
return $this->buildTree($data);
}
View:
<?php $form = ActiveForm::begin()
foreach ($tree as $cat) {
echo '<br><div class="spoiler-title">' . $cat['title'] . '</div>';
printNode($cat);
}
function printNode($cat, $level = 1)
{
if (count($cat['childs']) > 0) {
foreach ($cat['childs'] as $child) {
for ($j = 1; $j < $level; $j++) {
echo '------- <b>';
}
echo '' . $child['title'] . '</b><br>';
//echo $form->field($model, $child['title'])->checkbox();
//I want to do a checkbox, get an error, do not understand $
//form and $ model
if (count($child['childs']) > 0) {
printNode($child, $level + 1);
}
}
}
}
$form = ActiveForm::end() ?>
That's how I get the tree, this is with your code
root
category
category
category
---- <b>subcategory</b
---- <b>subcategory</b
---- <b>subcategory</b
---- <b>subcategory</b
category
category
I need to make checkboxes in subcategories, but I get an error, in the code I wrote in the comments, your code works, but I can not change it my needs as a picture.
You should also add recursion in view when you print tree.
Try this in view:
$form = \yii\bootstrap\ActiveForm::begin();
foreach ($tree as $cat) {
printNode($cat);
}
function printNode($cat, $level = 1) {
echo '<br><div class="spoiler-title">' . $cat['title'] . '</div>';
if (count($cat['childs']) > 0) {
foreach ($cat['childs'] as $child) {
echo \yii\helpers\Html::checkbox('someName[]') . ' ' . $child['title'] . '<br>';
if (count($child['childs']) > 0) {
printNode($child, $level + 1);
}
}
}
}
\yii\bootstrap\ActiveForm::end();

How to filter the children for it's parents from a tables in PHP

I've created a products categories tables which contain data here in this table have both parent and it children by the ways I'm doing is work as well but it simply messy and not much better with many function that I have to call for each categories levels so I want to get some help to find out the better and easy way to filter all it children and get the same as below images result.
I think function that I have create really the same so it should have some better way revise and make it better than this one.
Here is my Helper function
<?php
namespace app\Helpers;
use App\Http\Controllers\Admin\AdminController;
final class Helper extends AdminController
{
public function setData($data)
{
return $this->data = $data;
}
final public function GetCats($selection = null, $name = null)
{
$html = '<select name="'.$name.'" class="'.$selection.'" >';
foreach ($this->data as $key => $cats) {
if ((int)$cats->parent_id === 0) {
foreach ($cats->CategoryDescriptions as $d) {
$html .= '<option>';
$html .= $d->name.$this->getChild1($cats->id, $d->name);
$html .= '</option>';
}
}
}
$html .= '</select>';
echo $html;
}
private function getChild1($category_id, $parentName) //-->
{
$childs = '';
foreach ($this->data as $child) {
if ((int)$child->parent_id == (int)$category_id) {
foreach ($child->CategoryDescriptions as $d) {
$childs .= '<option>' .$this->myspace(). $parentName . ' -> ';
$childs .= $d->name.$this->getChild2($child->id,$parentName, $d->name);
$childs .= '</option> ';
}
}
}
return $childs;
}
private function getChild2($category_id,$parentName,$name1) //-->
{
$childs = '';
foreach ($this->data as $child) {
if ((int)$child->parent_id == (int)$category_id) {
foreach ($child->CategoryDescriptions as $d) {
$childs .= '<option>'.$this->myspace().$parentName.' --> '.$name1.' --> ';
$childs .= $d->name.$this->getChild3($child->id, $parentName, $name1,$d->name);
$childs .= '</option>';
}
}
}
return $childs;
}
private function getChild3($category_id, $parentName, $name1,$name2) //-->
{
$childs = '';
foreach ($this->data as $child) {
if ((int)$child->parent_id == (int)$category_id) {
foreach ($child->CategoryDescriptions as $d) {
$childs .= '<option>'.$this->myspace().$parentName.' --> '.$name1.' --> '.$name2.' --> ';
$childs .= $d->name.$this->getChildn4($child->id, $parentName, $name1,$name2,$d->name);
$childs .= '</option>';
}
}
}
return $childs;
}
private function getChildn4($category_id, $parentName, $name1, $name2,$name3) //-->
{
$childs = '';
foreach ($this->data as $child) {
if ((int)$child->parent_id == (int)$category_id) {
foreach ($child->CategoryDescriptions as $d) {
$childs .= '<option>'.$this->myspace().$parentName.' --> '.$name1.' --> '.$name2.' --> '.$name3.' --> ';
$childs .= $d->name.$this->getChildn5($child->id, $parentName, $name1,$name2,$name3,$d->name);
$childs .= '</option>';
}
}
}
return $childs;
}
private function getChildn5($category_id, $parentName, $name1, $name2, $name3,$name4) //-->
{
$childs = '';
foreach ($this->data as $child) {
if ((int)$child->parent_id == (int)$category_id) {
foreach ($child->CategoryDescriptions as $d) {
$childs .= '<option>'.$this->myspace().$parentName.' --> '.$name1.' --> '.$name2.' --> '.$name3.' --> '.$name4.' --> ';
$childs .= $d->name.$this->getChildn5($child->id, $parentName, $name1,$name2,$name3,$d->name);
$childs .= '</option>';
}
}
}
return $childs;
}
private function myspace (){
return ' ';
}
}
Call this is class and method in View
<?PHP
$helper = new Helper();
$helper->setData($cat);
$helper->GetCats('col-lg-9','cats');
?>
Result:

Multilevel Hierarchical select option using php

I want to generate a multilevel hierarchical select option that is indented right as we move from parent to child. I tried using recursion in PHP(CI) for this but can't generate what I needed.
This is the function I tried to generate the select option.
<?php
$category_list = $this->helper_model->get_category();
/* $category list contains
[{"id":"1","name":"Information Technology","parent_id":"0"},
{"id":"2","name":"Programming","parent_id":"1"},
{"id":"3","name":"Civil","parent_id":"5"},
{"id":"4","name":"Networking","parent_id":"1"},
{"id":"5","name":"Engineering","parent_id":"0"},
{"id":"6","name":"Electrical","parent_id":"5"},
{"id":"11","name":"Hardware","parent_id":"1"},
{"id":"12","name":"Car Driver","parent_id":"13"},
{"id":"13","name":"Driver","parent_id":"0"},
{"id":"14","name":"java","parent_id":"2"},
{"id":"15","name":"javascript","parent_id":"2"}]
*/
$select_option = $this->multilevel_select($category_list);
echo '<select name = "subCategory">
<option>Select Category</option>' . $select_option;
function multilevel_select($array,$parent_id = 0,$parents = array()) {
static $i=0;
if($parent_id==0)
{
foreach ($array as $element) {
if (($element['parent_id'] != 0) && !in_array($element['parent_id'],$parents)) {
$parents[] = $element['parent_id'];
}
}
}
$menu_html = '';
foreach($array as $element){
if($element['parent_id']==$parent_id){
$menu_html .= '<option>';
for($j=0; $j<$i; $j++) {
$menu_html .= '—';
}
$menu_html .= $element['name'].'</option>';
if(in_array($element['id'], $parents)){
$i++;
$menu_html .= $this->multilevel_select($array, $element['id'], $parents);
}
}
}
$i=0;
return $menu_html;
}
?>
Can anyone help me get through this?

html as php variable not rendered properly

Having the following method
public function printDropdownTree($tree, $r = 0, $p = null) {
foreach ($tree as $i => $t) {
$dash = ($t['parent'] == 0) ? '' : str_repeat('-', $r) . ' ';
printf("\t<option value='%d'>%s%s</option>\n", $t['id'], $dash, $t['name']);
if ($t['parent'] == $p) {
// reset $r
$r = 0;
}
if (isset($t['_children'])) {
$this->printDropdownTree($t['_children'], ++$r, $t['parent']);
}
}
}
which prints out nested select options and which works fine. But I would like to return the result as variable and I was trying to achieve this like
public function printDropdownTree($tree, $r = 0, $p = null) {
$html = "";
foreach ($tree as $i => $t) {
$dash = ($t['parent'] == 0) ? '' : str_repeat('-', $r) . ' ';
$html .= '<option value="'.$t['id'].'">'.$dash.''.$t['name'].'</option>';
if ($t['parent'] == $p) {
// reset $r
$r = 0;
}
if (isset($t['_children'])) {
$this->printDropdownTree($t['_children'], ++$r, $t['parent']);
}
}
return $html;
}
but the $dash won't get rendered
The simple solution: You have to fetch the result of the recursive calls of the function!
public function printDropdownTree($tree, $r = 0, $p = null) {
$html = "";
foreach ($tree as $i => $t) {
$dash = ($t['parent'] == 0) ? '' : str_repeat('-', $r) . ' ';
$html .= '<option value="'.$t['id'].'">'.$dash.''.$t['name'].'</option>';
if ($t['parent'] == $p) {
// reset $r
$r = 0;
}
if (isset($t['_children'])) {
$html .= $this->printDropdownTree($t['_children'], ++$r, $t['parent']);
}
}
return $html;
}

How do I sort an associative array and split into two div's based on a value?

I like to sort an associative array into two div's based on a value.
Here's what I have now:
function showDivs($array) {
/*
* sort en group by
*/
$luxury = false;
$no_luxury = false;
$return = '';
while (list($key, $value) = each($array)) {
if ($value["MinimumRate"] < 500) {
if ($no_luxury === false) {
$return .= '<div id="no_luxury" >';
}
$return .= $value['Description'] . " : " . $value["MinimumRate"] . "<br />";
if ($no_luxury === false) {
$return .='</div>';
$no_luxury = true;
}
}
if ($value["MinimumRate"] > 500) {
if ($luxury === false) {
$return .='<div id="luxury" >';
}
$return .= $value['Description'] . " : " . $value["MinimumRate"] . "<br />";
if ($luxury === false) {
$return .='</div>';
$luxury = true;
}
}
}
return $return;
}
My code doesn't work correctly.
The div is being created and closed on the first item only. I think you meant to open it on start and close it in the end. Try this:
function showDivs($array) {
/*
* sort en group by
*/
$luxury = array();
$not_luxury = array();
foreach ($array as $value) {
if ($value["MinimumRate"] > 500) {
$luxury[] = $value;
} else {
$not_luxury[] = $value;
}
}
$return = '<div id="no_luxury" >';
foreach ($luxury as $value) {
$return .= $value['Description'] . " : " . $value["MinimumRate"] . "<br />";
}
$return .= '</div>';
$return .= '<div id="luxury" >';
foreach ($luxury as $value) {
$return .= $value['Description'] . " : " . $value["MinimumRate"] . "<br />";
}
$return .= '</div>';
return $return;
}
If the problem is when MinimumRate = 500, you whould do:
if ($value["MinimumRate"] <= 500) // this is your first 'if' in your code
or
if ($value["MinimumRate"] >= 500) // this is the second 'if' in your code

Categories