10

Possibly Related:
Why don't PHP attributes allow functions?

Pardon me if this has been asked before, but why can you not have something like the following:

class foo {

 require_once 'defines.php';

 private $_server = DB_SERVER;
 private $_username = DB_USERNAME;
 private $_password = DB_PASSWORD;
 private $_database = DB_NAME;
 public  $debug = false;
 public $_conn;

 function __construct() {                          
    $connection = @mysqli_connect($this->_server, $this->_username, $this->_password, $this->_database);
 }

 ...

}

Cheers,

EDIT: Looking to find out why this behaviour exists and why its not possible. How come the votes to close?

EDIT2 : Would also like to re-open this

Community
  • 1
  • 1
barfoon
  • 27,481
  • 26
  • 92
  • 138
  • 1
    Related: [Why don't PHP attributes allow functions?](http://stackoverflow.com/questions/3960323/why-dont-php-attributes-allow-functions) – Pekka May 05 '11 at 16:28
  • A blueprint sure, but that blueprint should be able to take static definitions from other sources to avoid repetition should it not? – barfoon May 05 '11 at 16:32
  • You can put it before the class. – dqhendricks May 05 '11 at 16:32
  • @barfoon it could be argued that the `require_once` is a dependency (on the availability of the file, etc.) that doesn't belong in a blueprint. But I see what you mean - this would be handy to have sometimes. – Pekka May 05 '11 at 16:33
  • 2
    or you can simply put regular variables in the include file, and include the file within your constructor. you could even make the filename of the include file an argument for the constructor. – dqhendricks May 05 '11 at 16:34
  • @dqhendricks thanks - that worked. Despite implementing a solution, I'm more looking to find *why this isnt the case – barfoon May 05 '11 at 16:34
  • because that space is reserverved for defining class properties only. you can't simply put any code in that location. when would it run? on construct? then the code would go within construct. you can't do things like $blah = 1 + 2; in that space either because expressions are not allowed. – dqhendricks May 05 '11 at 16:37
  • I would argue I am defining - using elements from earlier definitions to compose the definition of the class.. – barfoon May 05 '11 at 16:39
  • You would basically be able to get rid of the construct method and put a bunch of procedural code at the head of the class which could get ugly. – dqhendricks May 05 '11 at 16:43
  • @dqhendricks but arguably, the interpreter could react to *that* with a syntax error then. I don't really understand why this decision was made either, seeing as `require_*` and `include_*` are language constructs and not functions. – Pekka May 05 '11 at 16:46
  • when looking at a class, you want to be able to cleanly see all of the properties it contains. this is a bad place for global defines anyways. how would coders know where to look for these global defines? in the head of a class is the last place I would look. Are these globals used by other classes? if so perhaps they should be placed in a higher level location. – dqhendricks May 05 '11 at 16:47
  • Related Bug report #1: http://bugs.php.net/bug.php?id=27569 – Pekka May 05 '11 at 16:47
  • @Pekka you will see that that bug was marked "not a bug". works as expected. – dqhendricks May 05 '11 at 16:49
  • 1
    Relate Bug report #2: http://bugs.php.net/bug.php?id=11835 money quote from Jan, a PHP internal: `include is not allowed here` :| – Pekka May 05 '11 at 16:49
  • 2
    My main point is, if it doesn't work, there are reaasons for it, and perhaps you are attacking the problem wrong. there is most likely an easier more intuitive way of handling the problem. – dqhendricks May 05 '11 at 16:50
  • 2
    I didn't mean for this to get closed as a dupe - I cast my vote too quickly, it really isn't one. Voting to reopen - although I doubt whether you will find a definitive answer. – Pekka May 05 '11 at 16:50
  • @Pekka in your bug link i think tbiegacz put it best. why not just make a base class with these definitions and has all classes who need them extend that base class? – dqhendricks May 05 '11 at 16:52
  • @dqhendricks It was what I suggested in my answer as well, but that doesn't feel like good OOP practice at all to me. Inheritances should be meaningful IMO, they shouldn't act as substitutes to `include()` – Pekka May 05 '11 at 16:53
  • 2
    The main thing is, you cannot do it. That will not change. As to why, there are probably many great reasons why, as a bunch were mentioned. As to my take, because the top of a class is meant for variable declarations. A require statement could not rightfully include variable declarations, and why would you want that? If you need a file / code to be included, do it in the constructor or a property of the class. You can argue about it all day, in the end it won't change, as I doubt many of the people here can speak for the PHP coders. – Jim May 05 '11 at 16:57
  • @Pekka if they all need the same variable definitions, then they are most likely related in a menaingful way. OOP TEMPLATE pattern does basically this exact thing. – dqhendricks May 05 '11 at 16:59
  • @dqhendricks fair enough, good point. – Pekka May 05 '11 at 16:59
  • @Pekka: Good link http://bugs.php.net/bug.php?id=11835 if you read the last comment it gives something that may be more of what the OP is looking for, not sure as no intent or example of `defines.php` was really given. @OP, You may want to look into extending the class and have a main class if you plan on using this a lot. I know you were not looking for solutions, but oh well :) – Jim May 05 '11 at 17:10
  • How is this a duplicate of "Why don't PHP attributes allow functions?"? `require` _is not a function_. – Lightness Races in Orbit May 05 '11 at 17:12
  • I think that this is an interesting question, but ultimately subjective. It _may_ be "not a real question". – Lightness Races in Orbit May 05 '11 at 17:13

2 Answers2

5

It was possible to require and include files both within function scope and at global scope, before Classes were added to PHP.

This is only a guess — I'm not sure what else we could do other than for the language designers to come and tell us their story — but I imagine it was believed that no benefit would be gained from adding this functionality to the "new scope" invented by the addition of Classes, especially considering the complexity added to the back-end in order to support it.

It's also not entirely clear what the scoping rules would be for any declarations made inside the required file.

In conclusion, I think you're asking the wrong question. Instead of "why isn't this supported?" it's more a case of "why should it be supported?".

I hope that this helps in some small way.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • The `class` scope is neither `function`, nor `global` scope. Its possible to use include-statements today, as it were before PHP implements classes. Nothing changed, except that a new concept arrived. – KingCrunch May 05 '11 at 17:29
  • @KingCrunch: That's what I said. I have edited my answer in the hopes of making it more clear. – Lightness Races in Orbit May 05 '11 at 18:10
2

It is because in the class definition "real" code is not allowed at all, only definitions for properties, methods and constants are allowed. You can put your include-statements into "main-scope" (procedural), functions and methods, like every other code.

class A {
  var $a = 1 + 1; // Parse error: unexpected '+'
}

However, as far as I know its not supported in any language. For example java uses static code blocks for this

class A {
  private static int a = 0;
  static {
    a = 1+1;
  }
}

In PHP just put your "static" code after the class itself.

class A {}
/* static */ {
  // do something
}

Its not possible to access private or protected static members this way.

KingCrunch
  • 128,817
  • 21
  • 151
  • 173
  • Understandable. I guess at that point the definition of "real code" comes into contention. The argument is that defines and static constants should be eligible and don't contain any additional logic so to speak. – barfoon May 05 '11 at 17:31
  • 3
    Although a _very_ loose analogy, C++'s `#include` (as a preprocessor directive) can go anywhere, including inside a class definition. I realise of course that some of the included file's contents may not be valid there. – Lightness Races in Orbit May 05 '11 at 18:12