Laravel trying to get property of non-object in an object - php

Simple code will not work! I keep getting the error Trying to get property of non-object on the line with the if statement. I tried accessing this like an array I get a message saying it can't access a stdClass as an Array.
public function isAllowed($perm)
{
$cando = 0;
$groups = DB::table('group_user')->where('user_id', $this->id)->get();
foreach ($groups as $mygroup)
{
$group_can = DB::table('group_permission')->where([
['permission_id', $permission->id],
['group_id', $mygroup->group_id]
])->first();
$setting = $group_can->setting; // Error returns for this line //
if ($setting > $cando)
{
$cando = $setting;
}
}
}
print_r, var_dump, and dd of $group_can give this:
stdClass Object
(
[group_id] => 1
[permission_id] => 50
[setting] => 1
)
object(stdClass)#555 (3) { ["group_id"]=> int(1) ["permission_id"]=> int(50) ["setting"]=> int(1) }
{#555 ▼
+"group_id": 1
+"permission_id": 50
+"setting": 1
}
Using $setting = $group_can->setting; returns the error Trying to get property of non-object
Using $setting = $group_can['setting']; returns the error Cannot use object of type stdClass as array
The details of the laravel error are:
at HandleExceptions->handleError(8, 'Trying to get property of non-object', '/home/mwsubmissions/public_html/jon/MWSubmissionManager/app/User.php', 91, array('perm' => 'manage.projects', 'cando' => 1, 'groups' => object(Collection), 'permission' => object(stdClass), 'mygroup' => object(stdClass), 'group' => null, 'group_can' => null, 'setting' => 1))
EDIT
I removed the first part of the code that I was having errors with and then got to this, another example of the same thing, but using a smaller object and this line is more important than the last was. All details updated.

Better you can check isset
public function isAllowed($perm)
{
$cando = 0;
$groups = DB::table('group_user')->where('user_id', $this->id)->get();
if(isset($groups)&&count($groups)>0){
foreach ($groups as $mygroup)
{
if(isset($mygroup->group_id)){
$group = Group::find($mygroup->group_id);
}
if (!is_null($group->project_id))
{
continue;
}
}
}
}

The property you're trying to access is an element of an array 'attributes', so try:
public function isAllowed($perm)
{
$cando = 0;
$groups = DB::table('group_user')->where('user_id', $this->id)->get();
foreach ($groups as $mygroup)
{
$group = Group::find($mygroup->group_id);
if (!is_null($group->attributes['project_id']))
{
continue;
}
}
}
Hope this helps :)

First, ensure you add "project_id" to $fillable array in Group Model
Try this
public function isAllowed($perm)
{
$cando = 0;
$groups = DB::table('group_user')->where('user_id', $this->id)->get();
foreach ($groups as $mygroup)
{
$group = Group::whereId($mygroup->group_id)->first();
if (!is_null($group->attributes['project_id']))
{
continue;
}
}
}

Related

Can't access $this on PHP Closure passed to an object method

