How to write this statement using PHP & CodeIgniter - php

I'm trying to figure out how to write a statement in my first CI app (and only second PHP app ever) and I'm stuck.
I have a junction table that holds book_id and user_id from their respective tables. I want to find out who has read a book and echo that back out, but I need the formatting to make sense. Here is the query:
$readQuery = $this->db->get_where('books_users', array('book_id' => $isbn));
And here's my logic for one person
// Get my user info
$user = $this->ion_auth->get_user();
// Tell me who has read it.
$this->db->select('user_id');
$readQuery = $this->db->get_where('books_users', array('book_id' => $isbn));
// If only one person has read it
if ($readQuery->num_rows() == 1) {
$readResult = $readQuery->row();
// And if that person was me...
if ($readResult->user_id == $user->id) {
$message = 'You have read this.';
// If it was someone else...
} else {
$reader = $this->ion_auth->get_user($readResult->user_id);
$message = "$reader->first_name $reader->last_name has read this";
}
// If two people have read it
}
So I'm good if only one person has read it. But when two people have read it, I want it to say "Name One and Name Two have read this." if the logged in person hasn't read it. If they're one of the two people, it should say "You and Name Two have read this".
And so on for 3-5. If 3-5 people have read it, the options would be "Name One, Name Two, and Name Three have read this" or "You, Name Two, and Name Three have read this." up to five people
And if it's 6 or more, it should just say the names of two of them, IE "You, Name Two, and 5 other people have read this."
I considered doing a conditional for each instance and then pushing all of the users to an array. Then I could use in_array() to see if the logged-in user has read it and try to report back, but I'm just having some trouble working up the logic.
Is there an easier way?
Thanks much in advance,
Marcus

I'd say use a switch statement with ranges. You'll have to do a bit of acrobatics to handle the issue of including "You" or not. The code below is untested but give you the general idea.
$message = "";
$readers = array();
$me_included = 0; // Counter increment if you're included in the reader list
$this->db->select('user_id');
$readQuery = $this->db->get_where('books_users', array('book_id' => $isbn));
foreach ($readQuery->result() as $row) {
if ($row->user_id == $user->id) {
$message = "You";
$me_included = 1;
} else {
$readers[] = $this->ion_auth->get_user($row->user_id);
}
}
$reader_count = $sizeof($readers) + $me_included;
switch(TRUE)
{
// One reader, not you
case( ($reader_count == 1) && ($me_included == 0) ):
$message .= $readers[0]->first_name . " " . $readers[0]->last_name . " has read this.";
break;
// Only you
case( ($reader_count == 1) && ($me_included == 1) ):
$message .= " have read this.";
break;
// Two readers
case( ($reader_count == 2) ):
for ($i = 0; $i <= sizeof($readers); $i++) {
if ($i == sizeof($readers)) {
$message .= " and ";
}
$message .= $readers[i]->first_name . " " . $readers[i]->last_name;
}
$message .= " have read this.";
break;
case( ($reader_count > 3) && ($reader_count < 6) ):
if ($me_included) {
$message .= ", ";
}
for ($i = 0; $i <= sizeof($readers); $i++) {
if ($i == sizeof($readers)) {
$message .= " and ";
}
$message .= $readers[i]->first_name . " " . $readers[i]->last_name;
if ($i != sizeof($readers)) {
$message .= ", ";
} else {
$message .= " have read this.";
}
}
break;
case( ($reader_count > 6) ):
if ($me_included) {
$message .= ", " . $readers[0]->first_name . " " . $readers[0]->last_name . " and " . ($reader_count - 2) . " others have read this.";
} else {
for ($i = 0; $i <= 1; $i++) {
$message .= $readers[0]->first_name . " " . $readers[0]->last_name . ", " . $readers[1]->first_name . " " . $readers[1]->last_name . " and " . ($reader_count - 2) . " others have read this.";
}
break;
}

$users = array();
while($row)
{
if(currentuser)
{
array_unshift($users,'You')
}
else
{
$users[] = row[name]
}
}
$count = $max = count($users);
if($max >= 6)
{
$max = 2;
}
$str = '';
for($i=0;$i<$max;$i++)
{
$str .= ($str == '' ? '' : ($i == $count-1 && $count < 6 ? ' And ' : ', ') ) . $users[$i];
}
if($count >= 6)
{
$str .= ' and '.$count-2.' others'
}
This should help you along. It's pretty much pseudo-code but the logic is there to achieve what you want (I believe). You'd obviously want to not fetch all the rows if you are just showing a number of users but that can easily be accomplished.

There are actually a couple places we can optimize this.
1) In the initial query do a JOIN with the user table so we don't have to query again multiple times just for each name:
$readers = $this->db->select('id', 'first_name', 'last_name')->from('books_users')->join('users', 'books_users.id =users.id', 'left')->where('book_id' => $isbn);
2) Additionally, we can avoid iterating over the entire (potentially large) result set just to see if you read it, by doing a separate query:
$you_read = $this->db->get_where('books_users', array('book_id' => $isbn, 'user_id' => $user->id));

