Better solution to this query - php

$query = $this->db->query("SELECT field_name FROM table_name;");
$getData= array();
foreach ($query->result() as $row) {
array_push($getData, $row->field_name);
}
I use codeigniter, for every table that I need to manage if the data exist for update or make a new insert I use this code so i would like to see is there are more options for dont replicate the code every time. I'm just a student, sorry for mi english

It is not clear why you are doing this, but I would call it "flattening" the array. If you find the need to do this often then creating a "worker" method might help.
For example, in a model, you might have two methods that both need "flat" results.
public function get_something()
{
$query = $this->db->query("SELECT field_name FROM table_name;");
//call the "worker"
return $this->make_flat($query);
}
public function get_something_else()
{
$query = $this->db->query("SELECT field_name FROM table_name;");
//call the "worker"
return $this->make_flat($query);
}
Elsewhere in the model, there is this "worker" method used in the code above used.
// The "worker" method to flatten the results
protected function make_flat($query)
{
$getData = []; //is same as $getData = array(); but with less typing
foreach ($query->result() as $row)
{
$getData[] = $row->field_name;
}
return $getData;
}
The line $getData[] = $row->field_name; does exactly the same thing as array_push($getData, $row->field_name);. But it is actually a bit faster. It is also less typing.

http://php.net/manual/en/function.array-column.php should work great for this.
$query = $this->db->query("SELECT field_name FROM table_name;");
$array = array_column($query, 'field_name');
print_r($array);
your question seems to contradict your code. if you just want to see if a particular entry already exists you can do:
$this->db->where('field_name', $var);
$exists = $this->db->count_all_results('table_name');
if ($exists > 0) {
// update
// there is an entry with $var for `field_name` in table `table_name`
} else {
// insert
}

Related

Recursive looping returns 500 Internal Server Error

I'm getting a 500 Internal server error when recursive is called in loop. Only then I get a 500 error.
When I remove recursive in loop everything work good:
Code:
public function getRecrusiveReferals($userID) {
$sql = "SELECT user_id, username, refered_by FROM users WHERE refered_by = ?";
$referals = $this->db->query($sql, $userID);
$list = $this->buildReferalsTree($referals->result_array());
return $list;
}
private function buildReferalsTree(array $referals, $parentID = 0) {
$data = array();
foreach ($referals as $item) {
if($item['refered_by']) {
$children = $this->buildReferalsTree($referals, $parentID);
if($children) {
$item['children'] = array();
}
}
$data[] = $item;
}
return $data;
}
Your code has a infinite recursive loop causing your script to be killed by PHP when the recursion reaches the limit set by PHP for the recursion depth.
This code is called again and again with the same set of arguments:
$children = $this->buildReferalsTree($referals, $parentID);
For recursive function to terminate, there should be a condition which should define when the recursion ends, I do not see that in your code.
As Jay Rajput said, you've got infinite recursion there. I think that the call
$children = $this->buildReferalsTree($referals, $parentID);
should pass not the $referals, but another array, built based on 'refered_by' element of $item.
So basically you need to create another private method, that extracts new $referals.
You must be still aware that this code won't be errorprone, and if two items refer each other you will still end with an infinite recursion.
What you're trying to accomplish is quite a challenge, especially when you're using relational database. You definitely would like to look at the 'nested set' concept in relational databases.
You'll want to pass a new value for the parent argument, not the same over and over again. Like this:
$children = $this->buildReferalsTree($referals, $item['user_id']);
Then in the loop you need to also filter by the parent ID:
if($item['refered_by'] = $parentID)
... so you will only link items that are "children" of that ID.
Furthermore, your original call should also specify the parentID, since you select only a specific referred_by subset of your table:
$list = $this->buildReferalsTree($referals->result_array(), $userID);
However, this will give an uninteresting result, since you only selected records with the same referred_by value, so there is not much to build a tree from. Instead, you could select all records from that table, and then still pass $userID to buildReferalsTree which will then have all the other records available for following the chains of referrals. So here is the code to select all records:
$sql = "SELECT user_id, username, refered_by FROM users";
$referals = $this->db->query($sql);
Finally, there is also an error in the inner if block where you currently assign an empty array to $item['children']. You should instead assign the result from the recursive call, like this:
if($children) {
$item['children'] = $children;
}
Taking this all together, the code would look like this:
public function getRecrusiveReferals($userID) {
$sql = "SELECT user_id, username, refered_by FROM users";
$referals = $this->db->query($sql);
$list = $this->buildReferalsTree($referals->result_array(), $userID);
return $list;
}
private function buildReferalsTree(array $referals, $parentID = 0) {
$data = array();
foreach ($referals as $item) {
if ($item['refered_by'] == $parentID) {
$children = $this->buildReferalsTree($referals, $item['user_id']);
if($children) {
$item['children'] = $children;
}
}
$data[] = $item;
}
return $data;
}
This could still give an infinite recursion if your data has cycles in terms of referrals. Given the meaning of a referral, this should however not be the case.

