3

Most of my recent experience is in Java, and I was quite surprised the following PHP code did not throw a compile-time error:

<?php
class Test { }
$a = new Test('foo', true, false, 18320);

Is there any way to force this to be a syntax or compile-time error?

Adam Monsen
  • 9,054
  • 6
  • 53
  • 82

3 Answers3

4

PHP, being a very loosely-typed dynamic language, always allows you to pass any set and any number of arguments to a function or constructor call without error, unless type hints in their definitions aren't met by the arguments passed; for instance, this won't work:

class Test {
    public function __construct(array $a, $b, $c, $d) {}
}

// Catchable fatal error: Argument 1 passed to Test::__construct()
// must be an array, string given
$a = new Test('foo', true, false, 18320);

But even then, that's not going to cause a syntax error either — that's a fatal error at runtime.

The closest you can get is to enforce the checks at runtime within the function or method bodies.

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
  • Thanks! What had me puzzled was that I didn't define a constructor, so I was hoping for a "Call to undefined method". But I forgot about the default constructor. – Adam Monsen Nov 28 '11 at 23:47
  • 1
    @Adam Monsen: Ah, here's another stumper for you: there's no such thing as a default constructor in PHP! If a class without any constructors is instantiated, the only thing that happens is memory allocation. No constructor gets called! More about this here: http://stackoverflow.com/questions/4650542/why-am-i-getting-fatal-error-when-calling-a-parents-constructor/4650617#4650617 – BoltClock Nov 28 '11 at 23:54
  • @Adam Monsen: But since objects in PHP are almost as dynamic and extensible as in JavaScript, you'll rarely run into problems anyway. The only time you'll find yourself in a hitch is in the situation described in that question. I just found this curiosity worth mentioning :) – BoltClock Nov 28 '11 at 23:55
  • Huh! No default constructor. I guess the language authors wanted `new` to work even without a constructor, and then I guess the loose-typing is similar behavior to any other function/method. – Adam Monsen Nov 29 '11 at 00:03
  • I suppose this is why you can even omit the parentheses with `new`, so you get something like `$a = new Test;` – BoltClock Nov 29 '11 at 00:08
1

From memory, I don't think that would even throw a warning at runtime. The converse raises an error, thankfully! - supplying too few arguments.

There is a way to raise an error however: write a constructor which checks the argument count. You can use func_num_args() and func_get_args() for this. If you needed it several times, you could put it in a parent class and extend, though of course that would preclude any other inheritence hierarchy you may need.

Edit: a random inspiration made me do a search for "php lint". And guess what I found? Not tried it, though :)

halfer
  • 19,824
  • 17
  • 99
  • 186
1

As BoltClock said, you can't...

But if you really want to check this at runtime, you can explicitly declare a default constructor, taking no arguments, and use func_num_args to check the number of effectively passed arguments, raising an exception if applicable.

class Test
{
    public function __construct()
    {
        if( func_num_args() > 0 )
        {
            /* Error management */
        }
    }
}
Macmade
  • 52,708
  • 13
  • 106
  • 123