Php says object is non-object - php

I'm sorry, this is yet another Trying to get a property of a non-object-question...
Here's some code and I just can't seem to figure out how this works (or not works rather):
$b = Model_Artist::query()->where('id', 18)->get_one(); // Fuelphp ORM query, returns \Orm\Model object
var_dump($b); // output: object(Model_Artist)[46] ... etc.
// definitely an object
var_dump($b->id); // [Error: Trying to get property of non-object] output: '18'
// umm ok, so maybe no object?
var_dump(is_object($b)); // output: bool(true)
// no, no, it is an object!
var_dump($b->id); // [Error: Trying to get property of non-object] output: '18'
// make up your mind, it's no object after all?
if ( is_object($b) ) {
var_dump($b->id); // output: '18' [No error!!]
}
// WAT?? It is only an object inside the if statement?
So the question is: why does PHP say that I try to get a property of a non-object in the first two cases, while is_object is true. And why does that suddenly change inside the if statement?
Either PHP is funny, or I'm doing something really really wrong?

$b is an array of objects. and so $b->id is not valid but reset($b)->id is.

Related

php: call a method of an object coming from an array

I'm trying to figure out a way to call a method of a specified member (Class A) coming from an array of members in class B.
<?php
class A
{
public function do_something()
{
echo "class A did something";
}
}
class B
{
private $arr = array();
private $current_index = 0;
public function add_new_A()
{
$new_a = new A;
array_push($this->arr, (object) [
$this->current_index => $new_a
]);
$this->current_index++;
}
public function get_an_A_by_index($index)
{
return $this->arr{$index};
}
public function do_something_with_A_member_inside_array($index)
{
self::get_an_A_by_index($index)->do_someting();
}
}
$b = new B;
$b->add_new_a();
$b->add_new_a();
echo print_r($b->get_an_A_by_index(0));
echo "\n";
$b->do_something_with_A_member_inside_array(0); // returns error
// console:
// stdClass Object ( [0] => A Object ( ))
// Uncaught Error: Call to undefined method stdClass::do_something();
?>
To wrap things up, I want to know if my approach is considered bad and/or if there is something I can do to fix the error. Before you disagree with my code, take a look at my php code I'm actually working on. That's all for my question.
Now about why I want to call a method of a member A inside . For my assignment I want a program that does something seperately with the method do_something of class a. So far, the only way to do that is by storing seperate members of A.
I'm not sure if I'm approaching this wrong or not, because I'm coming from Java. So, The first thing I came up with was the approach shown above. When I do this in Java, it works fine. But php is different from Java and I'm still learning how php works since I'm new to it.
Your code isn't far off, you've just got an issue with the way you're building up the collection of A objects.
array_push($this->arr, (object) [
$this->current_index => $new_a
]);
This is creating a data structure that I'm pretty sure isn't what you expect. You'll end up with an array full of stdClass objects, each with a single A member and its own internal index:
Array
(
[0] => stdClass Object
(
[0] => A Object
(
)
)
)
You're then retrieving the stdClass object and trying to run the method on that, hence the Call to undefined method stdClass::do_something... error you're seeing.
Instead, all you need to do is this:
$this->arr[$this->current_index] = $new_a;
The rest of your code is just expecting an array of A objects, nothing nested any deeper.
I've put a full example here: https://3v4l.org/ijvQa. Your existing code had a couple of other typos, which are also fixed. You'll spot them easily enough if you turn on error reporting.

Laravel: view->with passing an object

$somedata = Indicator::all();
$indicators = [];
// ... (re-structure the data; rows to columns)
$indicators[] = ['a'=>'2016', 'b'=>'2017', 'c'=>'2018'];
$indicators[] = ['a'=>'1232', 'b'=>'3242', 'c'=>'5467'];
$indicators[] = ['a'=>'1232', 'b'=>'3242', 'c'=>'5467'];
$indicators[] = ['a'=>'closed', 'b'=>'closed', 'c'=>'open'];>
// ??? How to form a valid object to send ???
return view('indicators.index')->with(['indicators'=> $indicators]);
I select data. I change the structure for displaying it; but cannot find the correct structure to then pass in my response.
The view throws the error "Trying to get property of non-object (View: "
(I looked at the dump of Indicator::all(); and wonder if I have the right/wrong approach)
// noob
You're returning an array, I image you are probably trying to access an index using object notation like:
$val->prop
when it should be:
$val['prop']
Indicator::all() returns a collection of objects which you're not using in your view.
As an aside, Laravel collections have some handy helper functions to work with result sets. You may be interested in:
https://laravel.com/docs/5.5/collections#method-map
As $indicators is an array so you have to use [''] instead of -> to access its data.

Zend-Framework related

I got two zend forms which belongs to one table in the database, broke it up in order to make sure the user does not find it lazy to finish it but I have a problem with my code in my model. I keep getting this error even though I tried numerous solutions.
Fatal error: Call to a member function save() on a non-object
public function smmedetailssmmedetails($companyname, $companytradingname)
{
$data = array(
'companyname' => $companyname,
'companytradingname' => $companytradingname,
);
return $this->insert($data);
}
public function smmesdetails2smmedetails($smmeid, $numberemployees, $ownership)
{
$row = $this->find($smmeid)->current();
$row->numberemployees = $numberemployees;
$row->ownership = $ownership;
return $row->save(); //problem lies on this line
}
Tried using the following codes/methods
$this ->row->save();
$row->save();
$this ->row->save();
return $this -> row->save();
According to the error you're getting, none of the method invocations you are trying will work.
You should first check what
$this->find($smmeid)->current();
returns using either a debugger, var_dump or print_r.
In your case, it seems that either null or something that is not an object is returned.
This means, that $row is not an object (should be), but probably is null. This means that find() method didn't get any result from database.
You should check $smmeid value and check if a such a row exists in the database.
Use var_dump function to check any variable in any line. This is how you can debug your problem.
Hey guys I got it using this method below, I marked codeblur answer because it was close thanks for the print_r information:
Example #1 print_r() example
<pre>
<?php
$a = array ('a' => 'apple', 'b' => 'banana', 'c' => array ('x', 'y', 'z'));
print_r ($a);
?>
</pre>
return ($row);//correct answer