PHP convention in retrieving results indexed by a particular column?

I often need to retrieve results and access them by a given column.
Is there a way to write this without walking through the whole dataset each time?
I looked into various PDO fetch modes, but nothing jumped out as being simpler than that. Thanks.
function get_groups() {
$stmt = $dbc->prepare("SELECT * FROM groups ORDER BY group_name");
$stmt->execute();
$groups = $stmt->fetchAll();
$return = [];
foreach($groups as $group) {
$return[$group['id']] = $group;
}
return $return;
}
My proposed solution was pretty obsolete. The right solution comes from this answer
$stmt = $pdo->query("SELECT foo,baz FROM bar")
$groupedByFooValuesArray = $stmt->fetchAll(\PDO::FETCH_GROUP|\PDO::FETCH_UNIQUE)
to group it by another column, change the first column you select
if your goal is to have your same array indexed by different column values, I think the only option is to actually index them by different column values.
you can do that by controlling by which field the array is returned
function get_groups($sql,$key,$values='') {
if ($values != '') {
$stmt = $dbc->prepare($sql);
$stmt->execute($values);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
}
else {
$rows = $dbc->query($sql)->fetchAll(PDO::FETCH_ASSOC);
}
foreach ($rows as $row) {
$indexed[$row[$key]] = $row;
}
return $indexed;
}
then, use get_groups to build an indexed array:
$sql = 'SELECT * FROM groups ORDER BY group_name'
var_dump(get_groups($sql,'id'));
There might be a way to store a resultset in some way that you can fetchAll() it multiple times, that would be awesome. but I don't know it.

Codeigniter function array always returns no

Rather noobish question. Given the following code:
public function in_group($group)
{
$session = $this->CI->session->userdata('logged_in');
$query = $this->CI->db->get_where('people_groups', array('people_id' => $session['user_id']));
$array = array();
foreach ($query->result() as $row)
{
$array = $row->group_id;
}
if ( $array == $group)
{
return 'YES';
}
return 'no';
}
The result is always no, when in fact it should be yes according to the database.
What i am trying to do is to check the people_groups table to see if the current user is in the requested $group. I have research as to how to use the arrays in the following way, but i fear i have done something rather noobish.
NOTE: The $group_id references the column in the table that stores the group id's
It's not inserting values into the array, so change this:
$array = $row->group_id;
to
$array[] = $row->group_id;
You should just change your query to select where there is a row with that user and group id, something like this:
$this->CI->db->select('*');
$this->CI->db->from('people_groups');
$this->CI->db->where('people_id', $session['user_id']);
$this->CI->db->where('group_id', $group);
$query = $this->CI->db->get();
Then you can just check if there is a result or not, instead of looping through all the results.
I descovered that i missed a section in the user guide to achieve what i wanted the correct code should have been:
public function in_group($group)
{
$session = $this->CI->session->userdata('logged_in');
$query = $this->CI->db->get_where('people_groups', array('people_id' => $session['user_id']));
foreach ($query->result_array() as $row)
{
if ( $row['group_id'] == $group)
{
return 'YES';
}
return 'no';
}
}
Thank you to the people who responded, I hope this helps other people making silly mistakes :)

