dynamic accordion with bootstrap - php

I'm having a hard time getting this dynamic accordion to work properly.
I'm fetching accordion title from MySQL database and trying to create a dynamic accordion based on number of rows in my database.
As of right now, I'm only able to create single tab with first title in my database.
<?php
foreach ($variable as $key);
?>
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#collapseOne" style="margin-right:50%;" > <img src="image.jpeg" class="event-icon"> <?php echo $key['title']?>;</a>
</h4>
</div>
<div id="collapseOne" class="panel-collapse collapse">
<div class="panel-body">
<p>Event content
</p>
</div>
</div>
</div>
</div>
</div>
I'm trying to create the following html structure when the foreach loop runs.
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#collapseOne" style="margin-right:50%;" > <img src="image.jpeg" class="event-icon"> <?php echo $key['title']?>;</a>
</h4>
</div>
<div id="collapseOne" class="panel-collapse collapse">
<div class="panel-body">
<p>Event content
</p>
</div>
</div>
</div>
Any suggestion is highly appreciated.

You have to add at the end of your foreach loop, like this:
<?php endforeach; ?>
Also you have to change ; -> : in your foreach header:
foreach ($variable as $key);
to:
foreach ($variable as $key):
//^See here

Looks like you have a problem with the alternative syntax for foreach
foreach ($variable as $key);
should be
foreach ($variable as $key):
semicolon (;) should be a colon (:)
it also ends with a endforeach semicolon
endforeach;

Related

PHP loop depending on number of folders

I am working on a project which is a sort of FAQ made in HTML and PHP (based on Bootstrap).
Some people with limited knowledge in HTML/PHP will need to update it regularly so I decided to use the "include" feature in PHP to call some .txt files. Then, the people who will update it will just have to modify the simple .txt files, which doesn't require any coding knowledge.
The text files are stored in faq/main-category/sub-category/1/question.txt and the same with "answer.php" (both in the same folder).
The FAQ items are identified with numbers (which you can see on the screenshot below). These numbers refer to the directory ("1" in the .txt file path above) where the files are.
Screenshot of list of FAQ items
Now, here's the thing: I want to allow people who will modify it to add some new FAQ items easily. The idea is for them to only have to create a new folder (let's say "4") in the FTP server, and it would be automatically listed on the FAQ.
For this, I need that the plugin detects all items in the FTP server and list them all. I believe that is possible with a loop, however, I have no idea how...
Can anyone help with that? Any help will be greatly appreciated! :)
Here is the current code for the first FAQ item of the screenshot:
<div id="accordion" role="tablist">
<div class="card">
<div class="card-header d-flex w-100 justify-content-between" role="tab" id="headingOne">
<h5 class="mb-0">
<a data-toggle="collapse" href="#collapseOne" role="button" aria-expanded="true" aria-controls="collapseOne">
<?php include('../faqs/professionals/eligibility-conditions/1/question.txt'); ?>
</a>
</h5>
<small>1</small>
</div>
<div id="collapseOne" class="collapse" role="tabpanel" aria-labelledby="headingOne" data-parent="#accordion">
<div class="card-body">
<div><p><?php include('../faqs/professionals/eligibility-conditions/1/answer.txt'); ?></p></div>
</div>
</div>
</div>
You will see both "include" codes that call the .txt files for the question and for the answer.
Here is a screenshot of the file path
<?php
foreach (glob("../faqs/professionals/eligibility-conditions/*",GLOB_ONLYDIR) as $foldername) {
?>
<div id="accordion" role="tablist">
<div class="card">
<div class="card-header d-flex w-100 justify-content-between" role="tab" id="headingOne">
<h5 class="mb-0">
<a data-toggle="collapse" href="#collapseOne" role="button" aria-expanded="true" aria-controls="collapseOne">
<?php include($foldername.'/question.txt'); ?>
</a>
</h5>
<small>1</small>
</div>
<div id="collapseOne" class="collapse" role="tabpanel" aria-labelledby="headingOne" data-parent="#accordion">
<div class="card-body">
<div><p><?php include($foldername.'/answer.txt'); ?></p></div>
</div>
</div>
</div>
<?php
}
?>
I am not sure what is your application structure, maybe you are using MVC architecture but you can do it like below.
Create a PHP function which will return an array with questions and answers
<?php
function get_faqs(){
$folderpath = 'faqs/shared/'; //change as per your desired path
if(scandir($folderpath)){
$file_arr = scandir($folderpath);
foreach ($file_arr as $val){
if($val == '.' || $val == '..'){
continue;
} else if(scandir($folderpath.$val)){
$faq_arr = scandir($folderpath.$val);
foreach ($faq_arr as $file){
if($file == '.' || $file == '..'){
continue;
} else if($file == 'question.txt'){
$faq_final[$val]['question'] = file_get_contents($folderpath.$val.'/'.$file);
} else if($file == 'answer.txt'){
$faq_final[$val]['answer'] = file_get_contents($folderpath.$val.'/'.$file);
}
}
}
}
}
return $faq_final;
}
?>
Then iterate that array in your HTML as below
<?php
$faqs = get_faqs(); // you need to call this in controller if you have MVC application
?>
<div id="accordion" role="tablist">
<?php foreach ($faqs as $num => $data) { ?>
<div class="card">
<div class="card-header d-flex w-100 justify-content-between" role="tab" id="headingOne">
<h5 class="mb-0">
<a data-toggle="collapse" href="#collapseOne" role="button" aria-expanded="true" aria-controls="collapseOne">
<?php echo $data['question']; ?>
</a>
</h5>
<small><?php echo $num; ?></small>
</div>
<div id="collapseOne" class="collapse" role="tabpanel" aria-labelledby="headingOne" data-parent="#accordion">
<div class="card-body">
<div><p><?php echo $data['answer']; ?></p></div>
</div>
</div>
</div>
<?php } ?>
</div>

