neat-php / object

Neat Object components
MIT License
4 stars 1 forks source link

Multiple relations of the same type to the same class #12

Closed baukevdw closed 4 years ago

baukevdw commented 5 years ago

If you need to reference for example an user class from an order class multiple times:

<?php

use Neat\Object\Relations;
use Neat\Object\Storage;

class Order
{
  use Storage;
  use Relations;

  /**
   * @var int
   */
  public $id;

  /**
   * @var int
   */
  public $createdBy;

  /**
   * @var int
   */
  public $updatedBy;

  public function creator(): Relations\One
  {
    return $this->belongsToOne(User::class);
  }

  public function updater(): Relations\One
  {
    return $this->belongsToOne(User::class);
  }
}

This causes two problems:

The current solution to these issues is to initialize the relations manually which is far from ideal.

Something like this:


<?php

use Neat\Object\Relations;
use Neat\Object\Storage;

class Order
{
  use Storage;
  use Relations;

  /**
   * @var int
   */
  public $id;

  /**
   * @var int
   */
  public $createdBy;

  /**
   * @var int
   */
  public $updatedBy;

  /**
   * @return One
   */
  public function creator(): One
  {
      /** @var One $relation */
      $relation = $this->relations->get('belongsToOneCreator', function () {
          $key = new LocalKey(
              new Property(new \ReflectionProperty(self::class, 'createdBy')),
              new Property(new \ReflectionProperty(User::class, 'id')),
              'id',
              User::repository()
          );

          return new One($key, $this);
      });

      return $relation;
  }
}
annavanbiemen commented 4 years ago

This extra parameter only allows for a different foreign key. What about specifying a different table name? The junction table cannot possibly be configured with extra parameter (not unless you litter the belongsToMany API with all possible parameters).

Instead I think you should be able to pass a callable as second argument to the has-/belongsTo-One/Many functions that allows you to interact with a factory for building these relations. To avoid the need for references to be created using this callable, a reference factory might then be stored inside the relation.