Display loop data in sorted manner - php

I want to display <li> where, I am having issue with my loop, see my code below
<?php
for ($j=0;$j<$task_count;$j++)
{
$task_name = $task[$j]['summary'];
$summary_length = strlen('');
$task_id = $task[$j]['_id'];
$task_status = $task[$j]['status'];
$summary_count = strlen($task_name);
if ($task_name=='task') {
$final_task_summary = $task_id ;
}
elseif($summary_count <= 50)
{
$final_task_summary = $task_name;
}
else
{
$final_task_summary = mb_substr($task_name, 0, 50);
}
?>
Here, I want to display <li> </li> in order where first it shows <li> having status "open" then "resolved" and then "close" and only 20 <li> should take place.

If I understand correctly, you want to:
Print list items for the first 20 items.
Printing should be done ordered based on status.
If you're getting the data from a database, then it would be better to handle this in the query, If not, you can do as follows.
Change your loop to get only 20 items instead of task count
Declare three strings to hold li items for each status.
Within the loop, Check for the status and append the desired string with li items.
After the loop, print the three strings in the required order.
Let me know if anything needs clarification.
Thanks,

Related

Change order of elements in query results array

[edited] I need to display posts from database sorted in a kinda specific way.
There is a page which at set time interval query database via ajax to pull 180 latest post. Each post in db has column "source" which can be "instagram" or "twitter". Ajax returns 30 sets (or less) x 6 posts each (less if there is not enough posts). Than with help of js all sets are hidden and only one set (6 posts) is displayed at a time. After few seconds set is hidden and next one is shown. Think of it like a typical slideshow but with posts instead of images on infinite loop.
At the begining it wasn't important what kind of post were in sets. It could be all 6 posts from twitter or instagram or mixed. But as usual when project was scheduled to finish, I was asked to change the way sets are generated. Now client wants to have only 2 types of sets with posts in particular order (described below).
So my question is how change this (simplified example from my ajax file):
DB details for ref.: table POSTS: id / source / user / date etc.
$sql="SELECT * FROM posts ORDER BY id DESC LIMIT 180";
...
$stmt->setFetchMode(PDO::FETCH_OBJ);
$set=1;
while($row = $stmt->fetch()) {
if($set==1){
echo '<!--start set--><div class="set">';
}
if($row->source="twitter"){
echo '<div class="post twitter">';
echo '{all stuff related to this twitter post}';
echo '</div>';
} else if($row->source="instagram") {
echo '<div class="post instagram">';
echo '{all stuff related to this instagram post}';
echo '</div>';
}
if($set==6) {
echo '</div> <!--//END set-->';
$set=0;
}
}
$set++
}
into something what let me generate those 30 sets but with posts distributed among them using this pattern:
<!--First set should has post in order: --
<div class="set>
<div class="post twitter">{stuff}</div> {instagram post} {instagram post}
{instagram post}{instagram post}{twitter post}
</div> <!--//END set-->
<!--Second set order:-->
<div class="set">
{instagram} {instagram} {twitter}
{twitter} {instagram} {instagram}
</div>
etc.
Of course there is no guarantee that there would be enough post to create all 30 sets with those patterns so I need to create as many sets following those two patterns and leftovers put in sets as before simply in order they are pulled from db.
Thats all.
Thanks in advance for any suggestions / ready solutions ;) etc.
You could try something with a split between the two kind of posts using array_filter.
$posts = $stmt->fetchAll();
$twitterPosts = array_filter($posts, function($post){
return $post->source == "twitter";
});
$instagramPosts = array_filter($posts, function($post){
return $post->source == "instagram";
});
$set=1;
while(!empty($twitterPosts) && !empty($instagramPosts))
{
if($set%2 == 1)
{
$instagramPost1 = array_shift($instagramPosts);
$instagramPost2 = array_shift($instagramPosts);
$twitterPost1 = array_shift($twitterPosts);
}
else
{
$instagramPost1 = array_shift($instagramPosts);
$twitterPost1 = array_shift($twitterPosts);
$twitterPost2 = array_shift($twitterPosts);
}
/* display them */
if($set==6) {//your condition
echo '</div> <!--//END set-->';
$set=0;
}
$set++;
}
/* now one of them is empty, you can just display the other one */
if(!empty($twitterPosts))
/* Display all remaining twitter posts */
elseif(!empty($instagramPosts))
/* Display all remaining instagram posts */
Of course you should add validation that there is still something in the array between 2 array_shift.
I hope this helps !
EDIT : sorry I missed the condition for only 3 item per row, adding it now.

