Php несколько конструкторов класса

Обновлено: 28.03.2024

PHP позволяет использовать только один конструктор в классе, что довольно раздражительно. Вероятно, мы никогда не получим нормальную возможность перегрузки конструкторов в PHP, но кое-что сделать все же можно. Для примера возьмем простой класс, хранящий значение времени. Какой способ создания нового объекта лучше:


Правильным ответом будет «в зависимости от ситуации». Оба способа могут являются корректным с точки зрения полученного результата. Реализуем поддержку обоих способов:

Выглядит отвратительно. Кроме того поддержка класса будет затруднена. Что произойдет, если нам понадобится добавить еще несколько способов создания экземпляров класса Time?


Также, вероятно, стоит добавить поддержку числовых строк (защита от дурака не помешает):

Реорганизация кода с использованием именованных конструкторов

Добавим несколько статичных методов для инициализации Time. Это позволит нам избавиться от условий в коде (что зачастую является хорошей идеей).


Теперь каждый метод удовлетворяет принцип Единой ответственности. Публичный интерфейс прост и понятен. Вроде бы закончили? Меня по прежнему беспокоит конструктор, он использует внутреннее представление объекта, что затрудняет изменение интерфейса. Положим, по какой-то причине нам необходимо хранить объединенное значение времени в строковом формате, а не по отдельности, как раньше:


Это некрасиво: нам приходится разбивать строку, чтобы потом заново соединить её в конструкторе. А нужен ли нам конструктор для конструктора?

Мы встроили тебе конструктор в конструктор.

Нет, обойдемся без него. Реорганизуем работу методов, для работы с внутренним представлением напрямую, а конструктор сделаем приватным:

Единообразие языковых конструкций

Наш код стал чище, мы обзавелись несколькими полезными методами инициализации нового объекта. Но как часто случается с хорошими конструктивными решениями — ранее скрытые изъяны выбираются на поверхность. Взгляните на пример использования наших методов:

  • fromString — использует в названии детали реализации PHP;
  • fromValues ​​- использует своего рода общий термин программирования;
  • fromMinutesSinceMidnight - использует обозначения из предметной области.
  • fromString => fromTime
  • fromValues => fromHoursAndMinutes


Возможно, такой подход будет не всегда оправдан, и такой уровень детализации излишен. Мы можем использовать любой из вариантов, но самое важное то, что именованные конструкторы дают нам возможность выбирать.

Часть 2: Когда использовать статические методы

Basic class definitions begin with the keyword class , followed by a class name, followed by a pair of curly braces which enclose the definitions of the properties and methods belonging to the class.

The class name can be any valid label, provided it is not a PHP reserved word. A valid class name starts with a letter or underscore, followed by any number of letters, numbers, or underscores. As a regular expression, it would be expressed thus: ^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$ .

A class may contain its own constants, variables (called "properties"), and functions (called "methods").

class SimpleClass
// property declaration
public $var = 'a default value' ;

// method declaration
public function displayVar () echo $this -> var ;
>
>
?>

The pseudo-variable $this is available when a method is called from within an object context. $this is the value of the calling object.

Calling a non-static method statically throws an Error . Prior to PHP 8.0.0, this would generate a deprecation notice, and $this would be undefined.

class A
function foo ()
if (isset( $this )) echo '$this is defined (' ;
echo get_class ( $this );
echo ")\n" ;
> else echo "\$this is not defined.\n" ;
>
>
>

$a = new A ();
$a -> foo ();

$b = new B ();
$b -> bar ();

Output of the above example in PHP 7:

Output of the above example in PHP 8:

To create an instance of a class, the new keyword must be used. An object will always be created unless the object has a constructor defined that throws an exception on error. Classes should be defined before instantiation (and in some cases this is a requirement).

If a string containing the name of a class is used with new , a new instance of that class will be created. If the class is in a namespace, its fully qualified name must be used when doing this.

Note:

If there are no arguments to be passed to the class's constructor, parentheses after the class name may be omitted.

// This can also be done with a variable:
$className = 'SimpleClass' ;
$instance = new $className (); // new SimpleClass()
?>

As of PHP 8.0.0, using new with arbitrary expressions is supported. This allows more complex instantiation if the expression produces a string . The expressions must be wrapped in parentheses.

In the given example we show multiple examples of valid arbitrary expressions that produce a class name. This shows a call to a function, string concatenation, and the ::class constant.

class ClassA extends \ stdClass <>
class ClassB extends \ stdClass <>
class ClassC extends ClassB <>
class ClassD extends ClassA <>