bootstrap 4 grid mixed up when using margin

I am generating html code using php. I have some information stored in an array called $persons and I'm trying to generate a bootstrap card for each $person:
<div class="container">
<div class="row">
<?php foreach ($persons as $person): ?>
<div class="card col-md-3 m-1">
<img class="card-img-top" src="<?=person['img_src']?>" alt="<?=$person['name']?>">
<div class="card-block">
<h4 class="card-title"><?=$person['name']?></h4>
<p class="card-text"><?=$person['info']?></p>
</div>
</div>
<?php endforeach; ?>
</div>
</div>
Everything works fine when I remove m-1 class, but as soon as I add m-1 class, margin causes the last div to go to next line. I think lack of space causes this problem. How can I fix this problem? How to have margin between divs without the last div going to the next line?
You should have a separate div for the card since it's display:flex. Also, just use my-1 for margin-top and margin-bottom so that x-axis space is not effected...
<div class="container">
<div class="row">
<?php foreach ($persons as $person): ?>
<div class="col-md-3 my-1">
<div class="card">
<img class="card-img-top" src="<?=person['img_src']?>" alt="<?=$person['name']?>">
<div class="card-block">
<h4 class="card-title"><?=$person['name']?></h4>
<p class="card-text"><?=$person['info']?></p>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
</div>
https://www.codeply.com/go/78AmkbWrLi
The easiest solution would be to just put another div inside the col, which applies the margin:
<div class="container">
<div class="row">
<?php foreach ($persons as $person): ?>
<div class="card col-md-3">
<div class="m-1"> <!-- NEW -->
<img class="card-img-top" src="<?=person['img_src']?>" alt="<?=$person['name']?>">
<div class="card-block">
<h4 class="card-title"><?=$person['name']?></h4>
<p class="card-text"><?=$person['info']?></p>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
</div>
Or if you don't want to add another div, just add the m-1 class to the card-block.

Loop on multiple values

I got a FAQ element in which I want to show questions and answers. I am using the joomla cms template to edit so I am fairly limited on how to add this.
My solution on how I wanted to do this:
In the textfield I add the string like this:
[question1? || Answer1]
[question2? || Answer2]
[question3? || Answer3]
Then I split the questions/answers on the brackets around them, and finally split those results on the two lines inbetween.
Then finally loop the results in this format:
<div id="accordion-1" role="tablist" aria-multiselectable="true">
<div class="panel panel-default panel-alt-two">
<div class="panel-heading active" role="tab" id="heading1">
<h5 class="panel-title"><a data-toggle="collapse" data-parent="#accordion-1" href="#collapse1" aria-expanded="true" class=""><span class="accordion-icon"><span class="stacked-icon"><i class="fa fa-rocket"></i></span></span>Question 1</a></h5>
</div>
<!-- LOOP FROM HERE -->
<div id="collapse1" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="heading1" style="height: auto;">
<div class="panel-body">Answer 1</div>
</div>
<div class="panel-heading" role="tab" id="heading2">
<h5 class="panel-title"><a class="collapsed" data-toggle="collapse" data-parent="#accordion-1" href="#collapse2" aria-expanded="false"><span class="accordion-icon"><span class="stacked-icon"><i class="fa fa-quote-left"></i></span></span>Question 2</a></h5>
</div>
<div id="collapse2" class="panel-collapse collapse" role="tabpanel" aria-labelledby="heading2" style="height: 0px;">
<div class="panel-body">Answer 2</div>
</div>
<div class="panel-heading" role="tab" id="heading3">
<h5 class="panel-title"><a class="collapsed" data-toggle="collapse" data-parent="#accordion-1" href="#collapse3" aria-expanded="false">Question 3<span class="accordion-icon"><span class="stacked-icon"><i class="fa fa-flag"></i></span></span></a></h5>
</div>
<div id="collapse3" class="panel-collapse collapse" role="tabpanel" aria-labelledby="heading3" style="height: 0px;">
<div class="panel-body">Answer 3</div>
</div>
<!-- -->
</div>
</div>
I split the parts like this:
// faq data
$faq = "SELECT * FROM `web_content` WHERE catid = 13 AND `alias` = '".$conn->real_escape_string($_GET['alias'])."' AND state = 1 ORDER BY ordering";
$faqcon = $conn->query($faq);
$faqcr = array();
while ($faqcr[] = $faqcon->fetch_array());
$faqtext = $faqcr[0]['introtext'];
preg_match_all("/\[([^\]]*)\]/", $faqtext, $faqarray);
How can I get the question and answer seperate and loop them for example like this:
<div class="panel-heading" role="tab" id="heading3">
<h5 class="panel-title"><a class="collapsed" data-toggle="collapse" data-parent="#accordion-1" href="#collapse3" aria-expanded="false">'.$question[0].'<span class="accordion-icon"><span class="stacked-icon"><i class="fa fa-flag"></i></span></span></a></h5>
</div>
<div id="collapse3" class="panel-collapse collapse" role="tabpanel" aria-labelledby="heading3" style="height: 0px;">
<div class="panel-body">'.$answer[0].'</div>
</div>
I know I have to add numbers to the accordion element but that is not an issue.