Just for the sake of completeness, here is the final code I used. Hopefully it will be of use to someone.
// Find out who has read this book
// Get the users
$current_user = $this->ion_auth->get_user();
$users = $this->ion_auth->get_users();
// Get the readers
$this->db->select('user_id');
$query = $this->db->get_where('books_users', array('book_id' => $isbn));
// If there were results
$readers = array();
if ($query->num_rows() > 0) {
foreach ($users as $user) {
if ($current_user->id == $user->id) {
array_unshift($readers, 'You');
} else {
$readers[] = $user->first_name . ' ' . $user->last_name;
}
$count = $max = count($readers);
if ($max >= 6) {
$max = 2;
}
$message = '';
for ($i = 0; $i < $max; $i++) {
$message .= ($message == '' ? '' : ($i == ($count - 1) && ($count < 6) ? ' and ' : ', ')) . $readers[$i];
}
if ($count >= 6) {
$message .= ' and ' . ($count - 2) . ' others';
}
$message .= ($count == 1 && !$current_user->id ? ' has ' : ' have ') . 'read this.';
}
} else {
$message = 'Be the first to read this.';
}

Related

Array_push in for loop giving null response

Hello I am trying to push in an array using array_push but I am getting the value of the first index then after that all I am getting a null response, I am not getting where I have done a mistake.I am getting the values properly but in array_push there is some mistake which is in for loop.
Here is my code :
function actioncouponcsv_download() {
$this->layout = false;
foreach (Yii::app()->log->routes as $route) {
if ($route instanceof CWebLogRoute || $route instanceof CFileLogRoute || $route instanceof YiiDebugToolbarRoute) {
$route->enabled = false;
}
}
$dateRange = json_decode($_POST['dateRange'], true);
$start = $dateRange['start'];
$end = $dateRange['end'];
$validity = $_POST['validity'];
$limit = isset($_REQUEST['limit']) && trim($_REQUEST['limit']) ? $_REQUEST['limit'] : 0;
$studio_id = Yii::app()->user->studio_id;
if (isset($_GET['type']) && intval($_GET['type']) ==2) {
$couponobj = new CouponSubscription();
$getcouponobj = $couponobj->getcoupon_data($studio_id,$start,$end,$validity);
$k = 0;
$title_addon = "\t" . "Discount Cycle" . "\t" . "Extend free trail";
$data_addon = "\t" . $getcouponobj[$k]['discount_multiple_cycle'] . "\t" . $getcouponobj[$k]['extend_free_trail'];
} else {
$title_addon = "";
$data_addon = "";
$couponobj = new Coupon();
$getcouponobj = $couponobj->getcoupon_data($studio_id,$limit,1);
}
//$Coupon = Coupon::model()->find('studio_id=:studio_id', array(':studio_id' => $studio_id));
$dataCsv = '';
if ($getcouponobj) {
$headings = "Sl no" . "\t" . "Coupon" . "\t" . "Coupon Type" . "\t" . "Used by a single user" . "\t" . "Valid" . "\t" . "Used" . "\t" . "User" .$title_addon. "\t" . "Used Date". "\t" . "Content Category". "\t" . "Content"."\n";
$i = 1;
$dataCSV[] = Array();
$j = 0;
for ($k = 0; $k < count($getcouponobj); $k++) {
$userList = '-';
if ($getcouponobj[$k]['used_by'] != '0') {
if ($getcouponobj[$k]['coupon_type'] == 1) {
$userList = '';
$userIdList = explode(",", $getcouponobj[$k]['used_by']);
foreach ($userIdList as $userIdListKey => $userIdListVal) {
if ($userIdListKey == 0) {
$userList .= Yii::app()->webCommon->getuseremail($userIdListVal);
} else {
$userList .= " | " . Yii::app()->webCommon->getuseremail($userIdListVal);
}
}
} else {
$userList = Yii::app()->webCommon->getuseremail($getcouponobj[$k]['used_by']);
}
}
if($getcouponobj[$k]['is_all']!=1){
if($getcouponobj[$k]['content_category']==1){
$cont_cat = "Digital";
$content_str = Coupon::model()->getContentInfo($getcouponobj[$k]['specific_content']);
$cont_str = $content_str;
}else if($getcouponobj[$k]['content_category']==2){
$cont_cat = "Physical";
$content_str = Coupon::model()->getContentInfoPhysical($getcouponobj[$k]['specific_content']);
$cont_str = $content_str;
}else{
$cont_cat = "All";
$cont_str = "All";
}
}else{
$cont_cat = "All";
$cont_str = "All";
}
#echo $getcouponobj[$k]['coupon_code'];
array_push($dataCSV[$j],$i);
array_push($dataCSV[$j],$getcouponobj[$k]['coupon_code']);
array_push($dataCSV[$j],(($getcouponobj[$k]['coupon_type'] == 1) ? 'Multi-use' : 'Once-use'));
array_push($dataCSV[$j],(($getcouponobj[$k]['user_can_use'] == 1) ? 'Multiple times' : 'Once'));
array_push($dataCSV[$j],(($getcouponobj[$k]['used_by'] == 0) ? 'Yes' : 'No'));
array_push($dataCSV[$j],(($getcouponobj[$k]['used_by'] == 0) ? '-' : 'Yes'));
array_push($dataCSV[$j],$userList);
array_push($dataCSV[$j],$getcouponobj[$k]['discount_multiple_cycle']);
array_push($dataCSV[$j],$getcouponobj[$k]['extend_free_trail']);
array_push($dataCSV[$j],(($getcouponobj[$k]['cused_date'] == 0) ? '-' : $getcouponobj[$k]['cused_date']));
array_push($dataCSV[$j],$cont_cat);
array_push($dataCSV[$j],$cont_str);
$j++;
//$dataCsv .= $i . "\t" . $getcouponobj[$k]['coupon_code'] . "\t" . (($getcouponobj[$k]['coupon_type'] == 1) ? 'Multi-use' : 'Once-use') . "\t" . (($getcouponobj[$k]['user_can_use'] == 1) ? 'Multiple times' : 'Once') . "\t" . (($getcouponobj[$k]['used_by'] == 0) ? 'Yes' : 'No') . "\t" . (($getcouponobj[$k]['used_by'] == 0) ? '-' : 'Yes') . "\t" . $userList .$data_addon. "\t" . (($getcouponobj[$k]['cused_date'] == 0) ? '-' : $getcouponobj[$k]['cused_date'])."\t" .$cont_cat ."\t".$cont_str."\n";
$i = $i+1;
}
}
print_r(json_encode($dataCSV));
}
PS: I am getting the values. Any help will be highly appreciated.
Well, first thing i see wrong is the way you declare your array:
$dataCSV[] = Array();
$array[] = Means that you are adding a new value to an existing array. To declare your array you should use
$dataCSV = array();
Also, this code:
array_push($dataCSV[$j],$i);
means that you are adding a new value to your $dataCSV[$j] array, but this is never declared as an array, so first thing would be to do
$dataCSV[$j] = new array();
Your code is really long and complicated, those are only examples of issues i see in there.