function getSomeClass (): string
return 'ClassA' ;
>

var_dump (new ( getSomeClass ()));
var_dump (new ( 'Class' . 'B' ));
var_dump (new ( 'Class' . 'C' ));
var_dump (new ( ClassD ::class));
?>

Output of the above example in PHP 8:

In the class context, it is possible to create a new object by new self and new parent .

When assigning an already created instance of a class to a new variable, the new variable will access the same instance as the object that was assigned. This behaviour is the same when passing instances to a function. A copy of an already created object can be made by cloning it.

$instance = new SimpleClass ();

$assigned = $instance ;
$reference =& $instance ;

$instance -> var = '$assigned will have this value' ;

$instance = null ; // $instance and $reference become null

var_dump ( $instance );
var_dump ( $reference );
var_dump ( $assigned );
?>

The above example will output:

It's possible to create instances of an object in a couple of ways:

class Test
static public function getNew ()
return new static;
>
>

class Child extends Test
<>

$obj1 = new Test ();
$obj2 = new $obj1 ;
var_dump ( $obj1 !== $obj2 );

$obj3 = Test :: getNew ();
var_dump ( $obj3 instanceof Test );

$obj4 = Child :: getNew ();
var_dump ( $obj4 instanceof Child );
?>

The above example will output:

It is possible to access a member of a newly created object in a single expression:

The above example will output something similar to:

Note: Prior to PHP 7.1, the arguments are not evaluated if there is no constructor function defined.

Properties and methods

Class properties and methods live in separate "namespaces", so it is possible to have a property and a method with the same name. Referring to both a property and a method has the same notation, and whether a property will be accessed or a method will be called, solely depends on the context, i.e. whether the usage is a variable access or a function call.

public function bar () return 'method' ;
>
>

$obj = new Foo ();
echo $obj -> bar , PHP_EOL , $obj -> bar (), PHP_EOL ;

The above example will output:

That means that calling an anonymous function which has been assigned to a property is not directly possible. Instead the property has to be assigned to a variable first, for instance. It is possible to call such a property directly by enclosing it in parentheses.

public function __construct () $this -> bar = function() return 42 ;
>;
>
>

echo ( $obj -> bar )(), PHP_EOL ;

The above example will output:

extends

A class can inherit the constants, methods, and properties of another class by using the keyword extends in the class declaration. It is not possible to extend multiple classes; a class can only inherit from one base class.

The inherited constants, methods, and properties can be overridden by redeclaring them with the same name defined in the parent class. However, if the parent class has defined a method or constant as final, they may not be overridden. It is possible to access the overridden methods or static properties by referencing them with parent::.

Note: As of PHP 8.1.0, constants may be declared as final.

class ExtendClass extends SimpleClass
// Redefine the parent method
function displayVar ()
echo "Extending class\n" ;
parent :: displayVar ();
>
>

$extended = new ExtendClass ();
$extended -> displayVar ();
?>

The above example will output:

Signature compatibility rules

When overriding a method, its signature must be compatible with the parent method. Otherwise, a fatal error is emitted, or, prior to PHP 8.0.0, an E_WARNING level error is generated. A signature is compatible if it respects the variance rules, makes a mandatory parameter optional, and if any new parameters are optional. This is known as the Liskov Substitution Principle, or LSP for short. The constructor, and private methods are exempt from these signature compatibility rules, and thus won't emit a fatal error in case of a signature mismatch.

class Base
public function foo ( int $a ) echo "Valid\n" ;
>
>

class Extend1 extends Base
function foo ( int $a = 5 )
parent :: foo ( $a );
>
>

class Extend2 extends Base
function foo ( int $a , $b = 5 )
parent :: foo ( $a );
>
>

$extended1 = new Extend1 ();
$extended1 -> foo ();
$extended2 = new Extend2 ();
$extended2 -> foo ( 1 );

The above example will output:

The following examples demonstrate that a child method which removes a parameter, or makes an optional parameter mandatory, is not compatible with the parent method.

class Base
public function foo ( int $a = 5 ) echo "Valid\n" ;
>
>

class Extend extends Base
function foo ()
parent :: foo ( 1 );
>
>

Output of the above example in PHP 8 is similar to:

class Base
public function foo ( int $a = 5 ) echo "Valid\n" ;
>
>

class Extend extends Base
function foo ( int $a )
parent :: foo ( $a );
>
>

Output of the above example in PHP 8 is similar to:

