Динамические трейты

grigori

( ͡° ͜ʖ ͡°)
Команда форума
какие слова из фразы "мы работаем не с классами, мы работаем с объектами" тебе непонятны?
"работа" - исполнение кода в runtime, вызов функций с передачей значений параметров в регистры процессора
трейт - это специализированный подвид класса, это не исполнимый код, в процессор к исполнению попадает объект
что непонятно?

нет термина "переопределение переменной", бывает "переопределение метода", я не понимаю этот диалект - пиши на русском, английском или украинском
 
Последнее редактирование:

StalkerClasses

Новичок
Отказался от этой идеи.
Если нужно что то переделать в трейте - будет еще 1 трейт с наследованием и все. Как понимаю трейты также наследуются.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
Изменение реализации трейта наследованием для изменения сигнатуры и реализации объекта на лету - в этом есть что-то привлекательно извращенное. Опуститься на дно, чтобы увидеть звезды. Насколько глубока кроличья нора? Можно ли сделать приложение еще сложнее в поддержке? Сколько времени получится получать деньги, и портить проект, прежде чем руководство поймет, что происходит?
 

Yoskaldyr

"Спамер"
Партнер клуба
@StalkerClasses
А еще есть AOP с магией в go-aop фреймворке
И тогда твои вопросы будут еще чудеснее :)
 

StalkerClasses

Новичок
Изменение реализации трейта наследованием для изменения сигнатуры и реализации объекта на лету - в этом есть что-то привлекательно извращенное. Опуститься на дно, чтобы увидеть звезды. Насколько глубока кроличья нора? Можно ли сделать приложение еще сложнее в поддержке? Сколько времени получится получать деньги, и портить проект, прежде чем руководство поймет, что происходит?
Вопрос про трейты уже немного не в тему.
В классе есть переменная
pageNumber = 0
Добавляю трейт с переменной pageNumber = 1

Разве трейт не переписывает (переопределят) переменные и функции в классе?
 

StalkerClasses

Новичок
PHP:
<?php
trait SayWorld {
    public $a = 1; // Ошибка
    public function sayHello() {
        echo 'World!';
        echo $this->$a;
    }
}

class MyHelloWorld {
    use SayWorld;
    public $a = 5; // Ошибка
}

$o = new MyHelloWorld();
$o->sayHello();
?>
Я думал что трейт переопределяет переменные и функции.
 

WMix

герр M:)ller
Партнер клуба

прям интересно, чему должно быть равно $a по твоему
PHP:
trait SayWorld {
    public function sayHello() {
        echo 'World!';
        echo $this->getA();
    }
   
    abstract public function getA();
}

class MyHelloWorld {
    use SayWorld;
    private $a = 5;
   
    public function getA(){
        return $this->a;
    }
}

$o = new MyHelloWorld();
$o->sayHello();
 

WMix

герр M:)ller
Партнер клуба
как-то надо закончить эту дискуссию
 

StalkerClasses

Новичок

прям интересно, чему должно быть равно $a по твоему
PHP:
trait SayWorld {
    public function sayHello() {
        echo 'World!';
        echo $this->getA();
    }
  
    abstract public function getA();
}

class MyHelloWorld {
    use SayWorld;
    private $a = 5;
  
    public function getA(){
        return $this->a;
    }
}

$o = new MyHelloWorld();
$o->sayHello();
Видемо так нельзя сделать.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
не, все нормально, просто StalkerClasses нужно примерно 10 раз прочитать фразу в разных контекстах, прежде, чем он ее примет, а не два-три, как большинству, но это не худший, и не безнадежный случай, а нам надо быть готовым писать ответ не один раз, а два-три, переживем
 

StalkerClasses

Новичок
@StalkerClasses смотри, я нашел тебе либу для динамических трейтов: https://github.com/lisachenko/z-engine
Спасибо - изучаю.
Не знаю насколько мне эта тема пригодится в плане дин. трейтов - от них пока отказался.


Есть пока два вопроса:
1. Как получить инфу о классах которые загружены через composer
2. Как расширить базовый класс дочерними, что бы в нем появились методы из каких-то других классов (в данном случае идет речь о модели).

Есть модель блог BlogModel.
Есть расширение в котором мне в эту модель нужно добавить MySQL-колонки и методы. И нужно что бы они как-то появились в BlogModel.
 

WMix

