Using undefined variable or array offset as argument in php - php

I have a static method that returns or creates an object if it doesn't exist. I'd like to find an elegant way to handle passing an ID argument to the object.
The logic here is that if an ID is passed, the object is created with that ID. If not, it's created with a default ID.
What I had was:
class App {
private $game_obj;
public static function get_game ($arguments) {
if (!isset($this->game_obj))
$this->game_obj = new Game ($arguments[0]);
return $this->game_obj;
}
}
class Game {
private $gameID;
public function __construct ($id=1) {
$this=>gameID = $id;
/* other code */
}
}
When I call App::get_game(5) I get the result I expect. A Game object with a gameID of 5.
When I call App::get_game() I do not get the result I expect, which would be a Game object with a gameID of 1. Instead I get an error about undefined offset in the App::get_game ().
I updated App::get_game() as follows, but it seems particularly inelegant. I'd prefer to define the default ID in the class definition.
class App {
private $game_obj;
public static function get_game ($arguments) {
if (!isset($this->game_obj)) {
$default_id = 1; // I don't like having this here
$id = isset ($arguments[0] ? $arguments[0] : $default_id;
$this->game_obj = new Game ($id);
}
return $this->game_obj;
}
}
Is there a simpler/better/more elegant way to handle this? Ideally one that would keep my default ID declaration in the Game class itself?

did you try
public static function get_game ($arguments=null) {
if($arguments==null) //etc..
?

you can test with :
if(is_object($my_object)) {
}

Related

PHP Chain with Parent Function

I'm wanting to chain a method with the parent function of itself.
Example:
class Query
{
protected $limit;
/**
* Returns some third object that isn't in this family.
* This object represents the results, and also has
* a first function that gets called in a chain.
*/
public function get()
{
// Do Stuff
return new /* ... */;
}
public function take($amount)
{
$this->limit = $amount;
return $this;
}
}
class ChildQuery extends Query
{
protected $singular = false;
public function get()
{
if($this->singular)
return $this->take(1)->parent::get()->first();
return parent::get()
}
public function singular()
{
$this->singular = true;
return $this;
}
}
This obviously isn't the full set of functions, nor does it work, but you get the idea. I'd like ChildQuery::get to be able to call Query::get in a chain.
Right now, I have to do this:
public function get()
{
$this->take(1);
parent::get()->first();
}
Which is not appealing to me. Any ideas?
I'm running PHP 7, if it matters.
My end result would look something like this:
$query->singular()->get(); // ($query is a ChildQuery)
It is just not possible to call a parent method by the public interface of an object (even if it is the same class/object like the current context). Please have also a look at https://stackoverflow.com/a/11828729/2833639.
In my opinion your solution is the right way to go.
Off Topic: I recommend to read https://ocramius.github.io/blog/fluent-interfaces-are-evil/ to evaluate whether a fluid interface is good for your use case.

can I access private variable in method in same class?

I have this controller
class PageController extends Controller
{
private $myid;
public funciton index(){
}
public function viewbyid($id){
$this->myid = $id;
return view('someview');
}
public function getRecord(){
$id = $this->myid;
echo $id; //it would be null here,if I am going to access this method.
return view('anotherview');
}
}
Yes, you can access private varible, in side class any where, Your using OOPS PHP. So may be problem is you might be accessing getRecord() method with diff object.
For Eg:
$obj=new PageController();
$obj->viewbyid("Test");
$obj->getRecord();//Then it will display the result
If your reinitialize an object or creating new object then that object will reallocate memory, so previous saved values will not be present.
For Eg:
$obj=new PageController();
$obj->viewbyid("Test");
$obj=new PageController();//$obj will allocate memory in diff location so your previous values will be initialized to default.
$obj->getRecord();//Then it will display result as null

PHP - Closure in class , getting private property

I'm attempting to get a private property from another class using closures, as explained here:
http://ocramius.github.io/blog/accessing-private-php-class-members-without-reflection/
So, I'm trying to get the $wheelCount property.
But I keep getting
Fatal error: Cannot access private property Car::$wheelCount
So my car class is:
class Car
{
private $wheelCount = 4;
public function __construct($wheely)
{
echo $wheely->getWheels($this);
}
}
and then
class getThoseWheels
{
public function getWheels($that)
{
$wheels = Closure::bind($this->getPrivate($that), null, $that);
var_dump($wheels);
}
public function getPrivate($that)
{
return $that->wheelCount;
}
}
which is run:
$wheely = new getThoseWheels();
new Car($wheely);
$wheels = Closure::bind($this->getPrivate($that), null, $that);
The problem is that you're executing $this->getPrivate(), and this method is trying to access a private property. All this happens before Closure::bind is being involved at all. You're supposed to use it like this:
$wheels = Closure::bind(function () { return $this->wheels; }, $that, $that);
Or possibly:
$wheels = Closure::bind([$this, 'getPrivate'], null, $that);
I haven't tested this, but at least this has a much better chance of succeeding than your code.

Attempt to assign property of non-object error

I am getting this error and i can't see what i am doing wrong. I have done the same thing with other objects from other classes which are built in the exact same way and i can't see why i am getting this error now.
The code in which i create the object is this one:
$consulta2 = "SELECT * FROM TiposDireccion WHERE Cliente_CIF='$cif' and Direccion_Direccion='$direccion' and Direccion_CP=$cp ";
echo($consulta2."</br>");
if ($resultado2 = $conexion->query($consulta2)){
while($fila2 = $resultado2->fetch_object()){
$tipodireccion78=$fila2->TipoDireccion_Tipo;
//we see here that the select is returning a correct string with a correct value
echo($tipodireccion78);
//we try to instantiate and it fails =(
$unTipoDireccion=TipoDireccion::constructor1($tipodireccion78);
This is the class TipoDireccion:
<?php
class TipoDireccion{
private $tipo;
private $descripcion;
//Construct auxiliar
function __construct() {
}
//Constructor 1 : completo
function constructor1($tipo) {
$tipoDireccion = new TipoDireccion();
$tipoDireccion->tipo = $tipo;
return $tipoDireccion;
}
function ponTipo($tipo) {
$this->tipo = $tipo;
}
function devuelveTipo() {
return $this->tipo;
}
function ponDescripcion($descripcion) {
$this->descripcion = $descripcion;
}
function devuelveDescripcion() {
return $this->descripcion;
}
}
?>
Thank you a lot in advance!
Don't know if this is still relevant to you, but in case anyone else comes on here for an answer. The problem is in this function:
function constructor1($tipo) {
$tipoDireccion = new TipoDireccion();
$tipoDireccion->tipo = $tipo;
return $tipoDireccion;
}
Because in the class definition, you define private $tipo; and then you try and assign $tipoDireccion->tipo to what was passed through the function. However, you aren't trying to access that variable through the scope of the class, you are trying to assign it from the 'public' scope as far as the class is concerned.
The fix for this has two options, the first one would be to change private $tipo; to public $tipo;. But that isn't a good solution as you have an assignment function for it.
Instead, use your functions that you made, which would make the function look like:
function constructor1($tipo) {
$tipoDireccion = new TipoDireccion();
$tipoDireccion->ponTipo($tipo);
return $tipoDireccion;
}
That's how you need to access it from the public scope, which you are doing after you initiate a new one.
function constructor1($tipo) {}
should be
static function constructor1($tipo) {}

When object property is asked first time gets data, and then just returns it - is it possible?

I need some data from the object.
I don't want these data to be loaded in class construction, because it is db heavy.
I don't want to load it more than once in a page.
I don't want to remember was it loaded already, or not.
$object->data // should be loaded in construction
$data = $object->get_data() // ok, but I need to remember was is got already, or not.
Is there a way to use $object->data, if it is asked first time, it actually gets data and returned it. And when I ask it after this, it just returns old data.
If there is no way, I will just use $data = $object->get_data(). But maybe I'm missing something.
This is usually solved using "lazy loading" - the property itself is backed using a private field, which gets initialized to some magic value (e.g. null) in the constructor, and gets filled the first time the getter gets called. After that, the getter returns the already-loaded value. Example:
class Foobar {
private $_lazy;
public function __construct() {
$this->_lazy = null;
}
public function __get($key) {
switch ($key) {
case 'lazy':
if ($this->_lazy === null)
$this->loadLazy();
return $this->_lazy;
}
}
private function loadLazy() {
$this->_lazy = rand();
}
}
Thing that you talking about is called Lazy Loading. You should implement that in method get_data(). If you wanna use it as property, not method, you must use PHP's magic __get method and return your data when accessing that data property.
But I recommend using method - it's more explict.
Well, you can do this
//create an object
class Foo{
//give some attributes
public $attr1;
public $attr2;
public $attr3;
public $attr4;
....
....
//create a function to load data
public function foofunction()
{
//and set the attrs
$this->attr1 = $somevalue;
$this->attr2 = $somevalue;
$this->attr3 = $somevalue;
//...
....
}
}
and you in your page
//create an object
$foo = new Foo();
//fetch data which will instantiate the attrs
$foo->foofunction();
//and you can use any attr at any time
echo $foo->attr1;
echo $foo->attr2;
//and this attr necessarily does not have to string, or int or ..
//it can be anything
Object has a property - flag, that indicates if the data have been asked before.
It's lazy loading
// simple implementation
public function get_data() {
if (is_null($this->_data)) {
$this->_data = $db->query();
}
return $this->_data;
}

Categories