php "count()" function and DB - php

I have a Joomla 1.5 site. I have articles in my site with different "status". What I'm trying to do is "count" and show how many articles have for example "status = 1"(expired) or "status = 3"(blocked) or "status = 2"(active) etc..
Here is the statuses in PhpMyAdmin - http://awesomescreenshot.com/07a8ijz75
Here is what I wrote, but it ALWAYS gives me same result - 1
<?php echo count($this->row->status==1) ?>
Did I miss something?
Thanks

Use the SQL count function.
select count(*) from articles where status = 1;
Use your DB! If you are sorting, counting, etc, data from a database in PHP code you're doing it wrong.
If you want all statuses, do something like:
select status, count(*) from articles group by status;

The count function in PHP counts all the elements in an array, and in your example you passed it a boolean value. As a result count doesn't know what to do with it, and so it returns -1, which isn't a valid count.
My PHP is really rusty (I haven't used it in a looong time), but here are two possible ways to accomplish what you want:
1. Use a function map/reduce style
<?php
$row[0]->status = 1;
$row[1]->status = 2;
$row[2]->status = 1;
$row[3]->status = 3;
$row[4]->status = 1;
// Count the number of statuses that are equal to 1
echo array_reduce(array_map(function($x) {
return $x->status == 1 ? 1: 0;
}, $row), function($x, $y) {return $x + $y;});
You'll have to replace the $row variable with $this->row, obviously. The code is essentially working in two steps. The inner part:
array_map(function($x) {
return $x->status == 1 ? 1: 0;
}, $row)
Creates a list where every status that's equal to 1 becomes a 1 and everything else becomes a 0. So you have an array of "array(1, 0, 1, 0, 1)". The out part of the code:
array_reduce( ... , function($x, $y) {return $x + $y;});
Takes the new array as the first argument and sums it all up by passing in the first two values of the array into the function, and then each following value and the result of the last function call. As a result all the values get summed, and you have a proper count of the matching values.
2. Use a simple procedural style
<?php
$row[0]->status = 1;
$row[1]->status = 2;
$row[2]->status = 1;
$row[3]->status = 3;
$row[4]->status = 1;
// Do it again, but in a procedural style
$num_1_statuses = 0;
foreach ($row as $r) {
if ($r->status == 1) {
$num_1_statuses++;
}
}
echo $num_1_statuses;
This should be really straightforward, it just has a variable that gets incremented whenever a row's status matches.

Related

Sums data from an array that has the same id

I have a query about this project that I am doing, I make a query to my two tables and the data that I call in this case is a quantity number for both, the data displayed is the one that has the same id for both tables.
The problem occurs when I pass two identifiers and to those two identifiers I want to add their current amount with the amount obtained from the other table
In general, what I want to do is add the amounts obtained, this is my code that I am working with, I would really appreciate if you can help me solve it or guide me.
$id_servis = [1077,1078];
$sum_quantity_add = Servis_tareas::where('servis_id',$id_servis)->get();
foreach($sum_quantity_add as $sum_add){
$quantity_two[] = $sum_add->quantity;
}
$quantity_actual = Servis::wherein('id',$id_servis)->get();
foreach($quantity_actual as $quantity_act){
$quantity_one[] = $quantity_act->quantity_final;
}
dd($id_servicios,$quantity_one, $quantity_two);
//ERROR
$total[] = $quantity_one + $quantity_two;
//ERROR
if(is_numeric($total) < 0 ){
Servis::wherein('id',$id_servis)->update(['quantity_final' => 0]);
}else{
Servis::wherein('id',$id_servis)->update(['quantity_final' => $total]);
}
In MySql/SQL there is SUM query which handles the addition and they are called Aggregation Functions, and in Laravel there is a Eloquent equivalent of these Laravel Aggregates, using these methods you will be able to count, max, min, avg on the query end rather than in the PHP end.
So, your code will look like
$id_servis = [1077, 1078];
$sum_quantity_add = Servis_tareas::where('servis_id', $id_servis)->SUM('quantity');
$quantity_actual = Servis::wherein('id', $id_servis)->SUM('quantity_final');
$total = $sum_quantity_add + $quantity_actual;
What you are trying is treating array as numeric value and adding it, which is wrong, + operator behaves totally different while you are using with array, it merges the two array, it is different than array_merge too, so i recommend giving this answer a read + operator for array in PHP
UPDATED:
I still don't understand if you want to replace with the SUM from Servis_tareas in the Servis Table or sum the each others quantity and save it, Code below sum the data from both table and save it.
$id_servis = [1077, 1078];
$servisTareas = Servis_tareas::selectRaw("SUM(`quantity`) as total, `servis_id` ")
->where('servis_id', $id_servis)
->groupBy('servis_id')
->having('total', '>', 0)
->get();
$foundId = [];
$servisTotal = Servis::query()->whereIn('id', $id_servis)->pluck('quantity_final', 'id')->toArray();
foreach ($servisTareas as $servisTarea) {
$foundId[] = $servisTarea->servis_id;
$total = $servisTarea->total + ($servisTotal[$servisTarea->servis_id] ?? 0)
Servis::where('id', $servisTarea->servis_id)->update(['quantity' => $total]);
}
if (!empty($foundId)) {
Servis::whereNotIn('id', $foundId)->update(['quantity' => 0]);
}

MySQL Recursive Get Right Nodes PHP

I have a table containing user id with left node and right node (Both are which user id). I am trying to create a function to count all the right nodes and total nodes of a particular user id in PHP.
The Code I have written till now which is always returning 0 :
function allcount($id) //Function to calculate all children count
{
$sqlz = "SELECT * FROM user_transaction_details WHERE user_id = '$id'";
$execsql = mysqli_query($conn,$sqlz);
$array = mysqli_fetch_array($execsql);
echo $sqlz;
(array_count_values($array));
$count = 0;
echo $array['l_node'];
if(!empty($array['l_node']))
{
$count += allcount($array['l_node']) +1;
}
if(!empty($array['r_node']))
{
$count += allcount($array['r_node']) +1;
}
return $count;
}
Here is the table structure :
Table Structure
Can anybody please help.
You need to pass $conn as an argument or declare it as global inside the function, because otherwise it is not available inside the function.

Pulling specific random values from php array

On the page I'm creating there is graphic representation of pigeon-holes with five compartments for new comments. If there is new unread comment it should show up as graphic in one random compartment. But it won't happen if all of the 5 are
already occupied. So if someone writes new comment I like the code to check for if there is already five of them taken, and if not, than to randomly occupied one of the remaining ones. So "new_c" stands for number of
unread (new) comments, and c1-c5 stands for compartments. Value 0 means empty compartment for each "c". I was trying to make code that would first separate new_c from rest of the array after knowing the number is smaller than 5,
so I'm only working with 5 compartments. And than to determine which one is/are empty. And then randomly choose one empty to occupy. It's not really working as it is I probably am not using that array_keys properly as c2 is changed to some other value than 0 but still is being echoed, there is probably also a better/more efficient way to achieve that. I will really appreciate some input.
<?php
$tucQuery = "SELECT new_c,c1,c2,c3,c4,c5 FROM users WHERE id = '{$author_id}' LIMIT 1";
$result_tuc = mysqli_query($connection, $tucQuery);
$tucArray = mysqli_fetch_assoc($result_tuc);
mysqli_free_result($result_tuc);
$new_c = $tucArray[0];
if($new_c < 5){
$new_array = array_keys((array_slice($tucArray,1)), 0);
$rand_zero = array_rand($new_array, 1);
echo $rand_zero + 1;
}
?>
Bellow code works but it doesn't seem to be efficient and there is probably a better way.
if($new_c < 5){
$empties = array();
if($tucArray['c1'] == 0){
$empties[] = 1;
}
if($tucArray['c2'] == 0){
$empties[] = 2;
}
if($tucArray['c3'] == 0){
$empties[] = 3;
}
if($tucArray['c4'] == 0){
$empties[] = 4;
}
if($tucArray['c5'] == 0){
$empties[] = 5;
}
print_r($empties);
$rand_zero = array_rand((array_flip($empties)), 1);
echo $rand_zero;
}

Php how to check for duplicate results?

Hi I'm currently querying from a database base user ids for a contest, However I want to avoid choosing duplicates in my results_array, this function getrandomspecies receives a array_result, this array results iterates 7 times. How test that I don't put duplicates in my results_array? I have gotten several duplicates.
function getrandomspecies($array_result){
//database connection
$dbn = adodbConnect();
foreach($array_result as $possible){
//query the results
$querys= "select * from taxonomic_units where tsn = $possible";
$resultss = $dbn -> Execute($querys);
while($rowss=$resultss->FetchRow()){
$id = $rowss['tsn']; //there ID
$ranksss = $rowss['rank_id']; //ranking id, I choose 220 and 230
if($ranksss == 220 || $ranksss == 230){
$prelimary_array[] = $id;
}
}
//grab random index
$index = array_rand($prelimary_array,1);
//put result id into a variable
$newspecies = $prelimary_array[$index];
//put that variable in an array
$results_array[] = $newspecies; //there is 7 newspecies/winners at the end, I dont want duplicates
}
return $results_array;
}
MySQL should be the following :
select distinct tsn, rank_id from taxonomic_units where tsn = $possible
But you should ideally use prepared statements.
what about this? You may do it with one query:
$querys= "select DISTINCT tsn from taxonomic_units where tsn IN (".implode(",",$array_result).") AND rank_id IN (220,230) ORDER BY RAND() LIMIT 7 ";
Loop your result array and if it does not exists add it. If you end up with less than 7, do your big loop again.
replace this line :
$results_array[] = $newspecies;
by:
$loop_1_more_time=0;
if (isset($results_array)){
foreach($results_array as $result){
if ($result == $new_specie){
$loop_1_more_time=1;
}
}
}
if ($loop_1_more_time == 0){
$results_array[] = $newspecies;
}
//there, if $loop_1_more_time equals 1, start again. To start again and be sure you have seven instead of 6 or less, You could replace your big first "foreach" loop with a "for" loop that depends of the count() of the $array_result, and the $array_result would be array_result[$i] instead of $possible. $i would start at 0 and increment at each end of loop. It would not be incremented if ­­$loop_1_more_time==1;.
Example :
for ($i = 0; $i < count($array_result); $i++) {
//stuff
//if ($loop_1_more_time=1;) { $i--; }
}
Why don't you try shuffling the array, and then picking the first X numbers?
That way, rather than having to check the results array for duplicates, it will never come up in the first place

Using Inner Join and mysql_num_rows() is Always returning 1 less row

I checked throught the existing topics. I have a fix for my problem but I know its not the right fix and I'm more interested making this work right, than creating a workaround it.
I have a project where I have 3 tables, diagnosis, visits, and treatments. People come in for a visit, they get a treatment, and the treatment is for a diagnosis.
For displaying this information on the page, I want to show the patient's diagnosis, then show the time they came in for a visit, that visit info can then be clicked on to show treatment info.
To do this a made this function in php:
<?
function returnTandV($dxid){
include("db.info.php");
$query = sprintf("SELECT treatments.*,visits.* FROM treatments LEFT JOIN visits ON
treatments.tid = visits.tid WHERE treatments.dxid = '%s' ORDER BY visits.dos DESC",
mysql_real_escape_string($dxid));
$result = mysql_query($query) or die("Failed because: ".mysql_error());
$num = mysql_num_rows($result);
for($i = 0; $i <= $num; ++$i) {
$v[$i] = mysql_fetch_array($result MYSQL_ASSOC);
++$i;
}
return $v;
}
?>
The function works and will display what I want which is all of the rows from both treatments and visits as 1 large assoc. array the problem is it always returns 1 less row than is actually in the database and I'm not sure why. There are 3 rows total, but msql_num_rows() will only show it as 2. My work around has been to just add 1 ($num = mysql_num_rows($result)+1;) but I would rather just have it be correct.
This section looks suspicious to me:
for($i = 0; $i <= $num; ++$i) {
$v[$i] = mysql_fetch_array($result MYSQL_ASSOC);
++$i;
}
You're incrementing i twice
You're going to $i <= $num when you most likely want $i < $num
This combination may be why you're getting unexpected results. Basically, you have three rows, but you're only asking for rows 0 and 2 (skipping row 1).
Programmers always count from 0. So, you are starting your loop at 0. If you end at 2, you have reached 3 rows.
Row0, Row1, Row2.
if $i = 0, and u increment it BEFORE adding something to the array, u skip the first row. increment $i AFTER the loop runs to start at 0 (first key).
For loops are not good for this: rather do:
$query=mysql_query(' --mysql --- ');
while ($row=mysql_fetch_array($query)){
$v[]=$row["dbcolumn"];
}
return $v for your function then.compact and neat. you can create an associative array, as long as the key name is unique (like primary ids).. $v["$priid"]=$row[1];

Categories