научите правильно мапить

WMix

герр M:)ller
Партнер клуба
допустим есть сущность
PHP:
class Foo{
  private $id;
  private $name;
}
чтобы получить набор по запросу имеется метод
PHP:
$foos = $this->query(['name' => $_GET['product_name']]);
$foo->name и ['name' => ...] подразумевает это одно и тоже но в разных контекстах (разница лишь в query-attribute или entity-property)

проблема refactoring'а если у сущности проперти сменится в найти запросах упоминание автоматом не получится
как вы решаете подобную ситуацию?
 

Вурдалак

Продвинутый новичок
На мой взгляд, такой проблемы не существует. То, что ты называешь «одним и тем же», таковым на самом деле не является. Достаточно вспомнить, что query/read часть может быть по причине обратной совместимости оставаться такой, какая она есть. Они (write и read части) могут совпадать, но совершенно не обязаны. Это разные контексты, как ты сам заметил.

Пример правда так себе, но можно представить, что со временем у сущности появятся firstName, lastName и lastName можно менять при действии marry(string $newLastName). В то же время ->query(['name' => ...] может делать поиск по двум составляющим сразу для legacy API под старые клиенты на iOS/Android. Если хочется сделать деление и тут, то нужно осознанно поменять read-часть отдельно.

Единственное, касательно рефакторинга, будет удобнее, пожалуй, если query тоже будут классами а-ля final class FindByName { private $name; }.
 

WMix

герр M:)ller
Партнер клуба
В этом запросе ‘name’ перемаппится в поле базы допустим lastName по тем же правилам что и проперти у сущности. Те запрос подразумевает имена проперти у сущностей. Я понимаю что это несколько разные вещи но прям хочется замутить

PHP:
$this->query(function(Foo $query){ 
  $query->name = “петя”;
});
но Foo это и приватные свойства и типы свойств. Те совершенно другое.
 

WMix

герр M:)ller
Партнер клуба
если query тоже будут классами а-ля final class FindByName { private $name; }.
а вы такое практикуете?

просто обычно запросы пишем так

PHP:
$this->query([
  'name' => new Expr(Expr::LIKE, $_GET['name'])
]);
в твоем варианте будет звучать так
PHP:
$this->query(new FindByName(new Expr(Expr::LIKE, $_GET['name']));
смущает несколько
 

WMix

герр M:)ller
Партнер клуба
расскажи пожалуйста, как в итоге собираете коллекцию.
PHP:
$collection = $mapper->find( $query->findByName($name)->findByAge($age) );
мне представить общее api хочется
 

WMix

герр M:)ller
Партнер клуба
PHP:
class Path{

  private $path = [];
  private $class;
 
  public function __construct($class){
    $this->class = $class;
  }

  public function __get($property){
    // TODO придумать валидацию
    if(false){
      throw new \Exception('property '.$property.' does not exist on '.$this->class);
    }
    $this->path[] = $property;
    return $this;
  }

  public function __toString(){
    return implode('.', $this->path);
  }
}


class ValueObject{

    /**
     * @return static;
     */
    public static function path(){
        return new Path(static::class);
    }
}

/**
 * @property Name $name;
 * @property \DateTime $dateOfBirth;
 */
class Person extends ValueObject{
    protected $name;
    protected $dateOfBirth;
}

/**
 * @property string $firstname;
 * @property string $lastname;
 */
class Name extends ValueObject{
    protected $firstname;
    protected $lastname;
}

echo Person::path()->name->firstname;
// вернет name.firstname которое будет использованно в ->find(['name.firstname' => 'вася'])
вот такую штучку придумал, автокомплит работает, но не рефйакторится :(
 

AnrDaemon

Продвинутый новичок
Жёсткий чит…
А для чего такие красоты используются?
 

WMix

герр M:)ller
Партнер клуба
добавил проверку на существование property, че скажите, "совсем непотребно" или "имеет право на жизнь"?
 

Adelf

Administrator
Команда форума
У меня правило простое - чем меньше магии в коде, тем обычно проще его поддерживать.
Вся эта магия... обычно базируется принципе "а давай я тут как-бы уменьшу количество кода, немного срезав поворот". Вот сколько раз я так делал и столько же раз убеждался, что не стоило. Иногда в разы проще и правильнее просто написать код. Нормальный код. Да, это увеличит количество строк в проекте, но это не всегда тот показатель, который надо стремиться уменьшить.
 

WMix

герр M:)ller
Партнер клуба
да я не против писать, мне не хотелось магические константы типа 'name.firstname' писать. а так есть autocomplete хотябы
PHP:
$query->findByName($name)->findByAge($age)
это не решает проблему, что написано в findByName ?
PHP:
function findByName($name){
   $this->query([ ???? => $name]); // как сослаться на проперти?
   return $this;
}
 

Вурдалак

Продвинутый новичок
PHP:
function findByName($name){
   $this->query([ ???? => $name]); // как сослаться на проперти?
   return $this;
}
Что такое «проперти»? Название поля в SQL-таблице? Зачем его держать в query?
 

WMix

герр M:)ller
Партнер клуба
Что такое «проперти»? Название поля в SQL-таблице?
нет это свойство в Entity
Те запрос подразумевает имена проперти у сущностей.
PHP:
/**
 * @property Name $name;
 * @property \DateTime $dateOfBirth;
 */
class Person{
    protected $name;
    protected $dateOfBirth;
}

/**
 * @property string $firstname;
 * @property string $lastname;
 */
class Name{
    protected $firstname; // эта штука откуда бы она небыла должна быть равна $_GET['name']
    protected $lastname;
}

// те о таблицах уже не говорим и опираемся только на обьекты
$sql = $query->from(Person::class)->where([
    Person::propertyPath()->name->firstname => $_GET['name']
]);
 

Вурдалак

Продвинутый новичок
нет это свойство в Entity
Какую «проперти» затрагивает запрос «найди мне самых релевантных пользователей»? Или, например, «найди пользователей с наибольшим количеством логинов (авторизаций) в период с 1-го по 5-е января»? Или «найди пользователей, с которыми пересекался данный»?
 

WMix

герр M:)ller
Партнер клуба
Какую «проперти» затрагивает запрос
любую которая маппится
«найди пользователей с наибольшим количеством логинов (авторизаций) в период с 1-го по 5-е января»?
PHP:
$query->from(User::class, 'user')->with(UserAuthorisation::class, 'authorisation')->where([
  UserAuthorisation::propertyPath()->date => new Between('2012-01-01', '2012-01-05')
]);
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
У меня правило простое - чем меньше магии в коде, тем обычно проще его поддерживать.
Вся эта магия... обычно базируется принципе "а давай я тут как-бы уменьшу количество кода, немного срезав поворот". Вот сколько раз я так делал и столько же раз убеждался, что не стоило. Иногда в разы проще и правильнее просто написать код. Нормальный код. Да, это увеличит количество строк в проекте, но это не всегда тот показатель, который надо стремиться уменьшить.
В твоем лице заядлого ларавелиста, у которого все параметры задаются неявным мапингом с магией через рефлексию, это звучит как в анекдоте "ненавижу расизм и негров" :D
 

Adelf

Administrator
Команда форума
Да. В чате ларки тоже постоянно это отмечают :)
 
Сверху