I have a class that when I instantiate it fill the property via construct.
The goal of this class is describe a shop, so his properties will protected because they belongs only to that class.
But the problem is that sometimes I need to get some informations about that class from the properties.
example:
class Shop {
protected $name;
protected $typology;
protected $owners;
protected $closed;
public function __construct($name,$typology,$owners,$closed)
{
$this->name = $name;
$this->typology = $typology;
$this->owners = $owners;
$this->close = $closed;
}
}
$shop = new Shop("Name Shop","vegetarian",2,1);
$superMarket = SupermarketFactory::getInstance($shop);
On the class Supermaket that (instantiated via Factory), need to get shop properties to work with.
There are a bunch of ways to make this work, but all solutions are a bit messy on my view point. I experimented this ways:
Setting getters and setters - To exclude this way, having 20 properties I need 40 methods. Scripts are not efficient.
Using __get() magic method, my IDE complain about getting those property via magic method. That's even true because at this point I could set it public.
Using Reflection, It seem to be the best of the above ways, but still need too much implementation for get only properties ( I guess)
So I would like achieve the best design to get this work, have a class that has protected property but at the same time callable in a elegant way.
There is any of design pattern that helps this goal?
I may have ask already something similar on stackOverflow but I reviewed the question and proposed in a better way.
You can define a list of properties accessible via __get() and __set() in your class docblock using the #property tag that should make them visible to IDEs
See http://www.phpdoc.org/docs/latest/for-users/phpdoc/tags/property.html and http://manual.phpdoc.org/HTMLSmartyConverter/PHP/phpDocumentor/tutorial_tags.property.pkg.html for reference and examples
Related
I am a junior PHP programmer. I still have a lot to learn. That's why I ask this question. In a class you have a public function which you can call it from outside that class. Sometimes you have a private function which you can call several times in that class where the private function resides, for reusable purpose. I like to set the private function to static and I call that function with:
self::privateFunctionName();
By using self it reminds me that this private function resides in that class. if I use $this->privateFunctionName() for non-static function, it could be in the superclass/base class or in that subclass itself. That is why I like to use static private function. In a professional point of view, is it a good idea to use static private function instead of non-static? Is there any disadvantage that a professional programmer like you prefers to avoid the static function?
Only using self::... must not mean the method is static. parent:: and self:: work as well for non-static methods. You can find this in the PHP manual - Scope Resolution Operator (::) and I add some exemplary code excerpt at the end of the answer.
You perhaps might want to read through all answers of this earlier question:
When to use self over $this?
In total you will get there more details then my short description in this answer.
You might have been confused by the scope-resolution-operator :: which is used by those. I had a similar understanding problem grasping that.
However, do not just choose to use static methods for such a limited reason. Those static class methods should only be used in very limited and narrowed situations. As a rule of thumb:
"Do not use static class methods."
If you like to start with object oriented programming, just use normal object methods.
Here is an excerpt from existing code that shows that self:: as well as parent:: are used with standard (non-static) methods:
<?php
...
/**
* Class XMLElementIterator
*
* Iterate over XMLReader element nodes
*/
class XMLElementIterator extends XMLReaderIterator
{
private $index;
private $name;
private $didRewind;
/**
* #param XMLReader $reader
* #param null|string $name element name, leave empty or use '*' for all elements
*/
public function __construct(XMLReader $reader, $name = null)
{
parent::__construct($reader);
$this->setName($name);
}
/**
* #return void
*/
public function rewind()
{
parent::rewind();
$this->ensureCurrentElementState();
$this->didRewind = true;
$this->index = 0;
}
/**
* #return XMLReaderNode|null
*/
public function current()
{
$this->didRewind || self::rewind();
$this->ensureCurrentElementState();
return self::valid() ? new XMLReaderNode($this->reader) : null;
}
...
self:: does not in fact mean that the method is part of the same class, it may as well have been inherited from a parent class!
You should not use the semantics of static method calls to differentiate "internal" and "external" methods. There's no real point to it anyway, and you're just abusing language features for something they weren't meant for. Maybe let that be a primary lesson: don't try to invent clever new ways of using language features. Just don't.
You should view methods as small, self contained black boxes. You don't need to know and don't want to know what they do. All you know is that when you call method foo with parameter $bar, x will happen or it will return y. You don't care how this happens, just that it does because that's what the method is supposed to do.
As such, static and non-static methods convey a different use with different limitations. static methods are supposed to be called when you don't have an object, for example as alternative constructor methods (e.g. DateTime::createFromFormat).
Further, restricting a method to being static means it has no access to object instance data, which may limit you in the future. As your project evolves, you may find that your method now needs to take into account some additional data from the object to do its job. If you declared it as non-static from the beginning, all it takes is a little modification to the method itself; to the outside world it still does its job the same way (input → output). However, if you declared it as static and suddenly find yourself needing to make it non-static, you have to change a lot more code than just that one method.
Bottom line: if your method is not supposed to be exposed publicly because it's nobody's business to call it except for your own class, make it private. If the method needs to be static because it must work without object context, make it static. If it fulfils both requirements, make it private static. Otherwise, don't.
Well basically a "private static" function is a construct which is totally nonsense because it cannot be called from the outside.
There is no real difference between $this-> and using self:: expect the fact that it can be called from the outside without a object and its the same amount of work for the CPU to call the function, no matter in what namespace/class this function is located.
However the fact that a private function can only be called within the same class you always have an object and the "static" modifier is somewhat superflous here because it makes no difference.
In this cases I always like to say: do what you like its just a matter of your personal style but dont switch arround, keep it that way to develop and use the standard you feel comfortable with.
In some cases there is just "another" way and a "professional" way does not exist at all.
The trend often makes the one or the other method to become popular over time.
I have an application with many classes in my Model, and each class has many properties.
Most of these classes share some properties, but in such a way that creating a class hierarchy using only single inheritance is not really suitable.
So I started creating some Traits containing only properties, without methods, such as:
trait Dateable {
protected $strat_date;
protected $end_date;
}
trait Featurable {
protected $image;
protected $description;
}
trait Buyable {
protected $price;
protected $buy_link;
}
etc... And then I define my classes like:
class Film {
use Featurable;
// some own properties...
}
class Showing {
use Dateable, Bookable;
// some own properties...
}
class Course {
use Featurable, Dateable, Bookable;
// some own properties...
}
This allows me to have a more organised model of classes, but I was wondering if this is a correct use of Traits because I can't find any examples of this...
Is not there any reason (e.g., performance) to avoid doing this?
It's incorrect in terms of OOP, because pure OOP suggests that you encapsulate everything possible. In general words, you should not have any public properties. All object's data should be accessible only by object's methods.
In your example, you have protected everywhere, but that is still a little bit incorrect, since it makes your code coupled on that trait meaning that you might get problems if you will try to disable it.
But if you will add getter-setter, then you are OK.
In fact, making those getters and setters abstract will ensure that your objects will be trully "Dateable, Featureable, Bookable, etc.".
A little bit better example would be trait called jsonParsable that has abstract function toJson(). Each class probably will have his own rules for returning JSON represenation, so it is good to make this trait abstract.
This question already has answers here:
What are public, private and protected in object oriented programming?
(7 answers)
Closed 9 years ago.
This may seem pretty simple and I am sure it is, I am just not getting it.
I understand that protected properties in a class in PHP can only be accessed within the class itself and inherited classes. Here is my code so far:
class q {
public $publicQ = "This is a public property";
protected $protectedQ = "This is a proected property";
public function displayProtected() {
echo $this->protectedQ;
}
}
$q = new q;
echo $q->publicQ; #prints "This is a public property"
echo $q->protectedQ; #nothing
$q->displayProtected();
I have read the documentation, looked at other answers on SO and the concept just is not clicking with me. What do protected properties actually do, why would we use them and why is my example not working?
Think of your public properties and methods as an API you expose to the outside world and private/protected ones as "inner workings" of your class that the outside world not only shouldn't be concerend with but shouldn't be able to mess with either.
Here comes the obligatory bad car analogy:
The methods you'd expose in a Car class could be driveForward() and driveBackwards(). Both of them would make use of a method called transmitTheDriveToTheWheels() but it shouldn't concern the car's users and shouldn't be accessed by them, so you'd "hide" it by making it private.
Your car would have an engine property. You definitely don't want someone to be able to replace the engine with a cute little kitty by going $car->engine = $kitty; so you'd make the engine private as well.
Finally, your car would have a mileage property. You want the user to be able to read the mileage but not to be able to modify it. So you make the mileage private and expose a public getMileage() method.
Now whether you want to use private or protected to encapsulate the "inner" stuff of your class, depends on whether you expect the class to be extended or not.
Protected fields can be inherited, but cannot be shown like echo $q->protectedQ;
Private fields cannot be neither displayed nor inherited.
Protected functions make your class more flexible.
Think of a class that somewhere has to load some data. It has a default implementation, which reads the data from a file. If you want to use the same class, but want to change the way it gets its data, you can create a subclass and override the getData() funciton.
You use protected/private methods to contain functionality to make your code easier to read and prevent repeating the same functionality in your public methods.
Making properties protected protects the object from being modified from outside unless you provided access via a setter.
You get more control over how your object is able to be used.
The only really difference from public methods is, as you've discovered, that protected functions can only be accessed from within the class or another class in the inheritance tree.
You wan't to declare functions as protected when they are not meant to be used from outside the class.
This is a language feature purely to make your code more understandable (easier to read) and less susceptible to bugs and misuse. There is nothing (in forms of functionality) that you can't accomplish using only public methods.
It is very useful if you're sharing your code with others or if it's some kind of library.
Specific to PHP there is a particular useful case when using PHP's magic getter and setter functions (http://www.php.net/manual/en/language.oop5.overloading.php#object.set).
public $a = '1';
protected $b = '2';
public function __get($name) {
return $this->{$name}.' (protected)';
}
$obj->a; //1
$obj->b; //2 (protected)
As per example, you can "protect" you variables and catch calls with the magic function.
It's useful if you've published a class with a variable, and you later decide to do some preprocessing internally in the class before returning the variable.
As the title says, I'm wanting to create an instance of a class from within a static method of the same class. I've figured out so far is that I can by doing something like this:
class Foo{
public $val;
public static function bar($val){
$inst = new Foo;
$inst->val = $val;
return $inst;
}
}
Which therefore lets me do this.
$obj = Foo::bar("some variable");
Which is great.
So now the questions. Is there an easier way of doing this that I'm not aware of, or any shortcuts to achieving the same result? Are there any advantages or disadvantages of creating an instance in this fashion?
Thanks.
They way you're doing it is fine. There are a few other things that can make your life easier that you can do as well.
Don't hardcode the class name. If you're on 5.3+, use the keyword static. That way, if you extend the class, the new function can instantiate that one as well:
public static function bar($var) {
$obj = new static();
$obj->var = $var;
return $obj;
}
Then you can use it in any extending class without needing to override anything.
Figure out if $var should be passed in through a constructor rather than set after construction. If the object depends upon it, you should require it.
public function __construct($var) {
$this->var = $var;
}
That way you can't instantiate the object without setting the variable.
Enforce the instantiation of the class through the static method. If you're doing anything in there that you need to do, then make the constructor either protected or private. That way, someone can't bypass the static method.
protected function __construct() {}
private function __construct() {}
Edit: Based on your comment above, it sounds to me like you're trying to implement the Singleton Design Pattern. There's tons of information out there about why it's not a great idea and the bad things it may do. It has uses as well.
But there are a few other patterns that may be of use to you depending on what you're doing exactly.
You can use the Factory Method if you're trying to create different objects using the same steps.
If all of the objects start off the same and then are customized, you could use the Prototype Pattern.
You could use an Object Pool if it's particularly expensive to create your object.
But one thing to consider, is that in PHP objects are pretty light weight. Don't try to avoid creating a new object just for that overhead. Avoid doing heavy things like database queries or filesystem accesses multiple times. But don't worry about calling new Foo() unless foo's constructor is particularly heavy...
This looks like a simple factory method pattern.
You have a nice advantage: suppose that in the future you want to start using a different implementation (but that does the same thing). Using a factory you can change all the objects that are created in many places of a complex system simply by changing the creator method. Note that this would work easier if you used an external class (as is in the first link below).
Keeping it as you have now, you can also subclass this class and override the method to create a more complex object. I don't think this is what you want to achieve in here.
Anyway, this is good to enable Test Driven Development, abstraction and lots of other good things.
links:
Php patterns
Factory method pattern on wikipedia
If you're just creating an object, this isn't very usefull. You could just call a constructor. But if you're doing something more complicated (like you're starting with some sort of singleton pattern but haven't included all the details in this example), then:
This sounds about right. If you want to prevent objects created in the default way like this:
$obj = new Foo("Some Variable");
You can add a private constructor:
class Foo{
public $val;
private __construct(){}
public static function bar($val){
$inst = new Foo;
$inst->val = $val;
return $inst;
}
}
Now you enforce people to use your static class. The need to set the val in the function might be gone, so you could even add the value-parameter to your private constructor but do the other things (that you presumably want to do, like check for some sort of singleton pattern) in your 'bar' function
Super late but found this useful.
A good example of this in the wild is this static method from Audi's UI library returning an Array of instantiated TextField classes from within TextField's static method upgradeElements.
/**
* Class constructor for Textfield AUI component.
* Implements AUI component design pattern defined at:
* https://github.com/...
*
* #param {HTMLElement} element The element that will be upgraded.
*/
export default class Textfield extends Component {
/**
* Upgrades all Textfield AUI components.
* #returns {Array} Returns an array of all newly upgraded components.
*/
static upgradeElements() {
let components = [];
Array.from(document.querySelectorAll(SELECTOR_COMPONENT)).forEach(element => {
if (!Component.isElementUpgraded(element)) {
components.push(new Textfield(element));
}
});
return components;
};
constructor(element) {
super(element);
}
...
See the rest in the repo
https://github.com/audi/audi-ui/blob/master/src/textfield/textfield.js#L25
First of all: A quite similar problem has been posted and somehow solved already, but is still not answering my specific problem. More about this later.
In words: I have a base class which provides some methods to all childs, but doesn't contain any property. My child is inheriting these methods, which should be used to access the child's properties.
If the child's property is protected or public, all works fine, but if the child's property is private, it fails without error (just nothing happens).
In code:
class MyBaseClass {
public function __set($name, $value) {
if(!property_exists($this, $name))
throw new Exception("Property '$name' does not exist!");
$this->$name = $value;
}
}
class ChildClass extends MyBaseClass {
public $publicProperty;
protected $protectedProperty;
private $privateProperty;
}
$myChild = new ChildClass();
$myChild->publicProperty = 'hello world'; //works of course!
$myChild->protectedProperty = 'hello world'; //works as expected
$myChild->privateProperty = 'hello world'; //doesn't work?
The above mentioned similar problem got the solution to use the magic __set() method to access the private properties, but this I am already doing. If I implement __set() within the child, it works of course, but the idea is, that the child inherits the __set() from it's parent, but obviously it can't access the child's private method.
Is that on purpose? Am I doinf something wrong? or is my approach just crap by design?
Background:
My original idea was: The whole dynamic thing about __set() is something I don't like. Usually a private property should never be accessible from outside, so I implemented throwing __set- and __get-methods in my ultimate base class (from which all classes inherit).
Now I want to dynamicially spawn an instance from an XML file and therefore need access to properties. I made the rule, that any XML-instantiatable class needs to implement the magic __set() method and so can be created dynamicially. Instead of implementing it in every Class that might be spawned some day, I decided to make them inherit from a class called like class Spawnable { } which provides the needed __set-method.
This is the difference between private and protected. Private methods and properties cannot be inherited or reached. You will need to change them to protected instead.
See the manual on visibility
Members declared protected can be
accessed only within the class itself
and by inherited and parent classes.
Members declared as private may only
be accessed by the class that defines
the member.
I guess you could fashion something using Reflection. For example, in your Spawnable class:
public function __set($name, $value)
{
$reflector = new ReflectionClass(get_class($this));
$prop = $reflector->getProperty($name);
$prop->setAccessible(true);
$prop->setValue($this, $value);
}
Not the prettiest of code, though.
After reviewing my concept, I think it's a bad idea, to go with that approach. This is a general issue with PHP's lack of differing between properties and fields. Of course private fields should never be accessible from outside, but only properties, which are defined by the programmer. The absence of auto-properties (and I don't mean these magical methods __set() and __get()) or some conventional rules for property access, makes it difficult to guess, which naming convention has been used by the programmer when implementing setters for private fields in his class.
The better concept here might be, to rely on the existence of well-named setters for each spawnable class, although it might break, if someone contributed code, which is not implementing the expected conventional named setters.
However, many thanks for your thoughts and hints!