Is it possible to exit gracefully out of a constructor in php? Something to the effect of
class Foo {
function __construct()
{
$active = false;
if(!$active)
{
return false;
}
}
}
I'm trying to accomplish this because I want to check to see if any of the methods in the class should run based on a configuration file. I don't want to have to check the configuration file in every method to see if the methods should be running.
That depends on what you mean by "gracefully". If you want your constructor to fail you can throw an exception, or you can use the factory pattern:
class FooFactory {
function makeFoo() {
return $someConstraint ? null : new Foo();
}
}
Maybe you can elaborate a bit on what exactly it is you want to accomplish.
Make it blow up. There is no such thing as a graceful failure in a constructor. Perhaps in the calling code, but not in the constructor. Throw an exception and handle it appropriately.
I can smell the Proxy pattern coming your way. What you are trying to achieve is not having the constructor fail gracefully but not allowing methods to be called on an object based on some $active criterion.
This might point you in the right direction. Or maybe not (=>> I don't quite like the page I linked in, but it was the best I could find for PHP). Do give Proxy a read, from other sources too perhaps. Basically, your ProxyObject will have a reference to a real object that will execute methods. Your client code will be calling methods on the ProxyObject as if it were the real thing, and the ProxyObject would decide whether it's active or not, whether to pass the message on to the real thing or to return nothing or nulls or dummy values. Sounds good?
If the constructor does so much logic, then it's not well designed.
Leave it empty, pass the configuration to it via a setter method and let it fail there.
It is not OO programming:
$o = new myObject();
if (!is_object($o)) // then what???
If your constructor fails, you should throw an exception, not return a false value. Unless you're using a language like C in which exceptions in the construction of the object means it can never be deconstructed.
The reason for this is because an exception forces the program to deal with it, and it give you the bad data. If you return a value, say -1 or whatever, the program can continue silently and ignore that until it causes a problem later down the road. Throwing an exception prevents these silent bugs from entering the code. You may know that it returns false if it failed to construct properly, but your co-worker may not and may happily try to use an object he thought was what he constructed to find out that it's really a boolean.
I think N3rd suggested a very cool solution but here is another simpler method.
class Foo {
private $active = TRUE;
function __construct() {
$this->check ( $active );
//OR
//if ($this->check ( $active )) { do something }
}
function check($var) {
if (! $var) {
$this->active = FALSE;
return FALSE;
}
return TRUE;
}
}
Related
How can I make the main PHP script return false from inside a class or a function?
Why: this is because of the built-in webserver:
If a PHP file is given on the command line when the web server is started it is treated as a "router" script. The script is run at the start of each HTTP request. If this script returns FALSE, then the requested resource is returned as-is.
from the documentation about the PHP Built-in webserver
In other words, you return false in your router script so that the built-in webserver can serve static files. Example from the documentation:
if (preg_match('/\.(?:png|jpg|jpeg|gif)$/', $_SERVER["REQUEST_URI"])) {
return false; // serve the requested resource as-is.
} else {
echo "<p>Welcome</p>";
}
The thing is that I'm trying to add that behavior to a web framework: I don't want to write that into index.php. I'd rather encapsulate that logic into a class (middleware) that will halt the script's execution if php_sapi_name() == 'cli-server' and a static asset is asked.
However, I don't know how I can make the whole PHP script return false from a class or a function, since obviously return false will return from the current method/function/file and not from the main file.
Is there a way to achieve the same behavior with exit() for example? I realize I don't even know what return false in the main file actually means (is that a specific exit code?).
You should have the router invoke the class method, and then, if the method returns false, you return false from your router file.
Of course it can turn into a headache. There are basically only two methods to achieve what you want to achieve.
There is a faster way though, you can abuse exceptions and create a specialized exception for the case:
StaticFileException.php
<?php
class StaticFileException extends Exception {}
router.php
<?php
try {
$c = new Controller();
return $c->handleRequest();
} catch (StaticFileException $e) {
return false;
}
Once you have this kind of code in place, just throw new StaticFileException and you're done.
If the method in your class handles static assets by using exit then the solution can be as simple as replacing exit with return false and having the caller of that method simply return the method in the global scope as well.
So if your class looks something like this...
class Router
{
public function handleRequest($uri)
{
if (is_file($this->docRoot . $uri->path)) {
exit; // static file found
} else {
// handle as normal route
}
}
}
Just replace exit there with return false ...
return false; // static file found
Then if your index.php works something like this...
$router = new Router($docRoot);
$router->handleRequest($_SERVER['REQUEST_URI']);
Simply add a return infront of the handleRequest method like so....
return $router->handleRequest($_SERVER['REQUEST_URI']);
This should have minimal side-effects on your framework design and as you can see requires very little code and refactoring because returning from the script's global scope only has a single side-effect in PHP (in that it returns the value to calling script i.e. if you used include/require as an expression in an assignment). In your case if index.php is the calling script then you have nothing to worry about here just by adding return infront of that method.
Of course, once you return the rest of the script will not continue so make sure it is the last statement in your index.php. You can even just assign the return value to a temporary value and return later if you needed for logic....
$router = new Router($docRoot);
if ($router->handleRequest($_SERVER['REQUEST_URI'])) {
/* if you need to do anything else here ... */
} else {
return false; // otherwise you can return false for static here
}
In general I would say that calling exit from inside of a function/method is almost never desirable. It makes your class harder to test and debug and really has no upside from the alternatives like throwing an exception, or just returning from the method, and letting the caller handle the failure scenarios gracefully.
Isn't possible to play with register_shutdown_function or with auto_append_file setting to deal with that? Not really nice but maybe that can do the job.
Within the class, I created a set method if what that is called that accepts data.
<?php
public function set_name($name)
{
$this->name = ucwords(trim($name));
// return $this->name;
}
?>
My question is, do I have to return the result of the function or not necessary. If not why? I know in the display() method you have to return like so: return $this->name;. I'm really confused.
You don't have to return anything.
However, it's good practice to return something on certain functions to perform tests on it, even if it's just true or false, to clarify that the function performed correctly.
Given your code, generally, I personally don't set a return on setters. So it's fine not to return anything.
For example, you may want to test that your name only contains letters and return false if it doesn't
<?php
public function set_name($name) {
if(preg_match("/[A-Za-z]+/", $name) {
$this->name = ucwords(trim($name));
return true;
} else {
return false;
}
}
?>
Then you'd call it by:
<?php
if(!set_name($name)) {
echo "There was an error";
}
?>
However, this doesn't comply with mvc framework.
In Object Oriented programming language return the value is the best. Otherwise it will be childish and hard to maintain bugs when your sites grow bigger and it tend to errors prone.
You don't HAVE TO return the result in a setter function, the best use is to make some getter functions to get the datas.
Otherwise my point of view with setter is to return $this. With this little trick you can chain up setter functions.
For exemple :
class C
{
private $arg;
private $arg2;
function setArg($NewArg)
{
// your tests or so
$this->arg = $NewArg;
return $this;
}
function setArg2($NewArg)
{
// your tests or so
$this->arg2 = $NewArg;
return $this;
}
function getArg()
{
return $this->arg;
}
function getArg2()
{
return $this->arg2;
}
}
And you can use it that way :
$Item = new C();
$Item->setArg('hello')
->setArg2('hi');
$Item->getArg(); // return 'hello'
$Item->getArg2(); // return 'hi'
It's more semantic in this case. Do I expect a function called set_name to give me the name? No, not really, that sounds silly. In this case, I wouldn't return anything.
Because a function should only do one thing, you should always be able to reduce the choice to a binary "yes, I'd expect it to return something" or "no, that doesn't make any sense" decision.
Generally speaking your methods should do what somebody would expect them to do just by looking at their names (some people will hate me for saying this).
It's always a good idea to put yourself in the position of a programmer who has to work with your code. If had to use a method called: set_name() he would never expect it to return something.
Your methods always should do what one would expect them to do and complain to the outer environment through exceptions. Not more, not less.
If you put this into practice: Congratulations. You have just built yourself a great and reliable alarm bell for methods that are doing too much (seperation of concerns) and you're a step closer to clean software design.
Of course that's not something you would force come hell or high water (nothing is), but that's something you need to decide by yourself. If you cannot do that for whatever reasons (for example method chaining, which has been mentioned several times) , you could provide a good documentation of your class(es) and make clear what the methods actually do.
The title is maybe not too clear, so here's an example.
abstract Class A {
public static $property = null;
}
Class B extends A {
}
Class C extends A {
}
I want to have a "None" method in all classes extending A, and this method should return an instance - always the same - of the called class. So:
B::None() // Returns a "default" B
C::None() // Returns a "default" C
Why is this: I have (simplifying) several Slots which may or may not be assigned to Activities of several kinds. So I can have a Slot for Surfing and one for Swimming. And that Slot may be null. In my code, when reporting, I could of course do something like
if (Slot.Surfing == null) {
println "Not surfing anywhere";
} else {
println Slot.Surfing.Location;
}
But I'd like to not check at all and just write
println Slot.Surfing.Location;
and pre-assign the slot to Surfing::None(). Actually I'd do that in a superclass and have it automatically assign the "proper" instance of None.
This way, Slot.Surfing(nowhere) is a different null from Slot.Swimming(nowhere), but that for me now would actually be a feature.
The problem is that if I really want to check I'm swimming somewhere, I must be sure that
if (Slot.Surfing == Surfing::None()) {
works. For that, None() must always return the same object. I could run the check on a field of Surfing, maybe a non-i18n-ed integer value... 0 or -1 being a typical choice... but adding a property for that purpose seems ill designed.
NOTE: this has many similarities with the Singleton (anti)pattern, but it is not actually a Singleton (see at bottom).
If I implement the None() method in A, though, I have to handle the fact that any static property will "live" only once, in A, and not in each of the child classes. So I create a default instance of B, save it in A, and then all subsequent calls to other subclasses of A will find and return that one instance -- and C::None() will be an instance of B.
I can make the None() method create a new default instance every time. This works, but now I have several "default" Bs, and in some circumstances two properties both set to B::None() will be, quite correctly, considered different.
In the end I came up with this workaround (PHP 5.3.+):
private static $nones = array(); // array of already created "null" instances
protected static function None() {
// If I do not already have an instance for this class...
if (!isset(self::$nones[$ChildName = get_called_class()])) {
// ... I create a default instance.
self::$nones[$ChildName] = new $ChildName(/*...*/);
}
// And I return the default instance.
return self::$nones[$myClass];
}
I have checked some questions and answers on Stack Overflow and elsewhere, and the most relevant one employs what amounts to the same approach (notice the $instance array indexed on the called class's name):
class A {
public static function getInstance(){
// Maybe use this function to implement the singleton pattern ...
return self::$instance[get_called_class()];
}
public function className(){
return get_class(self::getInstance());
}
}
Yet maybe because I'm still a wet-behind-the-ears OOPer, to me this approach smells. I would think there ought to be a way of declaring a child static property in the parent, and accessing it from the superclass (of course, then I would have to ask myself: if A declares a "downstream" static property, B inherits from A, and C from B, where does that property live, or where should it live, now? -- and I have no satisfying answer).
Addendum - Singletons
The above approach is in practice not too different from a Singleton. It seems (thanks to Touki for pointing me there) that I can get rid of Singletons through dependency injection. Yet in this case it would require to pass around, say, None_C to all methods that may require a default value for a reference to an instance of C. I would then have to push None_C into my Configuration object, and have it know about any subclasses of A that I might declare. At first sight, this smells even more (although in fact adding another subclass of A amounts to changing the system's configuration... which would be the reason for changing Configuration).
TL;DR
So to make a long story short, granted that the above approach does work,
is having the parent class maintain a static array of its "active" children acceptable from an OOP point of view?
is there a better and/or cleaner way to do it?
If memory is not an objection (nowadays, it rarely is), the solution is simply to get a step further into OOP land.
The real problem for which the "child singleton" was needed was that I wanted comparisons to be reliable. Of course two different "nulled" objects, while being both "nulled" and therefore identical in this respect, are not the same object. If they have identical properties too, then the == operator will return TRUE, but if one of them gets slightly changed for some reason (i.e., due to a bug), == will return FALSE. The use of === PHP5 operator in singleton context will solve this problem, but introduces more complexity.
The (not so obvious to me) simple solution is to discard comparisons altogether and simply replace:
if (Slot->Surfing == Surfing::None())
with a suitable
Slot->Surfing->isNull() // or maybe isEmpty() depending on semantics
Then I can declare the isEmpty method in the parent class, and this reveals that I really needed also a more specific equals and comparison operators:
abstract Class A {
...
public static function createNull() {
$nulled = new A();
$nulled->setNull(); // Whatever is needed to nullify an object
return $nulled;
}
public function setNull() {
$this->nullFlag = true; // Example
return $this;
}
public function isNull() {
return (true === ($this->nullFlag)); // Or whatever else
}
abstract function equals($obj);
abstract function compareTo($obj);
}
Class Surfing extends A {
public function equals($obj) {
if (null == $obj) {
return false;
}
if ($this === $obj) {
return true;
}
if (!($obj instanceOf Surfing)) {
return false;
}
// Properties
foreach(array('property1','property2',...) as $val) {
if ($this->$val !== $obj->$val) {
return false;
}
// Maybe some other check
...
return true;
}
}
...
Slot->Surfing = Surfing::createNull();
...
if (Slot->Surfing->isNull()) {
...
}
An additional big advantage of this approach is that now every activity is an independent object and can be safely updated without altering other instances (if Slot->Surfing was a nulled object, to set it to something else I needed to reassign, I couldn't simply go ahead and modify it -- this actually introduced horrid coupling and had a tremendous potential for subtle bugs).
For years now I have been writing (on and off) at an office-management app. I need to rewrite it, because the code has become unmaintainable, so I will choose a PHP-framework and rewrite the business logic into classes.
Now I am stuck with this fundamentamental question: do I still need to return the result and if yes, how do I capture that result? Some pseudocode to make my question clear:
function a( $1, $2, $3 ) {
doThis( if ... return TRUE; if ... return FALSE; );
if ( doThis() != TRUE ) { return; }
doThat();
}
vs
class example {
private $1;
private $2;
private $3;
public function go() { $this->doThis(); $this->doThat(); }
private function doThis(){}
private function doThat(){}
}
$a = new example;
$a->go();
How can I stop the execution of the go()-method if the doThis()-method does not perform as expected? I presume I should not go about returning booleans and checking inside every method if a certain property is set to false? Or do I simply throw an Exception if something went wrong and don't do anything if everything is ok?
This is pretty basic, I know...
Thx!
Exceptions are for exceptional behaviour, so don't throw exceptions just because your code isn't in a preferred state. When it comes to writing OOP, some people still manage to write procedural while using a object oriented framework, obviously you'd want to avoid that, a simple rule of thumb is to not write God-objects.
Now what I'm guessing that you want to do is to call two functions that should be called in a specific order, and there are several ways to do this, and it actually boils down to, what kind of class you have. Lets say you have an object of the type Person then you might want to call different methods on that person from somewhere else:
$john = new Person();
$john->tryToWakeUp();
if($john->isAwake) {
$john->brushTeeth();
} else {
echo "John is still sleeping!";
}
On the other hand you might have an object of the type Engine which might want to do several stuff internally for certain actions, like start:
class Engine {
public function start() {
$this->checkFuel();
if($this->hasFuel()) {
try {
$this->initializeSomethingThatHasToDoWithEngineStartUp();
} catch (EngineException $ee) {
$this->engineState = BAD_ENGINE;
Logger::log("Engine did not start");
}
}
}
}
I'd recommend you to read up on object oriented design and play around with it before you try to convert all of your business rules, because It's likely that half way through you'll realize that you've designed everything wrong. Object Oriented Design is not easy, but it does make sense EDIT:( It should make sense ).
This is actually an interesting question, and there's an easy (but ugly) fix to it (see below).
So I'm asking if there's a better way to do it.
What I'd like to do is making an object constructor return something else rather than a new instance.
Here's an example of what I'm trying to achieve:
$GLOBALS['object_cache']=array();
class Test {
public function __construct($id=0){
if(isset( $GLOBALS['object_cache'][$id] ))
return $GLOBALS['object_cache'][$id];
$GLOBALS['object_cache'][$id]=$this;
}
}
$t0=new Test(0);
$t1=new Test(1);
$t01=new Test(0);
// modifying $t01 would presumably also modify $t0
The easy (but ugly?) fix:
$GLOBALS['object_cache']=array();
class Test {
public static function create($id=0){
if(isset( $GLOBALS['object_cache'][$id] ))
return $GLOBALS['object_cache'][$id];
$new=new Test();
$GLOBALS['object_cache'][$id]=$new;
return $new;
}
}
$t0=Test::create(0);
$t1=Test::create(1);
$t01=Test::create(0);
// modifying $t01 would presumably also modify $t0
What do you guys think? Example 1 doesn't work, by the way; it returns a new instance regardless of the return statement.
So am I missing something, or is the better way the second one?
PS: No need stating the obvious about patterns (factory/singleton)...
Omg. Constructor cannot return anything.
It is called factory method pattern http://en.wikipedia.org/wiki/Factory_method_pattern and it is a common practice to instantiate objects.
ps: Store the instances in static class variable and second solution will not be so weird like now.
You could also use a procedural version:
class Test {
function __construct($i) {}
}
function Test($i) {
static $cache;
if (isset($cache[$i])) {
return $cache[$i];
}
else {
return $cache[$i] = new Test($i);
}
}
It's slightly nicer on the eyes, and allows for e.g. instant fluent Test(1)->do()->else() calls.
Basically what you're trying to do is implementing a Singleton pattern combined with a Factory method pattern. Anyone should be able to tell how it works if you document it in your technical documentation (and in your comments), so the first way can be used.
The second solution actually seems less obvious to me.