I'm trying to pass a closure that uses object data without having to assign the object to a variable and passing it as a parameter to the closure, but I can't seem to figure out the right way to do it.
Here is my arbitrary class code:
class Person
{
var $__data = [];
function setData($key, $value)
{
$this->__data[$key] = $value;
return $this;
}
function setAutoData($map)
{
$this->__data = array_merge($this->__data, $map());
return $this;
}
function getData($key)
{
return $this->__data[$key];
}
}
This piece of code here will work and add the first_name to the data array:
$p = (new Person())->setData('full_name', 'Valerie Maddison Bricks');
print_r($p->setAutoData(function () use($p) {
return [
'first_name' => array_shift(explode(' ', $p->getData('full_name')))
];
}));
/*
Output:
Person Object
(
[__data] => Array
(
[full_name] => Valerie Maddison Bricks
[first_name] => Valerie
)
)
*/
This one doesn't work.
print_r((new Person())
->setData('full_name', 'Valerie Maddison Bricks')
->setAutoData(function () {
return [
'first_name' => array_shift(explode(' ', $this->getData('full_name'))),
];
}));
/*
Output:
Fatal error: Uncaught Error: Using $this when not in object context in C:\Damian\xampp\web\dbo-dev\teste.php:44
Stack trace:
#0 C:\Damian\xampp\web\dbo-dev\teste.php(22): {closure}()
#1 C:\Damian\xampp\web\dbo-dev\teste.php(46): Person->setAutoData(Object(Closure))
#2 {main}
thrown in C:\Damian\xampp\web\dbo-dev\teste.php on line 44
*/
Is there a way to achieve that in a similar way without relying on a variable?
To avoid the use of $p, you can pass $this in the call of the closure. But you can't use $this in an anonymous function.
$this->__data = array_merge($this->__data, $map($this));
Then,
->setAutoData(function ($object) {
$array = explode(' ', $object->getData('full_name'));
return [
'first_name' => array_shift($array),
];
})
Note that array_shift requires a reference. You should create a variable for that.
Code:
class Person
{
private $__data = [];
public function setData($key, $value)
{
$this->__data[$key] = $value;
return $this;
}
public function setAutoData($map)
{
$this->__data = array_merge($this->__data, $map($this));
return $this;
}
public function getData($key)
{
return $this->__data[$key];
}
}
print_r(
(new Person())
->setData('full_name', 'Valerie Maddison Bricks')
->setAutoData(function ($object) {
$array = explode(' ', $object->getData('full_name'));
return [
'first_name' => array_shift($array),
];
})
);
Output:
Person Object
(
[__data:Person:private] => Array
(
[full_name] => Valerie Maddison Bricks
[first_name] => Valerie
)
)

Recursive function return issue

I'm writing a recursive function like below:
private function getManager($employee)
{
$manager = $employee->manager;
if ($manager) {
array_push($this->managers, $manager->id);
$this->getManager($manager);
}
return;
}
This function receive an employee and find his manage. If find a manage, then push manager id into an array ($this->managers on line 5). Then call this function recursively and pass manager as an employee. If no manager found on line 3, then this function just return (line 8).
So my question is, is their any problem if i'm not return the recursive call at line 6 ($this->getManager($manager);)
Not sure if this is what you think, but it works.
function getManagers($employee)
{
$managers = [];
if (isset($employee->manager)) {
array_push($managers, $employee->manager->id);
array_push($managers, ...getManagers($employee->manager));
}
return $managers;
}
No, there is absolutely no benefit in writing the empty return. The method will halt regardless of the existence of the return.
Please observe the two methods below which show identical, error-less outcomes regardless of the return.
Code: (Demo)
class Management
{
private $managers = [];
function __construct($managerTree)
{
$this->getManager($managerTree);
var_export($this->managers);
echo "\n---\n";
$this->managers = [];
var_export($this->managers);
echo "\n---\n";
$this->getManager2($managerTree);
var_export($this->managers);
}
private function getManager(?object $employee): void
{
$manager = $employee->manager;
if ($manager) {
array_push($this->managers, $manager->id);
$this->getManager($manager);
}
return;
}
private function getManager2(?object $employee): void
{
$manager = $employee->manager;
if ($manager) {
array_push($this->managers, $manager->id);
$this->getManager($manager);
}
}
}
new Management(
(object) [
'id' => 3,
'manager' => (object) [
'id' => 2,
'manager' => (object) [
'id' => 1,
'manager' => null
]
]
]
);
Output:
array (
0 => 2,
1 => 1,
)
---
array (
)
---
array (
0 => 2,
1 => 1,
)

CodeIgniter multidimensional array store in mysql database single column