Unexpected result when comparing PHP objects

When I compared two different objects, it returns firstly true, and than after print_r (on objects) returned false.
From PHP manual:
Two object instances are equal if they have the same attributes and values, and are instances of the same class.
But here, in example, I set different values. Why the result is different between PHP 5.4.0 - 5.5.7?
abstract class first
{
protected $someArray = array();
}
class second extends first
{
protected $someArray = array();
protected $someValue = null;
public function __construct($someValue)
{
$this->someValue = $someValue;
}
}
$objFirst = new second('123');
$objSecond = new second('321');
var_dump ($objFirst == $objSecond);
print_r($objFirst);
var_dump ($objFirst == $objSecond);
Result is:
bool(true)
second Object ( [someArray:protected] =>
Array ( ) [someValue:protected] => 123 )
bool(false)
But what I expected was:
bool(false)
second Object ( [someArray:protected] =>
Array ( ) [someValue:protected] => 123 )
bool(false)
This was a bug in PHP. It's fixed now, see the commit. In short:
If you extend a class and redefine the same property the properties_table of the object ends up having a NULL value.
The comparison code incorrectly aborted comparison when two objects had a NULL value in the properties_table at the same index - reporting the objects as equal. That doesn't make sense of course, because it discards all differences in the following properties. This is fixed now.
The reason why print_r changes the result, is that by fetching the properties of the object (get_properties) the properties hashtable is rebuilt (rebuild_properties_table) which uses entirely different (and correct) comparison code.
For context, properties_table and properties are two different ways PHP uses to represent properties - the former being way more efficient and used for declared properties and the latter used for dynamic properties. The print_r call effectively makes the object properties dynamic.
Well, ok, Identified as bug in php https://bugs.php.net/bug.php?id=66286.
Also here: Unexpected result when comparing PHP objects

PHP: What is this object type, and how do I add to it without causing warnings

I've encountered this here and there, and I always worked around it, but I've just gotta know.
Is this an array, an object, or ??? (Let's say I got this via var_export($co))
stdClass::__set_state(array(
'name' => 'Acme Anvil Corp.',
))
Most importantly, how can I add a value to it?
Let's say I want to add a value, like $co->owner = 'Wiley Coyote'. That always throws a warning.
How?
What?
The curiosity is just KILLING me :)
[EDIT]
As a clarification, I guess the root of my question would be "How do I add variables to the object without triggering Warnings?"
Here's the warning I always get:
A PHP Error was encountered
Severity: Warning
Message: Attempt to assign property of non-object
And a var_dump($co) yields: (currently done in a loop, if it's pertinent)
object(stdClass)#185 (1) {
["name"]=>
string(16) "Acme Anvil Corp."
}
[/EDIT]
$co is object of type stdClass. You can create one and add as many properties as you want without any warning:
$obj = new stdClass();
$obj->prop1 = 'val1';
$obj->prop2 = 3.14;
The warning you are facing is most probably Creating default object from null value, meaning that you are trying to assign property to uninitialized variable.
You should not try running the code produced by var_export for stdClass objects, since they don't have method __setState.
Not too sure about your error - but the stdClass class is a default in built class to PHP.
It's basically an empty object
You should be able to set properties with $class->foo = 'bar'
If you're not talking about stdClass - but the fact you're getting an array in var_export - it's simply a representation of the internal object state .
class Foo
{
private $bar = 'baz';
}
$foo = new Foo();
var_export($foo);
Should give output similar to
Foo::__set_state(array(
'bar' => 'baz',
))
The warning you get may be due to the property being protected/private.
var_dump() generally tells you about the access modifiers on internal objects better than var_export()
Can you clarify what the warning you get is and what the question is regarding, and I'll edit up my answer to make it relevant to what you're asking
var_export() prints executable PHP code able to recreate the variable exported.
When encountering objects, they are always exported as a call to their static magic method __set_state(). Compared to other magic methods, this method does not really have much magic in it besides the fact that var_export guarantees to create static calls with this method, so it is simply just the agreed upon name for such a method.
The __set_state() method of a class should return an instance of the object with all exported properties set to the values given as the array parameter.
Example:
class Foo {
public $bar;
public static function __set_state($params) {
$obj = new Foo;
foreach ($params as $key => $value) {
$obj->$key = $value;
}
return $obj;
}
}
$foo = new Foo;
$foo->bar = "Hello World";
var_export($foo);
This prints something like:
Foo::__set_state(array('bar' => 'Hello World'));
If you execute this and save it to a variable again:
$x = Foo::__set_state(array('bar' => 'Hello World'));
it will recreate the object with all given properties set.
It does not work with stdClass objects, because they don't have a __set_state() method.
See http://de3.php.net/manual/en/language.oop5.magic.php#object.set-state for more info.
Update:
This code does not trigger any warnings:
ini_set('display_errors', 1);
error_reporting(E_ALL | E_STRICT);
$co = new stdClass();
$co->name = 'Acme Anvil Corp.';
var_export($co);
$co->owner = 'Wiley Coyote';

Categories