Lack of interest Support arrays as keys in Relations

This suggestion has been closed automatically because it did not receive enough votes over an extended period of time. If you wish to see this, please search for an open suggestion and, if you don't find any, post a new one.

DragonByte Tech

Well-known member
At the moment, when you have a relation like so:
PHP:
            'Versions' => [
                'entity' => 'DBTech\eCommerce:DownloadVersion',
                'type' => self::TO_MANY,
                'conditions' => 'download_id',
//                'key' => 'product_version'
            ]

You can only use the "key" parameter if you have another column that is going to be unique within the result set generated by the conditions. What I would like is to be able to use an array here. The primary benefit of this is reducing the need for code like this:

PHP:
        foreach ($downloadVersions as $versionInfo)
        {
            if (empty($downloadVersionsGrouped[$versionInfo->product_version]))
            {
                $downloadVersionsGrouped[$versionInfo->product_version] = [];
            }
            $downloadVersionsGrouped[$versionInfo->product_version][$versionInfo->product_version_type] = $versionInfo;
        }
As it will be easier to reference these entities in the templates within my use case if they can be keyed by a sensible value.

I have created a patch for \XF\Mvc\Entity\FinderCollection that implements the array support. This has been tested in the following scenarios:
  • key column as array: FinderCollection::populate()
  • key column as array: FinderCollection::offsetGet()
  • key column as string: FinderCollection::populate()
  • key column as string: FinderCollection::offsetGet()
  • key column as array: one or more of the key columns were invalid (produces "invalid getter" server error as intended)
  • key column as string: one or more of the key columns were invalid (produces "invalid getter" server error as intended)
I have found it working in all these circumstances, which I believe should cover all test cases. If you need me to perform any other tests then please feel free to let me know.

Diff:
--- C:/xampp/htdocs/devboards/xf2/src/XF/Mvc/Entity/FinderCollection.php.orig    Tue Nov 28 18:17:35 2017
+++ C:/xampp/htdocs/devboards/xf2/src/XF/Mvc/Entity/FinderCollection.php    Wed Dec 20 12:01:14 2017
@@ -29,7 +29,20 @@

         foreach ($this->baseFinder->fetch() AS $entity)
         {
-            $this->entities[$entity->$keyField] = $entity;
+            if (is_array($keyField))
+            {
+                $column = [];
+                foreach ($keyField as $field)
+                {
+                    $column[] = $entity->$field;
+                }
+             
+                $this->entities[implode('_', $column)] = $entity;
+            }
+            else
+            {
+                $this->entities[$entity->$keyField] = $entity;
+            }
         }

         $this->falseEntities = [];
@@ -57,7 +70,16 @@
         if (!$this->populated)
         {
             $finder = clone $this->baseFinder;
-            $finder->where($this->keyField, $key);
+         
+            if (is_array($this->keyField))
+            {
+                $finder->where($finder->expression("CONCAT_WS('_', " . implode(", ", $this->keyField) . ")"), $key);
+            }
+            else
+            {
+                $finder->where($this->keyField, $key);
+            }
+         
             $value = $finder->fetchOne();
             if ($value)
             {

Thanks!

(PS: Can you please allow .patch and .diff as allowed extensions for attachments here? :D)


Fillip
 
Last edited:
Upvote 0
This suggestion has been closed. Votes are no longer accepted.
Back
Top Bottom