герр M:)ller
Партнер клуба
нужно что бы они как-то появились в BlogModel
А просто написать? Не годится?
1. Как получить инфу о классах которые загружены через composer
2. Как расширить базовый класс дочерними, что бы в нем появились методы из каких-то других классов (в данном случае идет речь о модели).
1. О какой инфе речь?
2. Чтото умалчиваешь, о каких других классах речь? Миксины уже вроде показывали
 

ksnk

прохожий
O! Я понял о чем идет разговор...! Требуется множественное наследование в php :)
В полном объеме такое никак пока не решить, так как динамика, которая была введена с помощью Closure пока еще не позволяет оторвать метод одного объекта и прикрутить его к нужному. Методы можно расширять только анонимными функциями или глобальными...
Ну а свойства легко замешиваются с помощью магии.
 

StalkerClasses

Новичок
А просто написать? Не годится?

1. О какой инфе речь?
2. Чтото умалчиваешь, о каких других классах речь? Миксины уже вроде показывали
1. Все что загружено через Composer пока не исползовано в коде - я не могу получить информацию о списке всех загруженных классов через композер. Мне нужно как-то получить список классов, получить переменные из них, а также аннотации к этим переменным.

2. Моя идея в чем.

Я создаю модель

PHP:
class Model {

/**
typeField: Input
typeDb: int
**/
private $id;

/**
typeField: Input
typeDb: varchar
**/
private $title;
}
Эта модель находится в расширении №1.
Допустим я завтра создал расширение №2 и мне нужно расширить эту модель доп.колонкой. Как бы вы добавили переменную в базовую модель. Запросы и обращения то я делаю через базовую модель.

O! Я понял о чем идет разговор...! Требуется множественное наследование в php :)
В полном объеме такое никак пока не решить, так как динамика, которая была введена с помощью Closure пока еще не позволяет оторвать метод одного объекта и прикрутить его к нужному. Методы можно расширять только анонимными функциями или глобальными...
Ну а свойства легко замешиваются с помощью магии.
А) Closure
Б) Ну а свойства легко замешиваются с помощью магии.


Можно несколько примеров для А и Б.
 

StalkerClasses

Новичок
Классы которые загружены через composer и use - по ним нет возможности получить инфу через get_declared_classes().
 

ksnk

прохожий
Вот и Б и А
PHP:
class a {
  var $x=1;
  var $y=11;
  function step(){return __CLASS__.':'.__FUNCTION__.' x='.$this->x;}
}
class b {
  var $x=2;
  var $y=22;
  function step(){return __CLASS__.':'.__FUNCTION__.' x='.$this->x;}
  function jump(){return __CLASS__.':'.__FUNCTION__.' y='.$this->y;}
}

class multi {
  protected $parents=[];
  protected $closures=[];

  var $y=33;
  function __construct($parents=[]){
    $this->appendparent($parents);
  }
  function appendparent($parents=[]){
    $this->parents=array_merge($this->parents,$parents);
  }
  function __call($n,$args){
    if(!isset($this->closures[$n])) {
      foreach ($this->parents as $p) {
        if (method_exists($p, $n)) {
// не работает :(
//          $this->closures[$n]=(Closure::fromCallable(array($p,$n)))->bindTo($this);
          $this->closures[$n]=Closure::fromCallable(array($p,$n));
        }
      }
    }
    if(isset($this->closures[$n])) {
      return call_user_func_array($this->closures[$n], $args);
    } else {
      throw new Exception('unknown function '.$n);
    }
  }
  function __get($n){
    foreach ($this->parents as $p) {
      if (property_exists($p, $n)) {
        return $p->{$n};
      }
    }
    throw new Exception('property not found '.$n);
  }
}

$a=new multi([new a,new b]);
printf("%s\n",print_r($a->x, true)); // 1
printf("%s\n",print_r($a->y, true)); // 33
printf("%s\n",print_r($a->jump(), true)); // b:jump y=22, а хочется b:jump y=33
//printf("%s\n",print_r($a->xx, true)); // exception
//printf("%s\n",print_r($a->xxx(), true)); // exception
Схема простая, объявляем класс multy, добавляем ему "родителей". Все свойства доступны без проблем, в порядке следования родителей, а вот с методами засада, при вызове метода, который принадлежит "родителю" не получается переопределить контекст собственного класса, здесь нам не javascript...
Тоесть соорудить из чужого метода типа как анонимную функцию, вообще говоря, получается, но она все равно работает в контексте своего класса-родителя, а bindTo тупо обламывается с ошибкой.
 
Сверху