PHP undefined index in a class - php

I know this has been asked before and I have looked at multiple threads on why this would happen but could not understand how mine does not work as other variables defined in the same way and gathered the same way work.
class item{
var $name = "test";
var $id = 3;
function setId($newID){
global $id;
$id = $newID;
}
function getId(){
return $GLOBALS['id'];
}
function setName($newName){
global $name;
$name = $newName;
}
function getName(){
return $GLOBALS['name'];
}
}
That is a snippet of the class as it is really long but duplicate getName and setName for 5/6 more items.
$item[0]->getName();
Would return "test"
$item[0]->getId();
Returns the "Undefined index: id in link to file on line 59" which is the getId() function.
Every function other then getId() works and I have no idea why
EDIT - this question has been answered I am waiting to be able to accept an answer. $this worked for the variable to return (even though I'm still not sure why it would even though the 5 or 6 others would)

Your understanding of variable scope within a class is wrong. Setters and getters are, usually, to modify and fetch private or protected properties. Assigning a property with var automatically gives them a public scope.
In a class, you don't need to use global - in fact, using global is bad practice anyway. You can reference class properties with $this.
For example;
class item {
private $name = "test";
private $id = 3;
function setId($newID){
$this->id = $newID;
}
function getId(){
return $this->id;
}
function setName($newName){
$this->name = $newName;
}
function getName(){
return $this->name;
}
}

Start your classes from large letter (and use camelCase for variables and CamelCase for classes):
class Item
Do not use var $id inside of your class, use private or protected access modifiers:
private $id;
Access your class variables using $this:
function setId($id){
$this->id = $id;
}
Hope it will help

Not sure if this helps but I can't tell if you initialized the class at all.
<?php
class Item{ //Use Capital for class name
var $name = "test";
var $id = 3;
function setId($newID){
$this->id = $newID;
}
function getId(){
return $this->id;
}
function setName($newName){
$this->name = $newName;
}
function getName(){
return $this->name;
}
}
Then this is how you get name
$item = new Item(); //initialize
$item->getName(); //get name

Related

How to solve undefined variable and undefined property warnings?

I have $name and $age defined in set_name() and set_age.
Please check index.php:
<?php
// This part needs some fixing.
class Pet {
public $name;
public $age;
// get() and set() functions for name
function set_name($name) {
$this->name = $name;
}
function get_name() {
return $this->$name;
}
// get() and set() functions for age
function set_age($age) {
$this->age = $age;
}
function get_age() {
return $this->$name;
}
}
.....
Edit:
This problem is fixed. No need for new answers!
You need constructor for your classes and don't do the makeSound method in your Pet class static. Try this:
public Cat(){
makeSound(sound);
}
public Dog(){
makeSound(sound);
}
Your method declaration is wrong. If a parent has an implemented version of a function, you do not need to declare it in the subclass. But even if you would want to, the correct way to do it (thus overriding the parent function) would be:
void makeSound(String sound) {
System.out.println("Hi, I make a " + sound);
}
The use of a static keyword would not make much sense. A static method is a method that is part of the class and not of the created objects. Meaning you could call the method like this Pets.makeSound(...)

variable creation inside classes

I am following a tutorial on dependency injection. My issue is that I do not understand how some of the variables are being formulated within the classes. Within class Author we have $firstname and $lastname. Within class Question we have $author and $question. Then magically(?) we have within the class Question constructor we get $authorFirstname and $authorLastname.
I don't get it - it's like they have been concatenated, but that can't be, right ?? But then the $authorFirstname and $authorLastname have not been declared within class Question.
So, Question: how does the author get to the $authorFirstname and $authorLastname - or am I over thinking this ??
class Author {
private $firstName;
private $lastName;
public function __construct($firstName, $lastName) {
$this->firstName = $firstName;
$this->lastName = $lastName;
}
public function getFirstName() {
return $this->firstName;
}
public function getLastName() {
return $this->lastName;
}
}
class Question {
private $author;
private $question;
public function __construct($question, $authorFirstName, $authorLastName) {
$this->author = new Author($authorFirstName, $authorLastName);
$this->question = $question;
}
public function getAuthor() {
return $this->author;
}
public function getQuestion() {
return $this->question;
}
}
You're overthinking.
you notice, __construct($question, $authorFirstName, $authorLastName)...
construct is a special function that runs when a new object of that class is created.
$authorFirstName and $authorLastName are just variables to be passed to the Question constructor function, aka
$question = new Question($questioninfo,'William','Shakespeare');
(in this case, $authorFirstName = William, $authorLastName = Shakespeare)
They only get used within the scope of the __construct() function, which in this case instantiates a new Author. so if the input was as above, this will happen inside the constructor of Question:
$this->author = new Author('William', 'Shakespeare');
and those variables will be handled by Author's constructor, as $firstName and $lastName... make sense?
The Question ctor is an example of a hidden dependency, not showing how dependency injection works:
public function __construct($question, $authorFirstName, $authorLastName) {
$this->author = new Author($authorFirstName, $authorLastName);
$this->question = $question;
}
As this code shows, the parameters $authorFirstName, $authorLastName are used to create the Author dependcy inside Question. Therefore the dependency is not injected.
Instead, the author should be injected:
public function __construct($question, Author $author) {
$this->author = $author;
$this->question = $question;
}
The Question is only interested in compositing an Author, there is no need that the Question needs to create an Author.
I hope this also illustrates how parameters work.

Why I can not using $this with get_object_vars

<?php
require_once 'database.php';
class User {
public $id;
public $username;
public $first_name;
public $last_name;
public $password;
public static function find_by_id($id){
$result_array = self::find_by_sql("SELECT * FROM users WHERE id = {$id} LIMIT 1");
return !(empty($result_array))? array_shift($result_array): false;
}
public static function find_by_sql($sql){
global $database;
$result = $database->query($sql);
$object = array();
while ($row = $database->fetct_array($result)){
$object[] = self::instantiate($row);
}
return $object;
}
public static function instantiate($record)
{
$object = new self;
foreach($record as $attribute => $value)
{
if ($object->has_attribute($attribute)){
$object->$attribute = $value;
}
}
return $object;
}
private static function has_attribute($attribute){
$object_var = get_object_vars($this);
return array_key_exists($attribute, $object_var);
}
}
?>
I got error when I try to call function has_attribute. Notice: Undefined variable: this
Why I cannot use this in get_object_vars in private function has_attribute($attribute).
Can anyone help me with that?
Thank you.
$this is not defined in static methods (they belong to the class in general, not to specific object) - but all the methods in your class are defined as static.
You might want to change the has_attribute method so it'll take the instance of User as a param, but I don't think that's good design. In fact, I don't understand why do you need this method at all: for all the cases when non-existing property of an object is accessed, so-called magic method __get() is called automatically:
The overloading methods are invoked when interacting with properties
or methods that have not been declared or are not visible in the
current scope. [...] __get() is utilized for reading data from inaccessible properties.
If you defined has_attribute to prevent accessing non-existing properties (log these attempts, for example), move the code into __get.
That is because $this keyword is not accesible on a static context.
Source

How do I use objects and access their methods while within an object in PHP?

How do I use an object (along with its methods and properties) when I'm inside an object?
Say I have useless classes like these:
class Fruit {
private $name; // Name of the fruit.
private $health = 10; // 0 is eaten, 10 is uneaten.
private $object; // This is a PHP object.
public function __construct($name) {
$this->name = $name;
}
public function set($varname,$value) {
$this->$varname = $value;
}
}
class Eater {
private $name;
public function eat($object) {
$object->set('health',0); // I know I can pass and modify objects like this.
// The object is passed by reference in PHP5 (but not 4), right?
}
}
And I use it as such:
<?php
$pear = new Fruit("Pear");
$apple = new Fruit("Apple");
$paul = new Eater("Paul");
$paul->eat($apple);
?>
But if I modify the Eater class like so:
class Eater {
private $name;
private $objectToEat; // Let's say if I need the object to be over here instead of in a method.
public function set($varname,$value) {
$this->$varname = $value;
}
public function eat() {
$this->objectToEat->set('health',0); // This doesn't work!
}
}
And set the main program like so:
<?php
$pear = new Fruit("Pear");
$apple = new Fruit("Apple");
$paul = new Eater("Paul");
$paul->set('objectToEat',$apple);
$paul->eat();
?>
How can I access the object's properties from inside a method? I know I use $this->objectToEat to tell PHP I'm talking about the class properity, but since that property is an object, how do I access the object's methods?
I've tried $this->objectToEat->set('health',0) but that doesn't work. I hope you guys understand what I'm trying to get at (sorry, I can't figure out how to condense my question without compromising clarity)!
You have to set the property correctly. Since it's private, you can't do this from outside the object, so you have to use encapsulation:
class Eaters {
private $name;
private $objectToEat;
public function eat() {
$this->objectToEat->set('health',0); // Assumed "object" was just a typo
}
public function setObjectToEat($object) {
$this->objectToEat = $object;
}
}
Then use it like so:
<?php
$pear = new Fruit("Pear");
$apple = new Fruit("Apple");
$paul = new Eater("Paul");
$paul->setObjectToEat($apple);
$paul->eat();
?>
Note: In this brief example, your original method is a better design. In certain cases, you might want to prime the method to be used by setting properties beforehand, but more often you want to call it with parameters directly, since it's more clear and more reusable (compartmentalized).
This answer modifies Renesis' answer
In the class, the object to eat is a private variable hence you can't go
$paul->objectToEat = $apple;
What you can do is to make a setter method inside Eaters
class Eaters {
private $name;
private $objectToEat;
public function eat() {
$this->objectToEat->set('health',0); // Assumed "object" was just a typo
}
public function setFood($object) {
$this->objectToEat = $object;
}
}
Therefore, you can call the setFood() method instead.
OR
Change eat() to
public function eat($object) {
$this->object->set('health',0);
return $object;
}
Saving the modified object back to the original variable.
OR
class Eaters {
private $name;
public function eat(&$object) { // this passes object by reference
$object->set('health', 0);
}
}
Although this code is not tested, that is how you can pass a variable by reference.
NOTE: You only need the & when defining the method not when you're passing an argument. For more info about Passing by Reference go to this link
It's probably because your eat method isn't accepting any parameters, and the Eaters class has no $object property.
Can you make $objectToEat a reference and then use it as such in the eat() function?
you have to set $this->object in class Eaters
function __construct($object){
$this->object = $object;
}
or
<?php
$pear = new Fruit("Pear");
$apple = new Fruit("Apple");
$paul = new Eater("Paul");
$paul->eat($apple);
?>
class Tester {
private $variable;
private $anObj;
public function testFn($val) {
$this->variable = $val;
$this->anObj = new SecondObj();
$this->doSomething();
}
public function doSomething() {
echo("My variable is set to " . $this->variable);
$this->anObj->wow();
}
}
class SecondObj {
public function __construct() {
echo("I'm new!");
}
public function wow() { echo("Wow!"); }
}
$tester = new Tester();
$tester->testFn(42);
Output:
I'm new!My variable is set to 42Wow!