PHP array not updating

There is probably something dumb I am doing wrong here.
public function get_scores($id)
{
$results = array();
$sql = "SELECT * FROM scores WHERE comp_id = $id";
$rows = $this->db->query($sql)->result();
foreach($rows as $row) {
if($row->confirmed_id) {
$results[$row->uid] += $row->score;
}
}
sort($results);
return $results;
}
So basically what I am trying to do is add all of the users scores in the database and return them in order of rank. confirmed->id is just a check to make sure the score has been confirmed (and thus is addable to their total score). I am basically trying to just make an associative array where the key is the users ID, and the score of each question they have in the database is added on. The query works fine, and $row-uid and $row->score both return the correct thing for every row, but $results[] never has anything added to it. If I even change it just to something silly like $results[3] = 0 at top, and then $results[3]++ or += 1 in the for loop, it doesn't add anything to $results[3].
EDIT: Problem solved. Indeed was something dumb -- confirmed_id was set to null by my partner when he reran our database after I had previously set it all to 1. Thanks guys :)
You are adding to $results[something] before it exists. You need to create it in the first case and then only increment it once it exists.
You need to remove the "+=" operation from the code. Check with this.
public function get_scores($id)
{
$results = array();
$sql = "SELECT * FROM scores WHERE comp_id = $id";
$rows = $this->db->query($sql)->result();
foreach($rows as $row)
if($row->confirmed_id)
$results[$row->uid] = $row->score;
sort($results);
return $results;
}
Your previous operation is similar to
$results[$row->uid] = $results[$row->uid] + $row->score;
So it will not add values to your row.

How do you create a simple function to query the database? Mine isn't working!

I want to make a simple function that I can call on to query my database. I pass the "where" part of the query to it and in the code below, my $q variable is correct. However, what should I then do to be able to use the data? I'm so confused at how to do something I'm sure is extremely easy. Any help is greatly appreciated!
function getListings($where_clause)
{
$q = "SELECT * FROM `listings` $where_clause";
$result = mysql_query($q,$dbh);
foreach (mysql_fetch_array($result) as $row) {
$listingdata[] = $row;
}
return $listingdata;
}
Your function should be like this:
function getListings($where_clause, $dbh)
{
$q = "SELECT * FROM `listings` $where_clause";
$result = mysql_query($q, $dbh);
$listingdata = array();
while($row = mysql_fetch_array($result))
$listingdata[] = $row;
return $listingdata;
}
Improvements over your function:
Adds MySQL link $dbh in function arguments. Passit, otherwise query will not work.
Use while loop instead of foreach. Read more here.
Initialize listingdata array so that when there is no rows returned, you still get an empty array instead of nothing.
Do you have a valid db connection? You'll need to create the connection (apparently named $dbh) within the function, pass it in as an argument, or load it into the function's scope as a global in order for $result = mysql_query($q,$dbh); to work.
You need to use while, not foreach, with mysql_fetch_array, or else only the first row will be fetched and you'll be iterating over the columns in that row.
$q = "SELECT * FROM `listings` $where_clause";
$result = mysql_query($q,$dbh);
while (($row = mysql_fetch_array($result)) != false)
{
$listingdata[] = $row;
}
Always add error handling in your code. That way you'll see what is going wrong.
$result = mysql_query($q,$dbh);
if (!$result) {
trigger_error('Invalid query: ' . mysql_error()." in ".$q);
}
Here is a function which will save you some time. First Argument tablename, then condition(where), fields and the order. A simple query will look like this : query_db('tablename');
function query_db($tbl_name,$condition = "`ID` > 0",$fields = "*",$order="`ID` DESC"){
$query="SELECT ".$fields." FROM `".$tbl_name."` WHERE ".$condition." ORDER BY".$order;
$query=$con->query($query);
$row_data=array();
while($rows = $query->fetch_array()){
$row_data[] = $rows;
}
return $row_data;
}

Categories