Renaming a method's parameter in a child class is not a signature incompatibility. However, this is discouraged as it will result in a runtime Error if named arguments are used.

class A public function test ( $foo , $bar ) <>
>

class B extends A public function test ( $a , $b ) <>
>

// Pass parameters according to A::test() contract
$obj -> test ( foo : "foo" , bar : "bar" ); // ERROR!

The above example will output something similar to:

::class

The class keyword is also used for class name resolution. To obtain the fully qualified name of a class ClassName use ClassName::class . This is particularly useful with namespaced classes.

The above example will output:

Note:

The class name resolution using ::class is a compile time transformation. That means at the time the class name string is created no autoloading has happened yet. As a consequence, class names are expanded even if the class does not exist. No error is issued in that case.

The above example will output:

As of PHP 8.0.0, the ::class constant may also be used on objects. This resolution happens at runtime, not compile time. Its effect is the same as calling get_class() on the object.

The above example will output:

Nullsafe methods and properties

As of PHP 8.0.0, properties and methods may also be accessed with the "nullsafe" operator instead: ?-> . The nullsafe operator works the same as property or method access as above, except that if the object being dereferenced is null then null will be returned rather than an exception thrown. If the dereference is part of a chain, the rest of the chain is skipped.

The effect is similar to wrapping each access in an is_null() check first, but more compact.

// As of PHP 8.0.0, this line:
$result = $repository ?-> getUser ( 5 )?-> name ;

// Is equivalent to the following code block:
if ( is_null ( $repository )) $result = null ;
> else $user = $repository -> getUser ( 5 );
if ( is_null ( $user )) $result = null ;
> else $result = $user -> name ;
>
>
?>

Note:

The nullsafe operator is best used when null is considered a valid and expected possible value for a property or method return. For indicating an error, a thrown exception is preferable.

User Contributed Notes 13 notes

I was confused at first about object assignment, because it's not quite the same as normal assignment or assignment by reference. But I think I've figured out what's going on.

First, think of variables in PHP as data slots. Each one is a name that points to a data slot that can hold a value that is one of the basic data types: a number, a string, a boolean, etc. When you create a reference, you are making a second name that points at the same data slot. When you assign one variable to another, you are copying the contents of one data slot to another data slot.

Now, the trick is that object instances are not like the basic data types. They cannot be held in the data slots directly. Instead, an object's "handle" goes in the data slot. This is an identifier that points at one particular instance of an obect. So, the object handle, although not directly visible to the programmer, is one of the basic datatypes.

What makes this tricky is that when you take a variable which holds an object handle, and you assign it to another variable, that other variable gets a copy of the same object handle. This means that both variables can change the state of the same object instance. But they are not references, so if one of the variables is assigned a new value, it does not affect the other variable.

// Assignment of an object
Class Object public $foo = "bar" ;
>;

$objectVar = new Object ();
$reference =& $objectVar ;
$assignment = $objectVar

//
// $objectVar --->+---------+
// |(handle1)----+
// $reference --->+---------+ |
// |
// +---------+ |
// $assignment -->|(handle1)----+
// +---------+ |
// |
// v
// Object(1):foo="bar"
//
?>

$assignment has a different data slot from $objectVar, but its data slot holds a handle to the same object. This makes it behave in some ways like a reference. If you use the variable $objectVar to change the state of the Object instance, those changes also show up under $assignment, because it is pointing at that same Object instance.

$objectVar -> foo = "qux" ;
print_r ( $objectVar );
print_r ( $reference );
print_r ( $assignment );

//
// $objectVar --->+---------+
// |(handle1)----+
// $reference --->+---------+ |
// |
// +---------+ |
// $assignment -->|(handle1)----+
// +---------+ |
// |
// v
// Object(1):foo="qux"
//
?>

But it is not exactly the same as a reference. If you null out $objectVar, you replace the handle in its data slot with NULL. This means that $reference, which points at the same data slot, will also be NULL. But $assignment, which is a different data slot, will still hold its copy of the handle to the Object instance, so it will not be NULL.

$objectVar = null ;
print_r ( $objectVar );
print_r ( $reference );
print_r ( $assignment );

I need to have a class constructor in PHP call its parent's parent's (grandparent?) constructor without calling the parent constructor.

I know this is a bizarre thing to do and I'm attempting to find a means that doesn't smell bad but nonetheless, I'm curious if it's possible.