Initialize static member with custom class in php

as there are no enums in PHP I tried to do something like this:
class CacheMode{
public static $NO_CACHE = new CacheMode(1, "No cache");
private $id, $title;
public function getId(){
return $this->id;
}
public function getTitle(){
return $this->title;
}
private function __construct($id, $title){
$this->id = $id;
$this->title = $title;
}
}
The problem is, that I get a parse error if I run the script:
Parse error: syntax error, unexpected T_NEW
I "worked it aroud" with this:
class CacheMode{
public static function NO_CACHE(){
return new CacheMode(1, __("No cache",'footballStandings'));
}
public static function FILE_CACHE(){
return new CacheMode(2, __("Filecache",'footballStandings'));
}
public static function VALUES(){
return array(self::NO_CACHE(), self::FILE_CACHE());
}
private $id, $title;
public function getId(){
return $this->id;
}
public function getTitle(){
return $this->title;
}
private function __construct($id, $title){
$this->id = $id;
$this->title = $title;
}
}
It works, but I am not really happy with it.
Can anyone explain, why I can't do the static $xyz = new XYZ(); way or has a better solution for this problem?
Its annoying, I know. I solve it like
class Foo {
public static $var;
}
Foo::$var = new BarClass;
Its a little bit similar to javas "static code blocks" (or whatever they are called ^^)
The file is only includeable once anyway (because a "class already define" error occurs), so you can be sure, that also the code below the class is executed once.
As an optimization, you could store the object instance as a static field, so that you are not creating a new object every time the static method is called:
private static $noCache;
public static function NO_CACHE(){
if (self::$noCache == null){
self::$noCache = new CacheMode(1, __("No cache",'footballStandings'));
}
return self::$noCache;
}
But yes, it is annoying that you cannot assign a new object instance to a class field when you first define the field. :(
Quoting the manual page of static :
Like any other PHP static variable,
static properties may only be
initialized using a literal or
constant; expressions are not allowed.
So while you may initialize a static
property to an integer or array (for
instance), you may not initialize it
to another variable, to a function
return value, or to an object.
That is why you cannot do
public static $NO_CACHE = new CacheMode(1, "No cache");

Categories