Recursion Fail..

xlebabarov

Registered
Здравейте, боря се с проблема за рекрусията:

[sql]-- phpMyAdmin SQL Dump
-- version 4.8.2
-- https://www.phpmyadmin.net/
--
-- Host: 127.0.0.1
-- Generation Time: Sep 06, 2018 at 09:20 PM
-- Server version: 10.1.34-MariaDB
-- PHP Version: 7.2.7

SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET AUTOCOMMIT = 0;
START TRANSACTION;
SET time_zone = "+00:00";


/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES cp1251 */;

--
-- Database: `blank_website`
--

-- --------------------------------------------------------

--
-- Table structure for table `user_product_categories`
--

CREATE TABLE `user_product_categories` (
`id` int(11) NOT NULL,
`name` varchar(225) COLLATE cp1251_bulgarian_ci NOT NULL,
`main` int(11) NOT NULL,
`level` int(11) NOT NULL,
`orders` int(11) NOT NULL,
`user_added` int(11) NOT NULL,
`user_edited` int(11) NOT NULL,
`time_added` int(11) NOT NULL,
`time_edited` int(11) NOT NULL,
`user_ip` varchar(225) COLLATE cp1251_bulgarian_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=cp1251 COLLATE=cp1251_bulgarian_ci;

--
-- Dumping data for table `user_product_categories`
--

INSERT INTO `user_product_categories` (`id`, `name`, `main`, `level`, `orders`, `user_added`, `user_edited`, `time_added`, `time_edited`, `user_ip`) VALUES
(1, 'Electronics', 0, 0, 1, 1, 0, 1533326058, 0, '1'),
(2, 'Computers & Tablets', 1, 1, 1, 1, 0, 1533326058, 0, '1'),
(3, 'Cameras & Photos', 1, 1, 2, 1, 0, 1533326058, 0, '1'),
(4, 'TV Audio & Surveillance', 1, 1, 3, 1, 0, 1533326058, 0, '1'),
(5, 'Video Games & Consoles', 1, 1, 4, 1, 0, 1533326058, 0, '1'),
(6, 'Cell phones & Accessories', 1, 1, 5, 1, 0, 1533326058, 0, '1'),
(7, 'Fashion', 0, 0, 2, 1, 0, 1533326058, 0, '1'),
(8, 'Home & Garden', 0, 0, 3, 1, 0, 1533326058, 0, '1'),
(9, 'Shop Cellphones & Accessories', 6, 2, 1, 1, 0, 1533326058, 0, '1'),
(10, 'Cellphones & Smartphones', 6, 2, 2, 1, 0, 1533326058, 0, '1');

-- --------------------------------------------------------

--
-- Table structure for table `user_product_categories_lang`
--

CREATE TABLE `user_product_categories_lang` (
`id` int(11) NOT NULL,
`cat_id` int(11) NOT NULL,
`lang_id` int(11) NOT NULL,
`name` varchar(225) COLLATE cp1251_bulgarian_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=cp1251 COLLATE=cp1251_bulgarian_ci;

--
-- Dumping data for table `user_product_categories_lang`
--

INSERT INTO `user_product_categories_lang` (`id`, `cat_id`, `lang_id`, `name`) VALUES
(1, 1, 1, 'Електроника'),
(2, 1, 2, 'Electronics'),
(3, 2, 2, 'Computers & Tablets'),
(4, 3, 2, 'Cameras & Photos'),
(5, 4, 2, 'TV Audio & Surveillance'),
(6, 5, 2, 'Video Games & Consoles'),
(7, 6, 2, 'Cell phones & Accessories'),
(8, 2, 1, 'Компютри и таблети'),
(9, 3, 1, 'Камери и снимки'),
(10, 4, 1, 'ТВ Аудио и Охранителна техника'),
(11, 5, 1, 'Видео игри и конзоли'),
(12, 6, 1, 'Мобилни телефони & Аксесоари'),
(13, 7, 2, 'Fashion'),
(14, 8, 2, 'Home & Garden'),
(15, 7, 1, 'Мода'),
(16, 8, 1, 'Дом & Градина'),
(17, 9, 2, 'Shop Cellphones & Accessories'),
(18, 10, 2, 'Cellphones & Smartphones'),
(19, 9, 1, 'Клетъчни телефони & Аксесоари'),
(20, 10, 1, 'Клетъчни телефони & Смартфони');

--
-- Indexes for dumped tables
--

--
-- Indexes for table `user_product_categories`
--
ALTER TABLE `user_product_categories`
ADD PRIMARY KEY (`id`);

--
-- Indexes for table `user_product_categories_lang`
--
ALTER TABLE `user_product_categories_lang`
ADD PRIMARY KEY (`id`);

--
-- AUTO_INCREMENT for dumped tables
--

--
-- AUTO_INCREMENT for table `user_product_categories`
--
ALTER TABLE `user_product_categories`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=11;

--
-- AUTO_INCREMENT for table `user_product_categories_lang`
--
ALTER TABLE `user_product_categories_lang`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=21;
COMMIT;

/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;[/sql]

PHP:
$url = 'http://localhost/starniko/';
$homec = '\\';
$home = 'E:\xampp\htdocs\starniko'.$homec;

$c = array(0 => $url,
1 => $homec,
2 => $home);

// Create connection
$conn = mysqli_connect($servername, $username, $password, $dbname);
// Check connection
if (!$conn) {
    die("Connection failed: " . mysqli_connect_error());
}
} 
mysqli_query($conn, "SET CHARACTER SET utf8");

А в случая Glang e това:

PHP:
<?php
$glang = array(
//'' => '',
'does_not_match_mysql_add' => 'Посочените стойности не съвпадат. Моля, уравновесете.',
'mysql_add_table_not_null' => 'Посочените стойности в таблицата за добавяне не могат да са празни. Моля, изберете стойност.',
'mysql_add_value_not_array' => 'Стойностите, value0 or value1 не са масив. Моля, предоставете масив.',
'mysql_select_table_not_null' => 'Посочените стойности в таблицата за селектиране не могат да са празни. Моля, изберете стойност.',
'mysql_select_what_not_null' => 'Стойността какво не може да е нула. Моля, изберете стойности.',
'mysql_select_is_not_array_where' => 'Стойността where не е масив. Моля, изберете масив.',
'mysql_select_is_not_array_where0' => 'Стойността where0 не е масив. Моля, изберете масив.',
'mysql_select_is_not_array_where1' => 'Стойността where1 не е масив. Моля, изберете масив.',
'mysql_select_is_not_the_same_where' => 'Стойността where0 и where1 не са равни. Моля, уравновесете.',
'mysql_update_table_not_null' => 'Таблицата в стойности за ъпдейт не може да бъде празна. Моля, изберете стойност.',
'mysql_update_update_not_null' => 'Ъпдейта в стойности за ъпдейт не може да бъде празен. Моля, изберете стойност.',
'mysql_update_update_not_array'> 'Ъпдейта в стойности за ъпдейт не може да не бъде масив. Моля, изберете стойност.',
'mysql_update_update_not_equal' => 'Ъпдейта или където в стойности за ъпдейт не може да бъдат празни или неравни. Моля, изберете стойност.',
'mysql_update_where_not_array' => 'Където в стойности за ъпдейт не може да не бъдат масив. Моля, изберете стойност.',
'Close_menu' => 'Затвори менюта',
'log_out' => 'Изход',
'' => '',
'' => '',// BB Code
'quoted' => 'Цитат',
'said' => 'каза',
'Image' => 'Изображение',
//Profile
//'' => '',
'Username' => 'Потребителско име',
'Password' => 'Парола',
'Email' => 'E-mail',
'Level' => 'Ниво',
'Country' => 'Държава',
'Countries' => 'Държави',
'Language' => 'Език',
'Credits' => 'Кредити',
'Gender' => 'Пол',
//Products
'Name' => 'Име',
'Store_id' => 'Име на магазин',
'Cat_id' => 'Категория',
'User_ip' => 'IP на потребител',
'Description' => 'Описание',
'Images' => 'Изображения',
'' => '',
'Time_added' => 'Добавено на',
//Register
'Check' => 'Провери',
'Change' => 'Промени',
'username_free' => 'Потребителското име е свободно.',
'username_not_free' => 'Потребителското име е заето.',
'select_an_option' => 'Моля изберете',
'Register' => 'Регистрация',
'email_not_free' => 'E-mail-ът вече се използва',
'email_free' => 'E-mail-ът е свободен',
'Lang' => 'Език',
'Address' => 'Адрес',
'Mobile_phone' => 'Мобилен телефон (код/телефон)',
'could_not_be_empty' => ' не може да бъде празен.',
'username_cannot_contain_extra_characters' => 'Потребителското име не може да съдържа допълнителни знаци. Може да съдържа само букви от аА до zZ и _.',
'not_valid' => ' е невалидно.',
'username_not_less' => 'Потребителското име трябва да бъде между 4 и 12 символа',
'password_not_less' => 'Паролата трябва да бъде между 4 и 12 символа',
'country_not_less' => 'Държавата трябва да е под или 10 символа',
'gender_not_less' => 'Полът трябва да е под или 10 символа',
'language_not_less' => 'Езикът трябва да е под или 10 символа',
'address_not_less' => 'Адресът трябва да е под или 10 символа',
'phone_code_not_less' => 'Телефонен код трябва да е под или 10 символа',
'phone_num_not_less' => 'Телефонен номер трябва да е под или 20 символа',
'registration_success' => 'Регистрацията успешна!',
// Add Product
'Product_name' => 'Име на продукта',
'Pictures' => 'Снимки',
'Categorie' => 'Категория',
'Send' => 'Изпрати',
'Submit' => 'Изпращане',

'' => ''
);
?>

Просто за изпълненнието на файла за да ме разберете давам и функцията си mysql_select която е добро мое изобретение, служещо ми вярно като идеята на функцията е да избере от

  • table - Името на селектираната таблица
    where - WHERE заявката на таблицата array('id') = array(1) под кода $where = array(array(), array())
    order - Реда на селектирането да речем array('id')=array('ASC') под кода $order = array(array(), array())

PHP:
function mysql_select($table, $what = array('*'), $where = array(array(), array()), $order = array(array(), array())){
	global $conn;
	global $glang;
	
	
	$sql = 'SELECT ';
	if(!$table){
		die($glang['mysql_select_table_not_null']);
	}
	switch(count($what)){
		case 0:
		die($glang['mysql_select_what_not_null']);
		break;
		case 1:
		if($what[0]=='*'){
		$sql.= '*';
		}else{
		$sql.= '`'.$what[0].'`';			}
		break;
	}
	if((count($what)>=2)&&(count($what)!=1)){
		for($i=0;$i<=count($what)-1;$i++){
			$sql.='`'.$what[$i].'`';
			if($i!=count($what)-1){
			$sql.=', ';
			}else{
			$sql.=' ';	
			}
		}
		
	}
	
	$sql.= 'FROM `'.$table.'` ';
	
	if(!is_array($order)){die('Order must be array. Please, select value.');}
	if(!is_array($order[0])){die('Order0 must be array. Please, select value.');}
	if(!is_array($order[1])){die('Order1 must be array. Please, select value.');}
	if(count($order[0])!=count($order[1])){die('Order count must be equal. Please, select value.');}
	
	if((count($where[0])==0)&&(count($where[1])==0)){	
	if(count($order[0])>=1){
			$sql .= 'ORDER BY ';
			for($i=0;$i<=count($order[0])-1;$i++){
				$sql.='`'.$order[0][$i].'` '.$order[1][$i];
				if($i!=count($order[0])-1){
					$sql.=', ';
				}
			}
		}
	
	
	$result = mysqli_query($conn, $sql);
	$rezult = array();
	if (mysqli_num_rows($result) > 0) {
		// output data of each row
		while($row = mysqli_fetch_assoc($result)) {
			array_push($rezult, $row);
		}
		return $rezult;
	} else {
		return false;
	}
	
	}else{
		
		if(!is_array($where)){ die($glang['mysql_select_is_not_array_where']);}
		if(!is_array($where[0])){ die($glang['mysql_select_is_not_array_where0']);}
		if(!is_array($where[1])){ die($glang['mysql_select_is_not_array_where1']);}
		if(count($where[0])!=count($where[1])){ die($glang['mysql_select_is_not_the_same_where']);}
		$sql.='WHERE ';
	for($i=0;$i<=count($where[0])-1;$i++){
		if($i!=count($where[0])-1){
			$sql.= '`'.$where[0][$i].'` = \''.$where[1][$i].'\' AND ';
		}else{
			$sql.= '`'.$where[0][$i].'` = \''.$where[1][$i].'\'';

		}
	}
		if(count($order[0])>=1){
			$sql .= 'ORDER BY ';
			for($i=0;$i<=count($order[0])-1;$i++){
				$sql.='`'.$order[0][$i].'` '.$order[1][$i];
				if($i!=count($order[0])-1){
					$sql.=', ';
				}
			}
		}

	$result = mysqli_query($conn, $sql);
	$rezult = array();
	if (mysqli_num_rows($result) > 0) {
		// output data of each row
		while($row = mysqli_fetch_assoc($result)) {
			array_push($rezult, $row);
		}
		return $rezult;
	} else {
		return false;
	}

	}
	
	
	
}

Рекрусията съм я включил ей тук но за съжаление скрипта не се изпълнява:

PHP:
function has_children($cat, $id){
	if(!$cat){die('Please, select cat.');}
	if(!$id){die('Please, select id.');}
	if(!is_numeric($id)){die('Please, select numeric values.');}


	for($i=0;$i<=count($cat)-1;$i++){
		foreach($cat[$i] as $key => $val){
			if($key=='main'){
				if($val==$id){return true;}
			}
		}
	}
}

function make_menu_rows($array = array(), $level = 0){
	$rez = mysql_select('user_product_categories', array('id', 'name', 'main', 'level', 'orders'), array(array('level'), array($level)), array(array('orders'), array('ASC')));
	$rez1 = mysql_select('user_product_categories', array('*'));
	$array1 = array();
	
	foreach($rez as $var){
		$array_key = array_pop(array_keys($array));
		if(isset($array_key)){$array_var = $array_key+1;}else{$array_var = 0;}
		$array[$array_var] = array('Main' => $var);
		
		
		if(has_children($rez1, $var['id'])){
		$rez2 = mysql_select('user_product_categories', array('id', 'name', 'main', 'level', 'orders'), array(array('main'), array($var['id'])), array(array('orders'), array('ASC')));
		foreach($rez2 as $var1){
			if(has_children($rez1, $var1['id'])){
				array_push($array[$array_var], array('Sub' => $var1));
				make_menu_rows($array, $var1['level']);
			}else{
				array_push($array[$array_var], array('Sub' => $var1));
			}
		}
		}else{
		}
	}
	return $array;
}


$make = make_menu_rows();
print_r($make);

резултатът е:
Код:
Array
(
    [0] => Array
        (
            [Main] => Array
                (
                    [id] => 1
                    [name] => Electronics
                    [main] => 0
                    [level] => 0
                    [orders] => 1
                )

            [0] => Array
                (
                    [Sub] => Array
                        (
                            [id] => 2
                            [name] => Computers & Tablets
                            [main] => 1
                            [level] => 1
                            [orders] => 1
                        )

                )

            [1] => Array
                (
                    [Sub] => Array
                        (
                            [id] => 3
                            [name] => Cameras & Photos
                            [main] => 1
                            [level] => 1
                            [orders] => 2
                        )

                )

            [2] => Array
                (
                    [Sub] => Array
                        (
                            [id] => 4
                            [name] => TV Audio & Surveillance
                            [main] => 1
                            [level] => 1
                            [orders] => 3
                        )

                )

            [3] => Array
                (
                    [Sub] => Array
                        (
                            [id] => 5
                            [name] => Video Games & Consoles
                            [main] => 1
                            [level] => 1
                            [orders] => 4
                        )

                )

            [4] => Array
                (
                    [Sub] => Array
                        (
                            [id] => 6
                            [name] => Cell phones & Accessories
                            [main] => 1
                            [level] => 1
                            [orders] => 5
                        )

                )

        )

    [1] => Array
        (
            [Main] => Array
                (
                    [id] => 7
                    [name] => Fashion
                    [main] => 0
                    [level] => 0
                    [orders] => 2
                )

        )

    [2] => Array
        (
            [Main] => Array
                (
                    [id] => 8
                    [name] => Home & Garden
                    [main] => 0
                    [level] => 0
                    [orders] => 3
                )

        )

)

Като тук
Код:
            [4] => Array 
                ( 
                    [Sub] => Array 
                        ( 
                            [id] => 6 
                            [name] => Cell phones & Accessories 
                            [main] => 1 
                            [level] => 1 
                            [orders] => 5 
                        ) 

                )
Би трябвало да се включи рекрусията понеже в таблицата Cell Phones & Accessories е с main 1 и включени 2 подменюта които не излизат ID 9 и 10

Shop Cellphones & Accessories
и
Cellphones & Smartphones
с level 2 и main 6

Ако схващате идеята моля помогнете :?:
 
Ако използваш MySQL 8 можеш да си направиш рекурсията в заявката:
https://www.db-fiddle.com/f/se4UTULGTUbVT6Lmwy33x5/1
 
raiden каза:
Ако използваш MySQL 8 можеш да си направиш рекурсията в заявката:
https://www.db-fiddle.com/f/se4UTULGTUbVT6Lmwy33x5/1

За съжаление не ползвам 8 а някъкви идеи защо не работи кода?
 
Функцията ти вика сама себе си, но това извикване не променя нищо в резултата. Трябва да имаш нещо от рода на
Код:
$array = make_menu_rows($array, $var1['level']);
или директно да правиш
Код:
return make_menu_rows($array, $var1['level']);
за да работиш при всяко следващо извикване с резултата от предишното. Иначе функцията не е рекурсивна. Предвид че имаш нивото на всяка категория в йерархията, рекурсията не е наложителна и можеш да минеш с нещо такова:
PHP:
<?php
$array = [
0 => ['id' => 1, 'name' => 'Electronics2', 'main' => 0, 'level' => 0],
1 => ['id' => 2, 'name' => 'Electronics1', 'main' => 0, 'level' => 0],
2 => ['id' => 3, 'name' => 'Electronics11', 'main' => 2, 'level' => 1],
3 => ['id' => 4, 'name' => 'Electronics12', 'main' => 3, 'level' => 2]
];

function nestSubs($array) {
    $result = array_reduce(
        $array,
        function ($result, $i) {
            $result[$i['level']][$i['id']] = $i;
            return $result;
        },
        []
    );
    $maxLevel = max(array_keys($result));
    for ($i = $maxLevel; $i > 0; $i--) {
        foreach($result[$i] as $sub) {
            $result[$i - 1][$sub['main']]['subs'][$sub['id']] = $sub;
        }
        unset($result[$i]);
    }

    return $result[0];
}

print_r(nestSubs($array));
 

Горе