The Grampa constructor sets properties for itself that are inherited by its children. Papa does some stuff in it's constructor that will mess up Kiddo. So I need the call to Grandpa constructor to set properties for Kiddo during construction.

@MitMaro. I agree and I actually solved my actual problem by creating an intermediate class that extended Grandpa. Then both Papa and Kiddo extended that class. Kiddo required some intermediate functionality of Papa but didn't like it's constructor so the class has that additional functionality and both extend it.

15 Answers 15

The ugly workaround would be to pass a boolean param to Papa indicating that you do not wish to parse the code contained in it's constructor. i.e:

good workaround, but it is not acceptable if the parent class comes from some external library wish you with to extend. I like the too much php answer below.

That's actually quite clever. In my implementation I do if($bypass) return; & can position it so some important stuff gets done before the bypass.

You must use Grandpa::__construct() , there's no other shortcut for it. Also, this ruins the encapsulation of the Papa class - when reading or working on Papa , it should be safe to assume that the __construct() method will be called during construction, but the Kiddo class does not do this.

Can't understand how. Declaring __construct as static results in the following error for me "Fatal error: Constructor Grandpa::__construct() cannot be static" under PHP5.3

When I tried it, I didn't declare it as static. I created the class structure normally but instead of calling parent::__construct(), I called Grandpa::__construct() and it worked. I doesn't seem right to me either but this whole question got kinda weird.

Agreed. I use this all the time - you can call a class by it's name, not just via the magic names of parent or self . I have been known to go three or four classes deep. In fact, I've started referring to my base class by it's name rather than using parent, that way I'm sure I'm getting the right object, always.

@SparK If you are using PHP 5.3.0 or later, Late Static Bindings would most likely solve your use case.

Personally I wouldn't choose to do this as it means Papa's contractor won't get called at all. I'd go with something like cballou's approach (i.e. of passing an argument to Papa's constructor and having it invoke it's parents constructor or not based on that).

The situation we are in here is in such a way that we need to skip the parent's logic and in most of the cases we can't change the grandparent or the parent classes. I believe this is the best way to do it as there are changes made only in the child. The only issue is that it might throw an E_STRICT notice link, it didn't for me though when I tested it.

This is an interesting solution, however, if you really don't need the logic of the parent's constructor, are you sure that you are really making a subsclass of a parent?

This is the correct answer. While it may seem silly to inherit Papa but you want to call the GrandPa constructor without Papa, I've found it useful to be do. I want to keep the hierarchy, but I need to do a clean Kiddo constructor that doesn't have anything to do with Papa, but still want the benefits of using what's going on in GrandPa's constructor. Maybe Papa is doing a bunch of junk in the constructor that isn't needed or wanted by Kiddo, but it still has useful components.

Beautiful solution using Reflection .

I ended up coming up with an alternative solution that solved the problem.

  • I created an intermediate class that extended Grandpa.
  • Then both Papa and Kiddo extended that class.
  • Kiddo required some intermediate functionality of Papa but didn't like it's constructor so the class has that additional functionality and both extend it.

I've upvoted the other two answers that provided valid yet ugly solutions for an uglier question:)

I think the better idea here is to break the functionality you are trying to use out of the constructed and into a protected method. Then you can call that method from a constructor selectively

This does not answer the exact question you've phrased. This happens if the real world muddies up something which should be clear and confined. It's a pity for this question.

Another option that doesn't use a flag and might work in your situation:

I agree with "too much php", try this:

I got the result as expected:

This is a feature not a bug, check this for your reference:

It is just the way it works. If it sees it is coming from the right context this call version does not enforce a static call.

Instead it will simply keep $this and be happy with it.

parent::method() works in the same way, you don't have to define the method as static but it can be called in the same context. Try this out for more interesting:

It also works as expected:

But if you try to initialize a new Papa, you will get an E_STRICT error:

Strict standards: Non-static method Kiddo::hello() should not be called statically, assuming $this from incompatible context

You can use instanceof to determine if you can call a Children::method() in a parent method:

Just remember that parent is only a shortcut to whatever first parent that implemented the method… Thus from a descendant calling AscendantName::method works and from an ascendant calling static::method will always call the latest generation that implemented the method. And you may check not to call yourself using (get_class($this)==__CLASS__?'Healthy people dont\'t call themself…':'Calling latest') if you'd like parents to call kid methods (seems strange but might be usefull combined with private function and __call magic function )…

There's an easier solution for this, but it requires that you know exactly how much inheritance your current class has gone through. Fortunately, get_parent_class()'s arguments allow your class array member to be the class name as a string as well as an instance itself.

