We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Intercept Many-to-Many relation

Hi

We have an Archivable class that extends \Phalcon\Mvc\Model in which we have overwritten find() and count() in order to filter archived objects out when requesting objects that extends Archivable. This is inspired by https://forum.phalcon.io/discussion/3248/auto-ignore-soft-delete-rows

This works great when using ::find() directly or when indirectly using find trough an alias of a hasMany-relation. But when we get to the class via a many-to-many it ignores the filter that is inserted in find().

Is there a another method that our Archivable class should overwrite in order to intercept many-to-many relations, or is there another way we accomplish what we want, which isn't to write filters into all getters on many-to-many relations?

Thanks!

edit: added Archivable class

  class Archivable extends \Phalcon\Mvc\Model
  {

      /**
       *
       * @var integer
       */
      public $archived;

      /**
       *
       * @var string
       */
      public $archivedAt;

      public function archive()
      {
          if ($this->archived == 1)
              return true;

          $this->archived = 1;
          $this->archivedAt = date('Y-m-d H:i:s');
          return $this->save();
      }

      public function unArchive()
      {
          if ($this->archived == 0)
              return true;

          $this->archived = 0;
          return $this->save();
      }

      public function isArchived()
      {
          return (bool) $this->archived;
      }

      /**
       * @inheritdoc
       *
       * @access public
       * @static
       * @param array|string $parameters Query parameters
       * @return \Phalcon\Mvc\Model\ResultsetInterface
       */
      public static function find($parameters = null)
      {
          $parameters = self::unArchivedFetch($parameters);

          return parent::find($parameters);
      }

      /**
       * @inheritdoc
       *
       * @access public
       * @static
       * @param array|string $parameters Query parameters
       * @return mixed
       */
      public static function count($parameters = null)
      {
          $parameters = self::unArchivedFetch($parameters);

          return parent::count($parameters);
      }

      public static function unArchivedFetch($parameters)
      {
          if ($parameters === null) {
              $parameters = 'archived = 0';
          } elseif (
              is_array($parameters) === false &&
              strpos($parameters, 'archived') === false
          ) {
              $parameters .= ' AND ' . 'archived = 0';
          } elseif (is_array($parameters) === true) {
              if (
                  isset($parameters[0]) === true &&
                  strpos($parameters[0], 'archived') === false
              ) {
                  $parameters[0] .= ' AND ' . 'archived = 0';
              } elseif (
                  isset($parameters['conditions']) === true &&
                  strpos($parameters['conditions'], 'archived') === false
              ) {
                  $parameters['conditions'] .= ' AND ' . 'archived = 0';
              }
          }

          return $parameters;
      }

  }


34.6k
Accepted
answer

Many to many are made using a query builder (also regular ones). Probably you can register the builder class in the di and use your own builder class.

https://github.com/phalcon/cphalcon/blob/2.0.x/phalcon/mvc/model/manager.zep#L1252-L1262

Thanks alot for your fast response, Andres!

We ended up writing getters on all our many-to-many relations - which links to archivable models.