Accessing HTML unordered list elements in PHP

I'm trying to access unordered list elements in php so I can insert them in a database, I need to be able to access them via position but I'm not sure how to do this in PHP. I'm using jQuery so that the list is sortable on the client side.
In Javascript it would be accessed with
alert($("#sortable li:first").text() + ' is first ' + $("#sortable li:eq(1)").text() + ' is second ' + $("#sortable li:eq(11)").text() + ' is last');
The list I'm using is on http://jsfiddle.net/mMTtc/
I'm simply looking for help as for how to store those list items in a php variable i.e. lets say I wanted the 6th element based on how the user had ordered the list.
How would I do this?
Thanks
Using the following code you can send updates to the PHP backend as the user changes the order of elements in the front-end:
$("#sortable").on("sortupdate", function() {
var dataArr = [];
$("#sortable li").each(function(idx, elem) {
dataArr[idx] = $(elem).html();
});
var dataStr = '{"newOrder":' + JSON.stringify(dataArr) + '}';
$.ajax({
url: "<url_to_php_file>",
data: dataStr
});
// alert(dataStr);
});
Live example (frontend part): here
You'll have to replace <url_to_php_file> with the path to your PHP file that does the processing of the elements order (i.e. saving them in the DB). The file will be able to access the user-defined order in a normal PHP Array, using json_decode($_POST["newOrder"]), i.e.
...
$newOrder = json_decode($_POST["newOrder"]);
for ($i = 0; $i < count($newOrder); $i++) {
echo("The item labeled '" . $newOrder[$i] . "' is placed by the user at index " . $i . ".\n";
/* 1st item: index 0 */
/* 2st item: index 1 */
/* ... */
}
Example:
You present a sortable list to the user, containing items: item1, item2, item3 (in this order).
The user places item2 before item1, at which point an AJAX call is made passing to the server the array ["item2", "item1", "item3"] (note the order). The above snippet would echo:
The item labeled 'item2' is placed by the user at index 0.
The item labeled 'item1' is placed by the user at index 1.
The item labeled 'item3' is placed by the user at index 2.
(Of course, instead of echoing anything, you would update the value of an index-field in the DB for each item or do something useful.)
You can use DomDocument to parse your HTML. This can be done either via a string using loadHTML(), or loading an external HTML file using loadHTMLFile().
This example uses loadHTML():
<?php
$html = '<html>
<body>
<ul id="sortable">
<li class="ui-state-default">1</li>
<li class="ui-state-default">2</li>
<li class="ui-state-default">3</li>
<li class="ui-state-default">4</li>
<li class="ui-state-default">5</li>
<li class="ui-state-default">6</li>
<li class="ui-state-default">7</li>
<li class="ui-state-default">8</li>
<li class="ui-state-default">9</li>
<li class="ui-state-default">10</li>
<li class="ui-state-default">11</li>
<li class="ui-state-default">12</li>
</ul>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
</body>
</html>';
$dom = new DomDocument;
$dom->loadHTML($html);
$li = $dom->getElementsByTagName('li');
// Print first item value
echo $li->item(0)->nodeValue;
// Print third item value
echo $li->item(2)->nodeValue;
Here's what I'd do, and it's certainly not the cleanest way, but it should work.
This assumes you're working with your own pages, and not the scenario where you're getting the page html via http request to some external site (e.g. via CURL) and needing to parse it. DOMDocument serves just fine for the latter case. This solution is for the former, as I'm assuming that since you're working with javascript on the client-side of it, it's probably your own page (unless you're injecting that javascript into the page after it's loaded).
First of all, inside each list item, I'd include a server-side accessible input tag. It will serve to keep track of the position and value, and pass it to the server-side script on form submission.
<form method="POST">
<ul id="sortable">
<li class="ui-state-default">1
<input id="the_list_item_1" name="the_list_item[]" type="text" value="1_0" style="display: none;">
</li>
...
</ul>
</form>
The value is the item's actual value (the example had them ranged 1 - 12) and it's position separated by an underscore (value + "_" + position);
The list needs to be inside a form variable if you only need to submit the list to the server for processing when the user's done. However, if you intend to only use Ajax to get that data to the server, this solution isn't really necessary (as you'd simply just use jquery to get each position and value pair and send them directly in your ajax call).
You'll need to handle updating these input tags as the user drags items and changes the ordering of the list. See here if you need to know how to work with the sortable events. Perhaps, on update, for each list item call this function with the new position:
function update_pos(value,pos)
{
$("#the_list_item_"+value).val(value+"_"+pos);
}
So on form submit, we're now on the PHP side.
$list_items = $_POST["the_list_item"]; // This is basically an array of all the list_items, thanks to naming all the list items with "the_list_item[]", note the empty subscript (square braces).
$ordered_list_items = array(); // Let's push them into an associative array.
foreach($list_items as $li)
{
$li_split = explode("_",$li);
if(count($li_split) <= 0)
continue; // maybe you'd want to handle this situation differently, it really shouldn't happen at all though. Here, I'm just ignoring nonsensical values.
$item_id = $li_split[0];
$pos = $li_split[1];
$ordered_list_items[$item_id] = $pos;
}
// Then later you can shoot through this list and do whatever with them.
foreach($ordered_list_items as $item_id => $pos)
{
// postgres perhaps. Insert if not already there, update regardless.
pg_query("insert into the_list_item (item_id,position) select '$item_id','$pos' where '$item_id' not in (select item_id from the_list_item where '$item_id' = item_id limit 1));
pg_query("update the_list_item set position = '$pos' where item_id = '$item_id'");
}
Of course, all that said, depending on your needs you may need to be reloading this data onto the page. So looping through your db results (perhaps, for that user), you'd output each list_item into place.
$list_items = pg_fetch_all(pg_query($sql)); // $sql needs to be the query to get the results. Probably should order by position ascending.
$lic = count($list_items);
?>
<html> and stuff
<form method="POST">
<ul id="sortable">
<?php
for($i = 0; $i < $lic; $i++)
{
$li = $list_items[$i];
echo "<li class=\"ui-state-default\">".$li["item_id"]."<input id=\"the_list_item_".$li["item_id"]."\" name=\"the_list_item[]\" type=\"text\" value=\"".$li["item_id"]."_".$li["position"]."\" style=\"display: none;\"></li>";
}
?>
</ul>
</form>

Only add item as needed in PHP array

I have bits of code I want to throw in to my site, and provisioned a space right after <body> using 'flairs' (divs) that sit outside the design. Here's the code:
//Add Flair Containers as needed
if($flairs>0){
echo "<!--Flair Graphics (if needed)-->\n";
while($fQty = --$flairs+1){ //-- subracts 1, +1 accounts for 1 being 0
$flair = array($flair1, $flair2, $flair3);
foreach($flair as $flairCode){
echo "<div id=\"flair-".$fQty++."\">".$flairCode."</div>\n";
};
};
};
It prints correctly, where content = $flair1, $flair2, and so on.
<div id="flair-1">Content1</div>
<div id="flair-2">Content2</div>
<div id="flair-3">Content3</div>
But if $flair2/$flair3 is empty, it still prints a div. How can I fix this?
Within your foreach loop you can check if the value is empty and continue (i.e. skip) to the next value if it is.
Like so:
if($flairs>0){
echo "<!--Flair Graphics (if needed)-->\n";
while($fQty = --$flairs+1){ //-- subracts 1, +1 accounts for 1 being 0
$flair = array($flair1, $flair2, $flair3);
foreach($flair as $flairCode){
if (empty($flairCode)) continue;
echo "<div id=\"flair-".$fQty++."\">".$flairCode."</div>\n";
};
};
};
I suspect that you could simply prepend if($flairCode) to your echo statement. That would make your inner loop:
foreach($flair as $flairCode){
if($flairCode) echo "<div id=\"flair-".$fQty++."\">".$flairCode."</div>\n";
};
Some points to note:
Since the $flair array will always be the same, construct it outside of the loop (this will let you evaluate the condition only once too.
Using $fQty++ is not enough to guarantee unique ID's, especially since every time it hits the while the value is reset. I suggest $fQty should not be part of the while condition and simply stay as an independent tally.
Stop using double-quotes. They're slow.

Not understanding how to add cart into PHP

I am stuck on this code. I am making a web page and on the side there is a place for a cart. And with the you should be able to click on an item and add it to cart. Well I am having trouble getting it to add it to cart. Can someone help me understand what I should be doing. I have been working on it for a few days and no matter what I am doing nothing is working. If i get the code to show you have 0 in your cart it wont add anything if i try to put it in the cart.
<h1>Cart Contents?</h1>
<div class="p2">
<?php
// Get all the categories and
// link them to category.php.
// Define and execute the query:
$q = 'SELECT category_id, category FROM categories ORDER BY category';
$r = mysqli_query($dbc, $q);
// Fetch the results:
while (list($fcid, $fcat) = mysqli_fetch_array($r, MYSQLI_NUM)) {
// Print as a list item.
echo "<li>$fcat</li>\n";
if($_SERVER['PHP_SELF']!="CART FILE"){
echo "<h1>Cart Contents</h1>";
echo "<div class=\"p2\">";
$itemCount=X;
foreach($_SESSION['cart'] as X=>X){
for($i=0;$i<count(X);$i++){
$itemCount+=X;
}
}
echo "You have ".$itemCount." total items in your cart.";
echo "</div>\n";
} // End of while loop.
?>
<h1>Specials?</h1>
<div class="p2">
<p>Maybe place specials or new items or related items here.</p>
</div>
</div>
<div class="content">
Ok here is a link to what the cart should do if you look over to the side it should do what that one is doing.
http://www.programmerskit.com/advPHP/ch5/
Shouldn't
$itemCount=X;
foreach($_SESSION['cart'] as X=>X){
for($i=0;$i<count(X);$i++){
$itemCount+=X;
}
}
just be:
$itemCount = count($_SESSION['cart']);
I can't otherwise figure out what that code is supposed to be doing.
Also, that code that outputs the cart appears to be in a while loop outputting each item category, so you will be displaying the cart multiple times, which I can only assume is not desired functionality.
Also, another poster made a point about the invalid use of X as a constant, which is also a good point.
You've got a bare X used all over the place. While saying
$somevar = X;
would be legitimate if you'd already done define('X', 'somevalue') previously, this next one
foreach($_SESSION['cart'] as X=>X){
is completely invalid. You cannot assign new values to a defined constant, let alone try to assign TWO different values at the same time
foreach($_SESSION['cart'] as $key => $value)
is how that particular bit of code should be.

Friends List Pagination

I have got a feature on my website called 'View friends' that displays a hidden div containing a users friends. The only problem so far is I would like it so that it would show 7 members on each row for 3 rows so a total of 21 members on each page. I know I will have to round up NumOfMembers/21 giving me the pages needed. I just need some advice in how I should set up the pagination from when thee SQL query gets the total amount of friends. Any ideas?
The SQL-query should use the limit and offset parameters for pagination, depending on the page n you are on, like this:
SELECT .... LIMIT 21 OFFSET n*21
When handling the results, simply use the modulo operator for determining the lines and rows your current result has to be put in:
// where $i is the result number
$row = $i % 7;
$line = $i % 3;
You have 2 options:
First you can load everything from the php in one query and put all users in an array(content), and just display in pages!
content = [];
max = 21;
function handlePaginationClick(page, pagination_container) {
$('#MyContentArea').empty();
for(var i=0;i<max;i++) {
if(null!=content[(page*max)+i]) $('#MyContentArea').append(content[(page*max)+i]);
}
return false;
}
$("#News-Pagination").pagination(content.length, {
items_per_page:max,
callback:handlePaginationClick
});
you can use Jquery Pagination: https://github.com/gbirke/jquery_pagination#readme
for that.
Another approach is still using jquery pagination, but not load everything at once! then you must have same ajax call in the method 'handlePaginationClick' to pull all page information.

Categories