Bear in mind that this also inherently relies on calling a class' __construct() method statically, though within the instanced scope of an inheriting object the difference in this particular case is negligible (ah, PHP).

Consider the following:

Again, this isn't a viable solution for a situation where you have no idea how much inheritance has taken place, due to the limitations of debug_backtrace(), but in controlled circumstances, it works as intended.

You can't put two __construct functions with unique argument signatures in a PHP class. I'd like to do this:

What is the best way to do this in PHP?

In my case, I want to have a protected constructor that has one less required argument than the public one - for the sake of standardizing its factory method. I need a class to be able to create copies of itself, and the factory is in an abstract class, but the concrete classes may have constructors that require a second argument - which the abstract class has no idea of.

Not really something of value but something I stumbled upon some time ago: the class DatePeriod in date_c.php has multiple constructors. But I do not know what PHP does internally with it.

25 Answers 25

I'd probably do something like this:

Then if i want a Student where i know the ID:

Or if i have an array of the db row:

Technically you're not building multiple constructors, just static helper methods, but you get to avoid a lot of spaghetti code in the constructor this way.

@gpilotino, overkill because you'd need yet another class, (or method) that would basically just consist of a switch/case decision tree, in the end just doing what I already did in two methods. factories are more useful in situations where you can't easily define the exact constraints of a problem, like creating form elements. but then, that's just my opinion and for the record; I don't claim it to be fact.

And could not we also make __construct() private, to prevent someone from ocassionally allocating a "non-ininitialized" instance?

@mlvljr: you could, but i'd suggest making it protected instead of private. otherwise you'll most likely run into trouble if you're ever going to extend your class.

Note from PHP 5.3 on you should probably use new static() rather than new self() , since new static() will work more sanely in child classes.

The solution of Kris is really nice, but I prefer a mix of factory and fluent style:

+1; This type of solution can yield really nice code. Although I would opt for setLastName (or rather all setters) in this solution to return $this instead of having effectively two setters on the same property.

How does providing a static create method differ from just using the constructor in the same way? $student = new Student()->setFirstName("John")->setLastName("Doe");

There's an important problem with that code: you can't ensure that the instance is valid (that's why there are constructors) and usually immutable classes are preferable.

This is most clean code which is seen for such question, and it can cleaner by use return new self() in the create() method

PHP is a dynamic language, so you can't overload methods. You have to check the types of your argument like this:

If you create your constructors as you would in a statically typed language it will become spaghetti code. But you don't. Creating two constructors with one parameter and no type (no type == any type) for that parameter will not work in any language, anyway (e.g. it won't work to have two Java constructors with one Object parameter each in one class, either).

What i meant is that you're doing different things in the same scope based on outside influence, It's not a bad solution (since it will work), just not the one I would choose.

A language being "dynamic" does not exclude the possibility for function/constructor overloads. It does not even exclude static typing. And even if, there would still be the possibility of allowing overloads based purely on argument-count. Please don't use "dynamic" as an excuse for things.

I like this as a way of simplifying the code for the user of the class, and it accomplishes what the OP wanted. It won't be spaghetti code if you make two functions (like Kris' answer) and just call the functions appropriately in the constructor. The code for checking arguments is likely not that complicated. This assumes of course that there is some way to distinguish the arguments from each other as in this case.

Now $paramters will be an array with the values 'One', 'Two', 3.

will give you the number of parameters to the function.

How does this solve the problem of knowing what was passed? I think it complicates the issue as instead of having to check the type of the parameter, you have to check if x parameter is set and then the type of it.

It doesn't solve the problem to know what type was passed, but it's the way to go for "multiple constructors" in PHP. Type checking is up to OP to do.

As has already been shown here, there are many ways of declaring multiple constructors in PHP, but none of them are the correct way of doing so (since PHP technically doesn't allow it). But it doesn't stop us from hacking this functionality. Here's another example:

Hope this helps. :)

Of course this won't work with JannieT's original question since her desired constructors were __construct($id) and __construct($row_from_database) . Both have one argument, presumably either an int for the first and an array or object for the second. The appending of a number could, of course, be extended to be some sort of argument signature in C++ style (i.e., __construct_i($intArg) and __construct_a($arrayArg) ).

+1: I kinda like this, but extended with type information and without the double underscore prefixes in the nested ctors. Thanks for the inspiration!

You even could add reflection to your example code to apply type checks on parameters of each function of the class that starts with __construct and match the appropriate constructor that way

