Access object properties outside foreach loop - php

I have a some data coming from the db via a model
public static function loadPermissions($user_role)
{
$db = \Config\Database::connect();
$builder = $db->table('role_has_perm');
$builder->select('*');
$builder->join('perms', 'perms.id_perm = role_has_perm.id_perm', 'left');
$builder->join('roles', 'roles.id_role = role_has_perm.id_role');
$builder->where('role_has_perm.id_role', $user_role);
$query = $builder->get();
return $query->getResultObject();
}
Now if I loop trough it with a foreach loop I can spit out the data.
foreach ($query as $row) {
echo "id_role = " . $row->id_role . " " . "id_perm = " . $row->id_perm . " " . "role_name = " . $row->role_name;
$role = $row->role_name;
}
However I don't always want to loop through the whole object. I want to access specific properties.
I want to access only the role_name for example.
$role = $query->role_name;
I get this error: Trying to get property 'role_name' of non-object
Am I handling the object wrong ?
Any input is welcomed :)
Alex

Apparently, the $query variable contains an array. So you just need to access an element of the array by index. The following snippet would give you the first element of the array.
$role = $query[0]->role_name;
As an alternative you can fetch a specific single raw.

Related

Search within array or compare values

To improve my php experiences I have written a small movie databse with the TMDB API.
Now I have data from the API and data from own codings. I have a database movieSeen where people can save movies they have already seen.
global $pdo;
$stmt = $pdo->prepare("SELECT * FROM movieSeen WHERE user_id = '" . $_SESSION['id'] . "'");
$stmt->execute();
foreach ($stmt as $row ) {
echo $row['movie_id'] . ', ';
} // outputs the IDs of the movies already seen. here: 157, 189, 298, 456
Now I have a API Call where I load all movies from a specific director.
$url = "https://api.themoviedb.org/3/person/" . $personID . "/movie_credits?api_key=" . $apiKey . "&" . $language . "";// path to your JSON file
$data = file_get_contents($url); // put the contents of the file into a variable
$personCareer = json_decode($data); // decode the JSON feed
foreach ($personCareer->crew as $showCrewDetails) { //output of the movies of a specific director
echo '<tr>';
echo '<td>' . $showCrewDetails->title . ' ' . $showCrewDetails->id . ' (' . substr($showCrewDetails->release_date, 0, 4) . ')</td>';
echo '<td><span class="badge badge-danger">Movie Seen</span></td>';
echo '<td>' . $showCrewDetails->job . '</td>';
echo '</tr>';
}
Every movie which has alredy be seen should be checked as seen in this list. So I have to check if the IDs from my database are included in the API call.
I think I have to use something like in_array or array_search to see if $showCrewDetails->id is equal to $row['movie_id'].
But I don't know how to exactly do it. I am thankful for every hint.
I would do something like this:
/**
* #param int $user_id DB user ID
* #param PDO $pdo
* #return int[] User movie IDs
*/
function getUserSeenMovieIds(int $user_id, PDO $pdo) : array {
$stmt = $pdo->prepare('SELECT movie_id FROM movieSeen WHERE user_id = :user_id');
$stmt->execute([':user_id' => $user_id]);
return $stmt->fetchAll(PDO::FETCH_COLUMN, 0) ?: [];
}
/**
* #return array Response from api.themoviedb.org/3/person/{int}/movie_credits
*/
function getMovieCredits(int $personID, string $apiKey, string $language) : array {
$query = http_build_query([
'api_key' => $apiKey,
'language' => $language,
]);
$url = 'https://api.themoviedb.org/3/person/' . $personID . '/movie_credits?' . $query;
$data = file_get_contents($url);
$credits = json_decode($data, true);
if (!is_array($credits)) {
throw new \RuntimeException("Failed decoding response $data from URL $url");
}
return $credits;
}
/**
* #param array $credits Response from api.themoviedb.org/3/person/{int}/movie_credits
* #param int[] $movie_ids
* #return array Crew details from the response filtered by the movie IDs
*/
function getMovieCrewDetails(array $credits, array $movie_ids) : array
{
$reference = array_flip($movie_ids);
$credits = [];
foreach ($credits['crew'] as $crew) {
$id = $crew['id'];
if (isset($reference[$id])) {
$credits[] = $crew;
}
}
return $credits;
}
////////////////////////////////////////////////////////////////////////////////
$movie_ids = getUserSeenMovieIds($user_id, $pdo);
$credits = getMovieCredits($personID, $apiKey, $language);
foreach (getMovieCrewDetails($credits, $movie_ids) as $crew) {
// TODO: Print $crew
}
The code above avoids nested loop (which would result in O(n*m) complexity) in getMovieCrewDetails by using a hash table $reference. Hash tables are O(1) average case complexity, so using them for moderate data sets is generally a good idea.
There is a number of other things to note:
do use PDO placeholders, since they free you from the need to escape the input;
do not use global, since you can easily avoid pollution of the global name space by using functions, classes and techniques like dependency injection;
always check for the values functions return; otherwise, you are risking to catch an unexpected runtime error or bug (I've put some error checking into the code, but you should really check every function call.)
if you have $showCrewDetails->id is multiple value.
use foreach
foreach ($showCrewDetails as $key => $val) {
$id_fromapi = $val->id;
$stmt = $pdo->prepare("SELECT *FROM movieSeen WHERE user_id ='".$id_fromapi ."'");
$stmt->execute();
}

how can get an object instead of array like FETCH_OBJECT instead of FETCH_ASSOC

I have a class names Product.php in my model directory. in my view directory, I have an index.php currently I fetching data out of my table using this function
the code works fine but I want to field $row['name'] to be called as an object. because I am not sure the way I'm doing is a semantically correct for oop programming.
public function display(){
$pizza = $this->connect()->query("SELECT * FROM pizza");
while ($row = $pizza->fetch(PDO::FETCH_ASSOC)) {
$data[]= $row;
} return $data;
}//end of method
and in my index page i write :
$blog = new Product();
$name = $blog->display();
foreach ($name as $row ) {
echo $row['name']. '<br>';
}
All you need to do is change PDO::FETCH_ASSOC to PDO::FETCH_OBJ.
Then for your index.php:
$blog = new Product();
$name = $blog->display();
foreach ($name as $row ) {
echo $row->name . '<br>';
}
Here is a really good article to read for PDO.
PDO Tutotrial

Codeigniter multi-dimensional array return only the first row

One day I'm on this problem and I cant find the solution.
My goal is to return a list of links from an ID (the father). So I want all his childs.
But in the view, I only have on result (the 1st one...).
I have in my controller :
$data['list_link'] = $this->menuManager->list_link();
In my Model :
function list_link($fatherid=0){
$r = array();
$sSQL = 'SELECT * FROM categories WHERE fatherid = ' . $fatherid . ' AND siteid = ' . MY_SITEID_DEFAULT . ' ORDER BY name';
$query = $this->db->query($sSQL);
// stock results in array
$r[] = $query->result_array();
foreach ($query->result() as $row) {
// let's find the childs
$this->list_link($row->id,$loop);
}
return $r;
}
If I "for each" the $r here, all looks good.
So, $data['list_link'] shoud now have all the rows.
In my view :
foreach ($list_link as $link){
foreach ($link as $row){
echo $row['name'];
}
}
But, I only have the first links (first childs), not the other one. Any help would be greatly appreciated as I'm on that problem for days...
You're not storing any values in the recursive calls (though I'm still not sure you'd get what you expect). You'd need to populate $r with each function call:
$r[] = $this->list_link($row->id,$loop);
However, either I missed something or you're overcomplicating things, but I think you could simply return the result array and use it:
function list_link($fatherid=0,$loop=0){
$sSQL = 'SELECT * FROM categories WHERE fatherid = ' . $fatherid . ' AND siteid = ' . MY_SITEID_DEFAULT . ' ORDER BY name';
$query = $this->db->query($sSQL);
return $query->result_array();
}
UPDATE
Your latest version still doesn't collect the data from recursive calls, here is the full function, see if it works:
function list_link($fatherid=0){
$r = array();
$sSQL = 'SELECT * FROM categories WHERE fatherid = ' . $fatherid . ' AND siteid = ' . MY_SITEID_DEFAULT . ' ORDER BY name';
$query = $this->db->query($sSQL);
$result = $query->result_array();
// stock results in array
$r[$fatherid] = $result;
foreach ($result as $row) {
// let's find the children
$r[$fatherid][$row['id']] = $this->list_link($row['id']);
}
return $r;
}
Note that I've added $r[$fatherid][$row['id']] so the end result should be an array with a branching structure. If you don't want that, just do $r[] instead.

How to through multidimensional array in Codeigniter?

I'm trying to get my head around grabbing all variable I need in Codeigniter and then passing those values to the view.
I understand the concept, but am getting stuck on iterating through an array and adding on another array to each of its keys.
The $data['items'] array contains data passed from a model via the get_all() function. The query is basically "Select * from items".
Each item has multiple features and pictures. In order to get the appropriate values I need the id of an item. I can grab this from the first array ($data['items']) which I can then pass to a model function.
I keep getting various errors when trying to do this via the code below. I've tried defining the features and pictures arrays before the foreach loop - still get errors.
I'm sure my syntax is just wrong. Any help is welcome.
$data['items'] = $this->amazon->get_all();
foreach ($data['items'] as $data )
$id = $data->id;
$data['features'] = $this->amazon->get_features($id);
$data['pictures'] = $this->amazon->get_pictures($id);
}
Edit
Based on feedback I've updated the code to this (lines 24 - 30 of the code):
$items = $this->amazon->get_all();
for($i=0; $i<count($items);$i++) {
$data = $items[$i];
$id = $data->id;
$items[$i]['features'] = $this->amazon->get_features($id);
$items[$i]['pictures'] = $this->amazon->get_pictures($id);
}
PHP is complaining with this:
PHP Fatal error: Cannot use object of type stdClass as array in /var/www/ci/application/controllers/main.php on line 28
Here are the functions from the amazon model:
function get_all()
{
$query = $this->db->get('items');
return $query->result();
}
function get_pictures($id) {
$query = $this->db->query("SELECT link FROM pictures WHERE item_id='$id' AND type IN('thumb_set')");
$style = "border-style:solid; border-width:1px";
$class = "modal-thumb";
$results = '';
foreach ($query->result() as $row) {
$results .= "<li style='$style' class='$class'><img src='$row->link' alt=''/></li>";
}
return $results;
}
function get_features($id) {
$query = $this->db->query("SELECT content FROM features WHERE item_id='$id' ORDER BY feature_num DESC");
$results = '';
foreach ($query->result() as $row) {
$results .= "<li>";
$results .= $row->content;
$results .= "</li>";
}
return $results;
}
I'm thinking i need to use 'results_array()' instead of 'results()'? Are my results returned as an object instead of an array the way things are now?
As you said, you have syntax error in the foreach statement, you are redefining the $data array.
foreach ($data['items'] as $data )
Try this:
$items = $this->amazon->get_all();
for($i=0; $i<count($items);$i++){
$data = $items[$i];
$id = $data->id;
$items[$i]['features'] = $this->amazon->get_features($id);
$items[$i]['pictures'] = $this->amazon->get_pictures($id);
}

NotORM: How to fetch data?

I´m having trouble using selects, I tried reading the documentation but it's not too clear, and the forums that talk about it are few and inactive.
I want to do a simple select, so I tried:
$applications = $NOTORM->user_types()
->select('id, group_title')
->where('id', 1);
return $applications;
That however gives me back a NotORM object where I don't see the resulting rows that I get when I do a normal: SELECT id, group_title FROM user_types WHERE id = 1
I tried using the fetch() but not really sure how to use it. Any insights?
Actually, recommended by the author of NotORM is to use:
<?php
array_map('iterator_to_array', iterator_to_array($result));
?>
Good luck!
I had the same problem till I realized that you have to loop over result.
Try
foreach($applications as $application) {
echo $application["id"] . ": " . $application["group_title"]
}
Alternatively as you mentioned you can use fetch() which will fetch you one row at a time.
$row=$applications->fetch();
echo $row["id"];
EDIT:
To get all the row data as plain associative array instead of NotORM Object I have come across 2 techniques:
foreach($row as $key => $value) {
$data[$key]=$value;
}
$data=iterator_to_array($row); - I haven't fount a NotOrm function that does this but I found that Notorm uses this technique internally(somewhere).
To actually get only the data array of the row, you have to access NotORM_Row->row param, but it is 'protected' by default. So to use it like this:
$row = $NOTORM->user_types()
->select('id, group_title')
->where('id', 1)
->fetch()->row; //here is the magic :)
You first need to 'hack' core NotORM_Row class in 'NotORM/Row.php',
by replacing
protected $row, $result;
to
public $row, $result;
Note: You have to call fetch() on NotORM results, because it will return the NotORM_Row object where the row data is placed.
Just add this code somewhere inside the NotORM_Result class:
function result() { return (Object)$this->result_array(); }
function result_array() {
foreach($this as $row) { $ret[] = iterator_to_array($row); }
return $ret;
}
And use it like:
$applications = $NOTORM->user_types()
->select('id, group_title')
->where('id', 1);
return $applications->result(); //To return it as an Plain Object
//or
return $applications->result_array(); //To return it as a Assoc Array
Try to define this PHP function:
function getArray($obj){
$arr = array();
foreach ($obj as $objSingle) {
$arrRow = array();
foreach ($objSingle as $key => $value) {
$arrRow[$key] = $value;
}
$arr[] = $arrRow;
}
return $arr;
}
And use it by calling:
$arr = getArray($applications);
NotOrm added a function that return raw row data than names jsonSerialize. You can get row data array by this function.
Example:
$row=$db->MyTable->where('X','93054660084')->fetch();
var_dump($row->jsonSerialize());
Output:
array (size=5)
'X' => string '93054660084' (length=9)
'Idc' => string '1132' (length=4)
'IdH' => string '1' (length=1)
'Mab' => string '0' (length=1)
'Tar' => string 'xsderf' (length=10)
For multi record data you need to use foreach and apply it to all records.
It can be done like this.
function comboBuilder2($tbl, $name, $lable, $value, $value2, $value3, $selected = NULL, $cond, $sort = NULL){
global $db;
$html = '';
$sort1 = (!empty($sort)) ? "order by sort asc" : '';
$sql = "select * from " . $tbl . " " . $cond . " " . $sort1 . "";
//echo $sql;
$sth = $db->query($sql);
$rs = $sth->fetchAll();
//print_r($rs);
if ($rs[0] > 0) {
foreach ($rs as $row) {
if ($selected == $row[$value])
$sel = 'selected = "selected" ';
else
$sel = '';
echo $row[$lable];
//$html .= '<option value="' . $row[$value] . '" data-min="' . $row[$value2] . '" data-max="' . $row[$value3] . '" ' . $sel . '>' . $row[$lable] . '</option>';
}
$html .= '';
}
return $html;
}

Categories