Initialize static member with custom class in php - 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");

Related

PHP undefined index in a class

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

What is the use of return $this in php constructors?

I have always done :
class Class1{
protected $myProperty;
public function __construct( $property ){
$this->myProperty = $property;
}
}
But recently, I have been coming across a particular technique like so:
class Class2{
protected $myProperty;
public function __construct( $property ){
$this->myProperty = $property;
return $this;
}
}
And in instantiating this class, one would do :
$property = 'some value';
$class1 = new Class1( $property );
$class2 = new Class2( $property );
What is the significance of the line return $this in the constructor of Class2 since with or without it, the variable $class2 will still contain an instance of Class2?
Edit : please this is different from a constructor returning values. I heard this one is called fluent interfaces (for method chaining). I have looked at this thread Constructor returning value?. It is not the same thing I am asking. I am asking for the significance of return $this
There isn't a use for returning $this there.
Chances are that they are using a IDE which automatically inserts return $this or similar, which is useful for method chaining, but the return statement to __construct is discarded.
return $this; should not have any value in the constructor. But I see some value if it is returned in any other function for the class, when you want to call the functions consecutively. For example :
class Student {
protected $name;
public function __construct($name) {
$this->name = $name;
//return $this; (NOT NEEDED)
}
public function readBook() {
echo "Reading...";
return $this;
}
public function writeNote() {
echo "Writing...";
return $this;
}
}
$student = new Student("Tareq"); //Here the constructor is called. But $student will get the object, whether the constructor returns it or not.
$student->readBook()->writeNote(); //The readBook function returns the object by 'return $this', so you can call writeNote function from it.

Too many parameters?

Ok, i have managed to end at this one.
Controller:
$addProperty=Property::addProperty($title,$description,$location,
$agent,$owner,$lat,$long,$position,$photoHolder,
$stars,$negatives,$adverts,$dropLink,$photosSite);
Model:
public static function addProperty($title,$description,$location,$agent,
$owner,$lat,$long,$position,
$photoHolder,$stars,$negatives,
$adverts,$dropLink,$photosSite)
The problem is that, not only, i have too many parameters but i need to pass around 10 more.
Any advice?
There's quite a few ways you could do this. My preferred way though when working with models is to have a set method for each attribute. That way you don't need to pass everything all at once (very useful as an application evolves and stuff gets added/removed).
So in a model, I would usually have something like this:
class Property {
private $title;
private $description;
private $location;
/**
* Creates an instance of property via a static method.
*
*/
public static factory()
{
return new Property();
}
public function setTitle($title)
{
$this->title = $title;
return $this;
}
public function setDescription($description)
{
$this->description = $description;
return $this;
}
public function setLocation($location)
{
$this->location = $location;
return $this;
}
// because the attributes in this instance are private I would also need getters
public function getTitle()
{
return $title;
}
public function getDescription()
{
return $description;
}
public function getLocation()
{
return $location;
}
}
Then you can also add in a save() method or whatever else you want it to do.
OK, so I've added a new static method called factory which allows you to create an instance without having to assign it to a variable. In addition to that I have added return $this; to all methods which do not return an attribute.
What this effectively means is you can now do this:
// create a new property
Property::factory()
->setTitle($title)
->setDescription($description)
->setLocation($location)
->save(); // if you had that function
The beauty of this is that if you did need to have a break in it, then the following would also work.
// create a new property
$property = Property::factory()
->setTitle($title)
->setDescription($description); // this is returning the property instance `return $this`
// do some processing to get the $location value
// continue creating the new property
$property
->setLocation($location)
->save(); // if you had that function
better way is to pass parameter as an array :
$params=array(
'title'=>'title',
'other_parameter'=>'value',
);
$addProperty=Property::addProperty($params);

getall function in PHP

What is wrong in my class.It;s giving me syntax error, unexpected ',' on my getall function.Is is not possible to send multiple return value? What would be the problem.
class Form
{
private $name;
private $email;
private $pass;
private $rpass;
private $phone;
public static function setname($name)//setting name
{
$this->name=$name;
}
public static function email($email)//setting email
{
$this->email=$email;
}
public static function password($pass)//setting password
{
$this->pass=$pass;
}
public static function repassword($rpass)//password again
{
$this->rpass=$rpass;
}
public static function phone($phone)
{
$this->phone=$phone;
}
public static function getall() //getting all value
{
$a=$this->name;
$b=$this->email;
$c=$this->pass;
$d=$this->rpass;
$e=$this->phone;
return($a,$b,$c,$d,$e);//here is the problem
}
}
It seems like you want to return an array, but what you have is invalid syntax it doesn't mean anything.
So change this:
return($a,$b,$c,$d,$e);
to this:
return [$a,$b,$c,$d,$e];
//^ See here ^
For more information about arrays see the manual: http://php.net/manual/en/language.types.array.php#language.types.array.syntax
Also you can't have static functions with $this. Because $this is only accessible in object syntax, but not in the class itself, so I think you want to remove the static keyword from the functions.

Return a reference to an instance of an object in PHP

I have a singleton factory and would like it to return a reference to the object instance so that I can use the singleton factory to destroy the instance and not have instances elsewhere in my code to survive.
Example of what I would like to be able to do:
$cat = CatFactory::getInstance();
$cat->talk(); //echos 'meow'
CatFactory::destructInstance();
$cat->talk(); //Error: Instance no longer exists
This could work:
<?php
class FooFactory
{
private static $foo;
private function __construct()
{
}
public static function getInstance()
{
return self::$foo ? self::$foo : (self::$foo = new FooFactory());
}
public static function destroyInstance()
{
self::$foo = null;
}
public function __call($fn, $args)
{
if (!method_exists(self::$foo, $fn) || $fn[0] == "_")
throw new BadMethodCallException("not callable");
call_user_func_array(array(self::$foo, $fn), $args);
}
# function hidden since it starts with an underscore
private function _listen()
{
}
# private function turned public by __call
private function speak($who, $what)
{
echo "$who said, '$what'\n";
}
}
$foo = FooFactory::getInstance();
$foo->speak("cat", "meow");
$foo->_listen(); # won't work, private function
FooFactory::destroyInstance();
$foo->speak("cow", "moo"); # won't work, instance destroyed
?>
Obviously it is a hack.
Based on the documentation for unset, I do not think that is possible. You cannot actually destroy an object, only a handle to it. If other variables are around that still hold a reference, the object will continue to live on.
You can accomplish what you want by having your Cat object enforce a private $destroyed property. PHP 5 passes objects by reference by default, so you don't have to worry about that part.
A work around would be creating a cat class
class cat
{
public $cat;
public function __construct()
{
$this->cat = CatFactory::getInstance();
}
public function __destruct()
{
CatFactory::destructInstance();
}
}
$cat = new cat();
$cat->cat->talk();
$cat->cat->talk();

Categories