two PHP loops in one html div

I have below code for help contents,
<div class="tab-content">
<?php
foreach($helpCategoryArray as $category)
{
?>
<div id="tab_<?php echo $category["helpcategory_id"]?>" class="tab-pane active">
<div id="accordion1" class="panel-group">
<?php
foreach($topicsArray as $topic)
{
?>
<div class="panel panel-default" id="topic_<?php echo $topic["topic_id"]?>">
<div class="panel-heading">
<h4 class="panel-title">
<a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion1" href="#accordion1_1">
<?php echo $topic["topic_subject"]?>
</h4>
</div>
<div id="accordion1_1" class="panel-collapse collapse in">
<div class="panel-body" id="context" data-toggle="context" data-target="#context-menu">
<?php echo $topic["topic_content"]?>
</div>
</div>
</div>
<?php
}
?>
</div>
</div>
<?php
}
?>
</div>
What is my requirement is left side of page is tree of selection, when one item category is selected, related contents are loading on right side,
Now on above code have did that with id=tab_x, x will come from DB, so need loop for that, so that i can give reference to tab_x as href,
In tab div, i have help topics which are related to this items, so i need to loop all my topics here,
Problem is that my one help topic is also looping in first loop looping times,
So how to echo this help topic,
Thanks,
Finally it solved with adding If condition in first PHP loop,
if ($category["helpcategory_id"] == $topic["topic_category"])
{--code---}

Laravel and nested foreach of database query error

I am building a menu on laravel.
In blade layout i have:
#foreach ($menu1 as $menu1)
{{$menu1->nome}}
<div class="panel-group" id="accordion">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#collapseOne">
<span class="glyphicon glyphicon-chevron-down"></span>
</a>
</h4>
</div>
<div id="collapseOne" class="panel-collapse collapse in">
<div class="panel-body">
<ul class="list-unstyled">
#foreach ($menu2 as $menu2)
<li> {{$menu2->nome}} </li>
#endforeach
</ul>
</div>
</div>
</div>
#endforeach
in my controller i pass 2 query.
public function menu($lingua)
{
return View::make('index', ['menu1'=>DB::table('cat_nome')->join('lingua', 'cat_nome.id_lingua', '=', 'lingua.id') ->where('lingua.lingua','=',$lingua)->get(array('cat_nome.nome')),
'menu2' => DB::table('campo_nome')->join('lingua', 'campo_nome.id_lingua', '=', 'lingua.id') ->where('lingua.lingua','=',$lingua)->get(array('campo_nome.nome'))]
);
}
I tried to UNnest the foreach and everything works fine. When i try to nest the foreach i get
Trying to get property of non-object
#foreach ($menu2 as $menu2)
That line is most likely the culprit. You cannot use the same variable name twice in a foreach loop like that and expect good results. The second one is supposed to be what each entry in $menu2 will be scoped to during each iteration of the loop.
See the foreach documentation
Try changing the loop to look more like this:
#foreach ($menu2 as $innerMenu)
<li> {{$innerMenu->nome}} </li>
#endforeach
I would suggest doing the same thing for your outer menu as well.

Categories