Getting Notice: Undefined offset: 0

I am getting this error in 3 spots in the function that I pasted below. There is more to this code, but I didn't think it was needed to get this thing figured out.
$count = count($collection);
$i = 1 ;
foreach ($collection as $product)
{
$j = 1 ;
$productId = $product->getDiamondsearchId();
$attributValueOptions = "[" ;
$attributValueOptions .= "'".$productId."', ";
foreach($filterAttributeIds as $filterAttributeId){
$attributValueCollection = Mage::getModel('diamondsearch/diamondsearchattributvalue')->getCollection()->addFieldToFilter('attribut_id',$filterAttributeId)->addFieldToFilter('diamondsearch_id',$productId)->getData();
$attrbutValueId = $attributValueCollection[0]['attrbut_value_id'];
//echo $attrbutValueId."<br>";
$attributValueOptionCollection = Mage::getModel('diamondsearch/diamondsearchattributoptionvalue')->getCollection()->addFieldToFilter('id',$attrbutValueId)->getData();
if($j == 1 && $attributValueOptionCollection[0]['attribut_value'] == ""){
break ;
}
if($j == 15){
$attributValueOptions .= "'".$attributValueOptionCollection[0]['attribut_value']."'";
}else{
$attributValueOptions .= "'".$attributValueOptionCollection[0]['attribut_value']."', ";
}
$j++;
}
if($count == $i ){
$attributValueOptions .= "]";
}else{
$attributValueOptions .= "], ";
}
$i++;
echo $attributValueOptions ;
}
The problem is with this line:
$attributValueCollection = Mage::getModel('diamondsearch/diamondsearchattributvalue')->getCollection()->addFieldToFilter('attribut_id',$filterAttributeId)->addFieldToFilter('diamondsearch_id',$productId)->getData();
$attrbutValueId = $attributValueCollection[0]['attrbut_value_id'];
You're trying to get the first item of array, but this variable is empty. You should verify and then do the stuff you want, like this:
if(!empty(attributValueCollection)){
$attrbutValueId = $attributValueCollection[0]['attrbut_value_id'];
Here's the complete gist:
https://gist.github.com/muriloazevedo/8dc5b11b17d1c4a3a518
But also is important to remember, if you trying to generate a json result, is better to use json_encode for that:
http://php.net/manual/pt_BR/function.json-encode.php

Why is my loop not incrementing?

I am trying to take a subset of an mysql statements results from an if statement, and if the last one in the sequence, apply appropriate code.
I want to set up two increments and then if($secondcount > $totalcount) do something else.
MySqlNUMRows won't work as it is a subset, neither will a where clause in this case, that I can see. Can anyone see the cause?
$counting = 0;
while($thisrow = mysqli_fetch_array($sqlchangenamesresult))
{
$change_name = $thisrow['change_name'];
#count the updating results
if(strstr($row['Content_lists'], $change_name) != FALSE)
{
$counting++;
}
$totalcount = $counting;
$secondcount = 0;
if(strstr($row['Content_lists'], $change_name) != FALSE)
{
if($secondcount > $totalcount)
{
echo '<br>' .$secondcount. '<br>' . $totalcount;
$sqlinsert .= $thisrow['change_name'];
$sqlinsert2 .= 'Yes';
$secondcount++;
}
else
{
echo '<br>' .$secondcount. '<br>' . $totalcount;
$sqlinsert .= $thisrow['change_name'] . ', ';
$sqlinsert2 .= 'Yes, ';
$secondcount++;
}
}
$secondcount is 0, so it cannot be larger than $totalcount.
note:
!= FALSE is incorrect
$totalcount always equals $counting. why have to variables?
$secondcount++; is in both branches.. move it out of the branch body.

How To Change Numbers Based On Results

I have a follow up question on something I got help with here the other day (No Table Three Column Category Layout).
The script is as follows:
$res = mysql_query($query);
$system->check_mysql($res, $query, __LINE__, __FILE__);
$parent_node = mysql_fetch_assoc($res);
$id = (isset($parent_node['cat_id'])) ? $parent_node['cat_id'] : $id;
$catalist = '';
if ($parent_node['left_id'] != 1)
{
$children = $catscontrol->get_children_list($parent_node['left_id'], $parent_node['right_id']);
$childarray = array($id);
foreach ($children as $k => $v)
{
$childarray[] = $v['cat_id'];
}
$catalist = '(';
$catalist .= implode(',', $childarray);
$catalist .= ')';
$all_items = false;
}
$NOW = time();
/*
specified category number
look into table - and if we don't have such category - redirect to full list
*/
$query = "SELECT * FROM " . $DBPrefix . "categories WHERE cat_id = " . $id;
$result = mysql_query($query);
$system->check_mysql($result, $query, __LINE__, __FILE__);
$category = mysql_fetch_assoc($result);
if (mysql_num_rows($result) == 0)
{
// redirect to global categories list
header ('location: browse.php?id=0');
exit;
}
else
{
// Retrieve the translated category name
$par_id = $category['parent_id'];
$TPL_categories_string = '';
$crumbs = $catscontrol->get_bread_crumbs($category['left_id'], $category['right_id']);
for ($i = 0; $i < count($crumbs); $i++)
{
if ($crumbs[$i]['cat_id'] > 0)
{
if ($i > 0)
{
$TPL_categories_string .= ' > ';
}
$TPL_categories_string .= '' . $category_names[$crumbs[$i]['cat_id']] . '';
}
}
// get list of subcategories of this category
$subcat_count = 0;
$query = "SELECT * FROM " . $DBPrefix . "categories WHERE parent_id = " . $id . " ORDER BY cat_name";
$result = mysql_query($query);
$system->check_mysql($result, $query, __LINE__, __FILE__);
$need_to_continue = 1;
$cycle = 1;
$column = 1;
$TPL_main_value = '';
while ($row = mysql_fetch_array($result))
{
++$subcat_count;
if ($cycle == 1)
{
$TPL_main_value .= '<div class="col'.$column.'"><ul>' . "\n";
}
$sub_counter = $row['sub_counter'];
$cat_counter = $row['counter'];
if ($sub_counter != 0)
{
$count_string = ' (' . $sub_counter . ')';
}
else
{
if ($cat_counter != 0)
{
$count_string = ' (' . $cat_counter . ')';
}
else
{
$count_string = '';
}
}
if ($row['cat_colour'] != '')
{
$BG = 'bgcolor=' . $row['cat_colour'];
}
else
{
$BG = '';
}
// Retrieve the translated category name
$row['cat_name'] = $category_names[$row['cat_id']];
$catimage = (!empty($row['cat_image'])) ? '<img src="' . $row['cat_image'] . '" border=0>' : '';
$TPL_main_value .= "\t" . '<li>' . $catimage . '' . $row['cat_name'] . $count_string . '</li>' . "\n";
++$cycle;
if ($cycle == 7) // <---- here
{
$cycle = 1;
$TPL_main_value .= '</ul></div>' . "\n";
++$column;
}
}
if ($cycle >= 2 && $cycle <= 6) // <---- here minus 1
{
while ($cycle < 7) // <---- and here
{
$TPL_main_value .= ' <p> </p>' . "\n";
++$cycle;
}
$TPL_main_value .= '</ul></div>'.$number.'
' . "\n";
}
I was needing to divide the resulting links into three columns to fit my html layout.
We accomplished this by changing the numbers in the code marked with "// <---- here".
Because the amount of links returned could be different each time, I am trying to figure out how to change those numbers on the fly. I tried using
$number_a = mysql_num_rows($result);
$number_b = $number_a / 3;
$number_b = ceil($number_b);
$number_c = $number_b - 1;
and then replacing the numbers with $number_b or $number_c but that doesn't work. Any ideas?
As mentioned before, you can use the mod (%) function to do that.
Basically what it does is to get the remainder after division. So, if you say 11 % 3, you will get 2 since that is the remainder after division. You can then make use of this to check when a number is divisible by 3 (the remainder will be zero), and insert an end </div> in your code.
Here is a simplified example on how to use it to insert a newline after every 3 columns:
$cycle = 1;
$arr = range (1, 20);
$len = sizeof ($arr);
for ( ; $cycle <= $len; $cycle++)
{
echo "{$arr[$cycle - 1]} ";
if ($cycle % 3 == 0)
{
echo "\n";
}
}
echo "\n\n";

add an if echo statement to my search engine

I have a search engine and because of the paralympics, I want people to be able to see a h1 countdown I have placed at the top of my site. Underneath will be the looped results from my database. Any ideas where I go wrong? because in this if, it won't echo the h1 tag at all. I would like to above my results.
$query = " SELECT * FROM scan WHERE ";
$terms = array_map('mysql_real_escape_string', $terms);
$i = 0;
foreach ($terms as $each) {
if ($i++ !== 0) {
$query .= " OR ";
}
$query .= "keywords LIKE '%{$each}%'";
}
// Don't append the ORDER BY until after the loop
$query .= "ORDER BY rank";
$query = mysql_query($query) or die('MySQL Query Error: ' . mysql_error($connect));
$numrows = mysql_num_rows($query);
if ($numrows > 0) {
while ($row = mysql_fetch_assoc($query)) {
$id = $row['id'];
$title = $row['title'];
$description = $row['description'];
$keywords = $row['keywords'];
$link = $row['link'];
$rank = $row['rank'];
echo '<h2><a class="ok" href="' . $link . '">' . $title . '</a></h2>' . PHP_EOL;
echo '<p maxlength="10" class="kk">' . $description . '</p>' . PHP_EOL;
echo '<p><a class="okay" href="' . $link . '">' . $link . '<br><br><span class="keywords"></p>' . PHP_EOL;
}
} else {
echo "No results found for \"<b>{$k}</b>\"";
}
if ($k = "Paralympics 2012") {
echo "<h1> Countdown to Paralympics: 7 Days </h1>";
}
if ($k = "Paralympics 2012") {
echo "<h1> Countdown to Paralympics: 7 Days </h1>";
}
Will always print the <h1>. You're doing assignment rather than comparison. Try:
if ($k == "Paralympics 2012")
Also, verify that $k is what you expect it to be when debugging.
One equals (=) assigns, and two/three (==/===) compares. The line
if ($k = "Paralympics 2012") {
Assigns $k to a string, which always returns true, because any string other than an empty one ("") is truthy. Try this:
if ($k === "Paralympics 2012") {
First things first, the <h1> is always displaying, opposite of what you're question states. It's always displaying due to the fact that you're doing an assignment of a non-false value with:
if ($k = "Paralympics 2012") {
Update that to use a comparison to fix that logic issue.
if ($k == "Paralympics 2012") {
Next, to get it to display above your results, you need to actually move that if-statement above the loop that echos the results. Try placing it in the if ($numrows > 0) { block, like this:
if ($numrows > 0) {
if ($k == "Paralympics 2012") {
echo "<h1> Countdown to Paralympics: 7 Days </h1>";
}
while ($row = mysql_fetch_assoc($query)) {
...

Categories