Codeigniter function array always returns no - php

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 :)

Related

Better solution to this query

$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
}

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.

Codeigniter/PHP: How to merge distinct arrays and make it unique into one array in query result

- ingredient
- menu
recipe
How will I merge the two array under name into one array and make it unique. As you can see the result on the [0] is
Beef Adobo
qwerty
iswi
and on 1 is
qwerty
iswi
I want the both of them to be in one array and the result should be
Beef Adobo
qwerty
iswi
query:
public function get_halal($name) {
$terms = explode(',', $name);
foreach ($terms as $name) {
$this->db->distinct();
$this->db->select('r_name');
$this->db->from('recipe');
$this->db->join('menu', 'menu.recipe_id = recipe.recipe_id');
$this->db->join('ingredient', 'ingredient.ingredient_id = menu.ingredient_id');
$this->db->where('menu.category_id = 2');
$this->db->like('ingredient.name', $name);
$query = $this->db->get()->result();
$data[] = $query;
}
return $data;
}
controller:
public function ajaxSearchHalal() {
postdata = file_get_contents("php://input");
if (isset($postdata)) {
$post = json_decode($postdata);
$name = $post->name;
if ($this->user_model->get_halal($name)) {
$user_id = $this->user_model->get_halal($name);
$data = array(
'name' => $user_id,
);
echo json_encode($data);
} else {
echo json_encode("false");
}
} else {
echo "Error!";
}
}
Ok, I see what you are doing now. Thanks for including your tables.
From what I see, you are trying to get all the recipe names, from the recipe table, that have the ingredients your are passing.
What you need to do to fix this issue is not worry about how to merge the arrays, but how you can redo your sql query in order to obtain the information you want in just one query. The way you have it now is not efficient as you are calling a query per every iteration.
What you need to do is use WHERE IN, and GROUP BY to get the info you need and group them by a column. Redo your model method like this:
public function get_halal($name) {
$terms = explode(',', $name);
$this->db->select("r.name");
$this->db->from('recipe r');
$this->db->join('menu m', 'm.recipe_id = r.recipe_id');
$this->db->join('ingredient i', 'i.ingredient_id = m.ingredient_id');
$this->db->where('m.category_id = 2');
$this->db->where_in('i.name', $terms);
$this->db->group_by('r.recipe_id');
$q = $this->db->get();
return $q->result();
}
This will give you one result set which you can then pass as JSON to your front-end without having to iterate or merge arrays.
Hope this helps.

Reorder array from mysql query

I have an array returned from MYSQL query with 2 LEFT JOINs.
Question is: "Is there another way for writing the code below?". I got the code but I want a more clear way of it just to understand what happens inthere.
CODE:
$result = array();
while ($resultArr = mysqli_fetch_assoc($booksAndAuthors)) {
$result[$resultArr['book_id']] ['book_name'] = $resultArr['book_title'];
$result[$resultArr['book_id']] ['author'][] = $resultArr['author_name'];
print_r($result);
}
With the extract() function you can make the data in the result into variables. I have put the example below inside a function, so they will be local variables.
function getBooksAndAuthors($queryResult)
{
while ($data = mysqli_fetch_assoc($queryResult))
{
extract($data);
$BooksAndAuthors[$book_id] = array('book_name' => $book_title,
'author' => $author_name);
}
return $BooksAndAuthors;
}
This makes the code a lot more readable. You will, of course, have to know which columns there are in your database table. I also left out the extra '[]' for the author.
Here's how I recommend writing it, because I don't think you should depend on automatic creation of intermediate arrays.
$result = array();
while ($row = mysqli_fetch_assoc($booksAndAuthors) {
$bookid = $row['book_id'];
if (!isset($result[$bookid])) {
# First time we see this book, create a result for it
$result[$bookid] = array('book_name' => $row['book_title'],
'author' => array());
}
# add this author to the result entry for the book
$result[$bookid]['author'][] = $row['author_name'];
}
It's essentially equivalent, but I think it also makes the logic clearer.

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.

Categories