A
A
Andrey Makarov2016-04-18 02:51:09
PHP
Andrey Makarov, 2016-04-18 02:51:09

How to initialize properties of type Object in PHP traits or is it possible to register multiple __construct methods in a queue?

I tried to ask a question on stackoverflow, but, apparently, because of clumsy English, they didn’t understand me there. I need to initialize a trait property as an instance of a neighbor class.

trait FilterTrait {
    protected $_filter = new Filter(); // Нельзя использовать как дефолтное значение

    public function __construct () { // Перезапишется в используемом классе
        $this->_filter = new Filter();
    }

    public function SetFilter ($arFilter) {
        $this->_filter->Set($arFilter);
    }

    public function CleanFilter () {
        $this->_filter->CLean();
    }

    public function GetFilter () {
        return $this->_filter->Get();
    }
    ...
}

I do not want the child class to help in the work of the used trait, and generally know something about its structure, like this:
class Select extends Query {
    use TablesListTrait,
        FieldsListTrait,
        FilterTrait,
        HavingTrait,
        SortTrait,
        LimitTrait,
        GroupTrait;

    function __construct () {
        $this->_tablesList = new TablesList();
        $this->_fieldsList = new FieldsList();
        $this->_filter = new Filter();
        ...
    }
    ...
}

And I also don’t want to initialize with each method call
trait FilterTrait {
    protected $_filter;

    public function InitializeFilter () {
        if (is_null($this->_filter)) {
            $this->_filter = new Filter();
        }
    }

    public function SetFilter ($arFilter) {
        $this->InitializeFilter();
        $this->_filter->Set($arFilter);
    }

    public function CleanFilter () {
        $this->InitializeFilter();
        $this->_filter->CLean();
    }

    public function GetFilter () {
        $this->InitializeFilter();
        return $this->_filter->Get();
    }
}

You can, of course, stir up method reloading, but this is not much better.
I found information that in version 5.6 this spelling is supported
class Foo {
    protected $bar = new Baz();
}

I didn't check it, but still, most hostings currently stand at 5.3 - 5.4, and it's still difficult to use these chips. In addition, I also want to implement the registration of mnemonics for calling trait methods from parameters passed to child classes. If there was some magic method that registers multiple __construct functions, this would help me:
trait Actions {
    protected $_arActions = array();

    public function RegisterActions ($arActions) {
        $this->_arActions = array_merge($this->_arActions, $arActions);
    }

    public function ResetParameters ($arParameters) {
        foreach ($arParameters as $mnemonic => $actionParameters) {
            if (isset($this->_arActions[$mnemonic])) {
                $action = $this->_arActions[$mnemonic];
                $this->$action($actionParameters);
            }
        }
    }
}

trait FilterTrait {
    use Actions;
    
    public function __onUse () {
        $arActions = array(
            "filter" => "SetFilter"
        );
        $this->RegisterActions($arActions);
    }
    
    public function SetFilter ($arFilter) {...}
}

class Select extends Query {
    use TablesListTrait,
        FieldsListTrait,
        FilterTrait,
        HavingTrait,
        SortTrait,
        LimitTrait,
        GroupTrait;
    
    public function __construct ($arParams) {
        $this->ResetParameters($arParams);
    }
}

...
$arSelectParams = array(
    "table" => "products",
    "fields" => array(
        "id",
        "name",
        "price"
    ),
    "filter" => array(
        "id" => 5,
        "<=price" => 1000
    ),
    "sort" => array(
        "price" => "asc"
    )
);
$query = new Select($arSelectParams);

Is there any option to do something similar now or, if not, is the concept of something similar expected in the future, somewhere in the seventh version?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
I
index0h, 2016-04-18
@index0h

The default object concept is a lousy idea. Connection to a DB you for example as in property of a class will make (not object)?
Traits are a rather dangerous thing that extends the functionality of your classes. You want her to live her own life in the context of each class, this is not right, you don’t have Golang here)).
Regarding your example of working with the database: you don't need traits here, from the word "absolutely")). Extend your Query with whatever methods you want to shove into traits. You don't need the Select class either, add its functionality as a method to Query. If I understand correctly Query is a stateful object, which should be able to create SQL code as a result, so add the getSQL () method to it.
Pay attention to SQL injection protection. What happens if you call your Select like this:

<?php

$query = new Select(
    [
        'table'  => "1;DROP TABLE products;",
        'fields' => [],
    ]
);

Generally speaking: if the goal is to learn - go for it, if you do it - use Doctrine2, you should not waste time on crafts that will be 99.99% worse than existing analogues.
I highly recommend you, read PSR-2
I almost forgot:
In the class that connects the trait, either directly or by calling a method from the trait.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question