I am trying to store this data in database but i am getting error. how to fix this?
I want simply store multidimensional array in a single column.
$data = array(
'2017' => array(
'6' => array(
'10' => array(
'count' => 76
),
),
),
);
$getdata = $this->view_count->setView($data);
Model
public function setView($data)
{
$setData = $this->db->where('short', 'honwl')->update('ci_links', $data['view_count']);
return $setData;
}
Error which i am getting
A PHP Error was encountered
Severity: Notice
Message: Undefined index: view_count
Filename: models/View_count.php
Line Number: 14
Backtrace:
File: C:\wamp\www\blog\application\models\View_count.php
Line: 14
Function: _error_handler
File: C:\wamp\www\blog\application\controllers\Dashbord.php
Line: 52
Function: setView
File: C:\wamp\www\blog\index.php
Line: 315
Function: require_once
A Database Error Occurred
You must use the "set" method to update an entry.
Filename: C:/wamp/www/blog/system/database/DB_query_builder.php
Line Number: 1864
As message says, you don't have key $data['view_count'] but you have $data[2017][6][10]['count'] value. I asume those dates are changed dynamically so you need to get value of inner array by key count.
If your array always has similar keys i.e. $data[year][month][day][count], you can use code (bit modified) from this answer to get that key value. Put in your model
private function getCount($arr, $search)
{
$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($arr));
foreach($iterator as $key => $value) {
if($search == $key && $value !== '') {
return $value;
}
}
return false;
}
Then in your first method use value filtered through this function:
public function setView($data)
{
$count = $this->getCount($data, 'count');
if ($count !== false) {
$setData = $this->db->where('short', 'honwl')->update('ci_links', $count);
return $setData;
}
return false;
}
According to you example code, you can encode array data to JSON for saving to column, then get back by decode:
Controller:
$data = array(
'2017' => array(
'6' => array(
'10' => array(
'count' => 76
),
),
),
);
$getdata = $this->view_count->setView($data);
$data = $this->view_count->getView();
Model:
public function setView($data)
{
$data = json_encode($data);
$setData = $this->db->where('short', 'honwl')->update('ci_links', array('column_name'=>$data));
return $setData;
}
public function getView($data)
{
$row = $this->db->where('short', 'honwl')->get('ci_links')->row();
return json_decode($row->column_name, true);
}
The column_name depends on your table's column name that save the array data.

add properties to php pbject

I have this object that represents colors with counts
I am trying to add property of color code to the object from another array
printing object $oColors :
stdClass Object
(
[black] => 2207
[blue] => 783
[red] => 672
[white] => 555
[green] => 463
)
and am trying to loop through them and map them with another array of objects like below :
foreach ($oColors as $color => $count) {
if (array_key_exists($color, $oColorsMapper)) {
$oColors->$color['code']= $oColorsMapper->$color->code;
}
}
but printing the result is showing the object is still the same
what am I doing wrong thanks
The problem is that the keys are not arrays. They are strings. So the solution would be something like:
foreach ($oColors as $color => $count) {
if (array_key_exists($color, $oColorsMapper)) {
$oColors->$color = array(
'count' => $count,
'code' => $oColorsMapper->$color->code
);
}
}
As a simple example:
$arr = (object) array('test' => 43, 'test1' => 435);
function test($obj) {
foreach ($obj as $key => $val) {
$obj->$key = array($val);
}
}
test($arr);
var_dump($arr);
will output:
object(stdClass)#1 (2) {
["test"]=>
array(1) {
[0]=>
int(43)
}
["test1"]=>
array(1) {
[0]=>
int(435)
}
}
#sisimh
Your problem is passing variable into function without reference.
By default, function arguments are passed by value (so that if the value of the argument within the function is changed, it does not get changed outside of the function). To allow a function to modify its arguments, they must be passed by reference. More info u can get here
So, if you have function:
function changeColors ($oColors) {
...
}
You should change $oColors to &$oColors, like this:
function changeColors (&$oColors) {
Next point is that $color from your example with foreach section is not an array. It'a a key value (in most cases it has a string type). Perhabs, you made mistake and ['code'] should be absent.
Another point of my attention is array_key_exists. In most cases better to use isset instead of array_key_exists. It's a more faster way.
For example:
function changeColors (&$oColors) {
...
foreach ($oColors as $color => $count) {
if (isset($oColorsMapper->$color)) {
$oColors->$color = $oColorsMapper->$color->code;
}
}
...
}

How to access data in nested Std Object array in PHP

I need to access the data: 'hotelID', 'name', 'address1','city' etc. I have the following Std Object array ($the_obj) in PHP that contains the following data:
object(stdClass)[1]
public 'HotelListResponse' =>
object(stdClass)[2]
public 'customerSessionId' => string '0ABAAA87-6BDD-6F91-4292-7F90AF49146E' (length=36)
public 'numberOfRoomsRequested' => int 0
public 'moreResultsAvailable' => boolean false
public 'HotelList' =>
object(stdClass)[3]
public '#size' => string '227' (length=3)
public '#activePropertyCount' => string '227' (length=3)
public 'HotelSummary' =>
array (size=227)
0 =>
object(stdClass)[4]
public 'hotelId' => 112304
public 'name' => La Quinta Inn and Suites Seattle Downtown
public 'address1' => 2224 8th Ave
public 'city' => Seattle
public 'stateProvinceCode' => WA
public 'postalCode' => 98121
public 'countryCode' => US
public 'airportCode' => SEA
public 'propertyCategory' => 1
public 'hotelRating' => 2.5
I have tried the following for lets say to access the 'name':
echo $the_obj->HotelListResponse->HotelList->HotelSummary[0]->name;
Also I have tried to print each key and value pairs by using foreach loop but I keep on getting errors. Here is what I tried:
foreach ($the_obj->HotelListResponse->HotelList->HotelSummary[0] as $key => $value){
echo $key.' : '.$value.'<br />';
}
Here are the errors that I get:
Trying to get property of non-object
Warning: Invalid argument supplied for foreach()
Thank you everyone for answering, I have figured out the way to access the 'hotelID', 'name' and all other keys and value pairs in the deepest nest of the array.
I converted the Std Object array to an associative array, then I accessed each of the value by using the foreach loop:
foreach ($the_obj["HotelListResponse"]["HotelList"]["HotelSummary"] as $value){
echo $value["hotelId"];
echo $value["name"];
//and all other values can be accessed
}
To access both (Keys as well as values):
foreach ($the_obj["HotelListResponse"]["HotelList"]["HotelSummary"] as $key=>$value){
echo $key.'=>'.$value["hotelId"];
echo $key.'=>'.$value["name"];
//and all other keys as well as values can be accessed
}
Regarding to #Satya's answer I'd like to show simpler way for Object to array conversion, by using json functions:
$obj = ...
$tmp = json_encode($obj);
$objToArray = json_decode($tmp,true);
This way you can easily access array items. First you can dump structure...
try something like this :
$p=objectToArray($result);
recurse($p);
}
function objectToArray( $object )
{
if( !is_object( $object ) && !is_array( $object ) )
{
return $object;
}
if( is_object( $object ) )
{
$object = get_object_vars( $object );
}
return array_map( 'objectToArray', $object );
}
function recurse ($array)
{
//statements
foreach ($array as $key => $value)
{
# code...
if( is_array( $value ) )
{
recurse( $value );
}
else
{ $v=$value;
$v=str_replace("’",'\'',strip_tags($v));
$v=str_replace("–",'-',$v);
$v=str_replace("‘",'\'',strip_tags($v));
$v=str_replace("“",'"',strip_tags($v));
$v=str_replace("”",'"',strip_tags($v));
$v=str_replace("–",'-',strip_tags($v));
$v=str_replace("’",'\'',strip_tags($v));
$v=str_replace("'",'\'',strip_tags($v));
$v=str_replace(" ",'',strip_tags($v));
$v=html_entity_decode($v);
$v=str_replace("&",' and ',$v);
$v = preg_replace('/\s+/', ' ', $v);
if($key=="image")
{
if(strlen($v)==0)
{
echo '<'.$key .'>NA</'.$key.'>';
}
else
{
echo '<'.$key .'>'. trim($v) .'</'.$key.'>';
}
}
}
}
}

Categories