You could do something like this:

As of version 5.4, PHP supports traits. This is not exactly what you are looking for, but a simplistic trait based approach would be:

We end up with two classes, one for each constructor, which is a bit counter-productive. To maintain some sanity, I'll throw in a factory:

So, it all comes down to this:

It's a horribly verbose approach, but it can be extremely convenient.

Here is an elegant way to do it. Create trait that will enable multiple constructors given the number of parameters. You would simply add the number of parameters to the function name "__construct". So one parameter will be "__construct1", two "__construct2". etc.

Another option is to use default arguments in the constructor like this

This means you'll need to instantiate with a row like this: $student = new Student($row['id'], $row) but keeps your constructor nice and clean.

On the other hand, if you want to make use of polymorphism then you can create two classes like so:

now you have two classes with different names but the same functionality just a different signature on the constructor, sounds like a pretty bad idea to me.

Creating multiple classes to provide different constructors is indeed a bad idea. Classes that extends other classes should extend, meaning they should have added functionality, thats the point of OOP, not this.

as stated in the other comments, as php does not support overloading, usually the "type checking tricks" in constructor are avoided and the factory pattern is used intead

Looks neat. I'm not familiar with factories. In your example, would $myObj be of the type MyClass? What would the two static functions look like that return a constructed instance of $myObj?

You could do something like the following which is really easy and very clean:

why assign func_get_args to a variable and call it again in the next line? would also be better if you only called func_get_args after deciding you need to based on fund_num_args .

This question has already been answered with very smart ways to fulfil the requirement but I am wondering why not take a step back and ask the basic question of why do we need a class with two constructors? If my class needs two constructors then probably the way I am designing my classes needs little more consideration to come up with a design that is cleaner and more testable.

We are trying to mix up how to instantiate a class with the actual class logic.

If a Student object is in a valid state, then does it matter if it was constructed from the row of a DB or data from a web form or a cli request?

Now to answer the question that that may arise here that if we don't add the logic of creating an object from db row, then how do we create an object from the db data, we can simply add another class, call it StudentMapper if you are comfortable with data mapper pattern, in some cases you can use StudentRepository, and if nothing fits your needs you can make a StudentFactory to handle all kinds of object construction tasks.

Bottomline is to keep persistence layer out of our head when we are working on the domain objects.

Как в контроллере приложения создать конструктор? Это нужно, чтобы во всех контроллерах был общий функционал, нужно в этот конструктор поместить, например такой код
$this->test['b'] = 2;
Спасибо.

Простой 7 комментариев

5d16868103cf2669469375.jpg

parent?

Станислав, я если добавляю parent, то он требует параметр $this->route, а если я добавляю параметр, то у меня в базовом контроллере $route не заполнена и отваливаются индексы :(

5d168896f3a15635753535.jpg

Артём Рыженький, А вот нечего инжектить в метод тогда(есть варианты когда это норм, типа как симфони, но это отдельная тема).
Смотри, я сделал так. Это очень криво и написано "за 5минут", но работает.
ps повторюсь что это говонокод и так делать не стоит)


5d168d28611d5922164304.jpg


5d168d5674ee1545268376.jpg

Конструкторы, определенные в классах-родителях не вызываются автоматически, если дочерний класс определяет собственный конструктор. Чтобы вызвать конструктор, объявленный в родительском классе, требуется вызвать parent::__construct() внутри конструктора дочернего класса. Если в дочернем классе не определен конструктор, то он может быть унаследован от родительского класса как обычный метод (если он не был определен как приватный).

если бы всё было так, как я прочитал уже давно в доках, то я бы не писал этот вопрос на полэкрана )))

я если добавляю parent, то он требует параметр $this->route, а если я добавляю параметр, то у меня в базовом контроллере отваливаются индексы в $route :(

индекс controller не найден
индекс action не найден

сори уважаемый, убрал public из public function __construct() и шторм даже сразу автоматом развернул правильную конструкцию с уже заполненными параметрами

а что, с public и без public разве это не одно и тоже?

Артём Рыженький, Уважаемый, внимательнее документацию, и почитайте про принцип постановки Барбары Лисков

Евгений Ромашкан, ну я читал, что если писать без public, то по дефолту - public, так что не наезжайте :)

вот шторм мне развернул правильный варик, когда я набрал function __construct() - без public


вопрос решён, спасибо за участие

на Ваш кстати удалённый вариант шторм ругался, что метод должен быть абстрактным :)

Читайте также: