Yii2,SELECT 来自两个连接的表作为 ActiveRecord

Yii2, SELECT from two joined tables as ActiveRecord

有 2 个表:

  1. product_url (id,product_id,url)

  2. 店铺 (id,url,tag)

(!) 我从 SUBSTRING_INDEX 上的两个连接表 (product_url + shop ) 中执行 ActiveQuery select 作为 Array.

$product_url = ProductUrl::find()
    ->alias('pu')
    ->select('pu.*, tag')
    ->leftJoin('shop', "SUBSTRING_INDEX(pu.url, '/', 3) = SUBSTRING_INDEX(shop.url, '/', 3)")
    ->asArray()
    ->all();

并希望得到这样的数据

product_url_tag (id,product_id,url,tag)

| id | product_id | url                                                       | tag |
|----|------------|-----------------------------------------------------------|-----|
| 1  | 1234       | http://example.org/sku1234.html                           | low |
| 2  | 1234       | http://anotherdomain.com/alice-book.html                  | med |
| 3  | 1234       | http://bookstore.com/Alices-Adventures-in-Wonderland.html | hig |
| 4  | 4321       | http://example.org/sku4321.html                           | low |

作为数组输出正常:

array(4) {
  [0]=>
  array(4) {
    ["id"] => string(1) "1"
    ["product_id"] => string(4) "1234"
    ["url"] => string(31) "http://example.org/sku1234.html"
    ["tag"] => string(3) "low"
  }
  [1]=>
  array(4) {
    ["id"] => string(1) "2"
    ["product_id"] => string(4) "1234"
    ["url"] => string(40) "http://anotherdomain.com/alice-book.html"
    ["tag"] => string(3) "med"
  }
  [2]=>
  array(4) {
    ["id"] => string(1) "3"
    ["product_id"] => string(4) "1234"
    ["url"] => string(57) "http://bookstore.com/Alices-Adventures-in-Wonderland.html"
    ["tag"] => string(3) "hig"
  }
  [3]=>
  array(4) {
    ["id"] => string(1) "4"
    ["product_id"] => string(4) "4321"
    ["url"] => string(31) "http://example.org/sku4321.html"
    ["tag"] => string(3) "low"
  }

但是如果我想获得与 ActiveRecord 对象相同的数据 tag 就会丢失。

$product_url = ProductUrl::find()
    ->alias('pu')
    ->select('pu.*, tag')
    ->leftJoin('shop', "SUBSTRING_INDEX(pu.url, '/', 3) = SUBSTRING_INDEX(shop.url, '/', 3)")
                //  ->asArray()
    ->all();

结果

array(4) {
  [0]=>
  object(app\models\ProductUrl)#139 (10) {
    ["_attributes":"yii\db\BaseActiveRecord":private]=>
        array(3) {
          ["id"] => int(1)
          ["product_id"] => int(1234)
          ["url"] => string(31) "http://example.org/sku1234.html"
        }
    ["_oldAttributes":"yii\db\BaseActiveRecord":private]=>
        array(3) {
          ["id"] => int(1)
          ["product_id"] => int(1234)
          ["url"] => string(31) "http://example.org/sku1234.html"
        }
    ["_related":"yii\db\BaseActiveRecord":private]=>
    array(0) {
    }
    ["_relationsDependencies":"yii\db\BaseActiveRecord":private]=>
    array(0) {
    }
    ["_errors":"yii\base\Model":private]=>
    NULL
    ["_validators":"yii\base\Model":private]=>
    NULL
    ["_scenario":"yii\base\Model":private]=>
    string(7) "default"
    ["_events":"yii\base\Component":private]=>
    array(0) {
    }
    ["_eventWildcards":"yii\base\Component":private]=>
    array(0) {
    }
    ["_behaviors":"yii\base\Component":private]=>
    array(0) {
    }
  }
  [1]=>
  object(app\models\ProductUrl)#149 (10) {
    ["_attributes":"yii\db\BaseActiveRecord":private]=>
        array(3) {
          ["id"] => int(2)
          ["product_id"] => int(1234)
          ["url"] => string(40) "http://anotherdomain.com/alice-book.html"
        }
    ["_oldAttributes":"yii\db\BaseActiveRecord":private]=>
        array(3) {
          ["id"] => int(2)
          ["product_id"] => int(1234)
          ["url"] => string(40) "http://anotherdomain.com/alice-book.html"
        }
    ["_related":"yii\db\BaseActiveRecord":private]=>
    array(0) {
    }
    ["_relationsDependencies":"yii\db\BaseActiveRecord":private]=>
    array(0) {
    }
    ["_errors":"yii\base\Model":private]=>
    NULL
    ["_validators":"yii\base\Model":private]=>
    NULL
    ["_scenario":"yii\base\Model":private]=>
    string(7) "default"
    ["_events":"yii\base\Component":private]=>
    array(0) {
    }
    ["_eventWildcards":"yii\base\Component":private]=>
    array(0) {
    }
    ["_behaviors":"yii\base\Component":private]=>
    array(0) {
    }
  }
  [2]=>
  object(app\models\ProductUrl)#150 (10) {
    ["_attributes":"yii\db\BaseActiveRecord":private]=>
        array(3) {
          ["id"] => int(3)
          ["product_id"] => int(1234)
          ["url"] => string(57) "http://bookstore.com/Alices-Adventures-in-Wonderland.html"
        }
    ["_oldAttributes":"yii\db\BaseActiveRecord":private]=>
        array(3) {
          ["id"] => int(3)
          ["product_id"] => int(1234)
          ["url"] => string(57) "http://bookstore.com/Alices-Adventures-in-Wonderland.html"
        }
    ["_related":"yii\db\BaseActiveRecord":private]=>
    array(0) {
    }
    ["_relationsDependencies":"yii\db\BaseActiveRecord":private]=>
    array(0) {
    }
    ["_errors":"yii\base\Model":private]=>
    NULL
    ["_validators":"yii\base\Model":private]=>
    NULL
    ["_scenario":"yii\base\Model":private]=>
    string(7) "default"
    ["_events":"yii\base\Component":private]=>
    array(0) {
    }
    ["_eventWildcards":"yii\base\Component":private]=>
    array(0) {
    }
    ["_behaviors":"yii\base\Component":private]=>
    array(0) {
    }
  }
  [3]=>
  object(app\models\ProductUrl)#151 (10) {
    ["_attributes":"yii\db\BaseActiveRecord":private]=>
        array(3) {
          ["id"] => int(4)
          ["product_id"] => int(4321)
          ["url"] => string(31) "http://example.org/sku4321.html"
        }
    ["_oldAttributes":"yii\db\BaseActiveRecord":private]=>
        array(3) {
          ["id"] => int(4)
          ["product_id"] => int(4321)
          ["url"] => string(31) "http://example.org/sku4321.html"
        }
    ["_related":"yii\db\BaseActiveRecord":private]=>
    array(0) {
    }
    ["_relationsDependencies":"yii\db\BaseActiveRecord":private]=>
    array(0) {
    }
    ["_errors":"yii\base\Model":private]=>
    NULL
    ["_validators":"yii\base\Model":private]=>
    NULL
    ["_scenario":"yii\base\Model":private]=>
    string(7) "default"
    ["_events":"yii\base\Component":private]=>
    array(0) {
    }
    ["_eventWildcards":"yii\base\Component":private]=>
    array(0) {
    }
    ["_behaviors":"yii\base\Component":private]=>
    array(0) {
    }
  }

为什么tag输了?以及如何从加入的 shop 中获取 tag 作为 ActiveRecord 对象?

更新:

./models/Shop.php

namespace app\models;

use Yii;

/**
 * This is the model class for table "shop".
 *
 * @property int $id
 * @property string $url
 * @property string $tag
 */
 ...

./models/ProductUrl.php

namespace app\models;

use Yii;

/**
 * This is the model class for table "product_url".
 *
 * @property int $id
 * @property int $product_id
 * @property string $url
 *
 * @property Product $product
 * @property Shop $shop
 */

...

/**
 * @return \yii\db\ActiveQuery
 */
public function getShop()
{
    return $this->hasOne(Shop::className(), ["SUBSTRING_INDEX(url,'/',3)" => "SUBSTRING_INDEX(url,'/',3)"]);
}

./controllers/ProductController.php

namespace app\controllers;

use Yii;
use app\models\ProductUrl;
use app\models\Shop;
...

谢谢@rob006。 有必要在 ProductUrl class 中用 public $tag; 明确定义 ProductUrl::$tag,就像在手册 selecting-extra-fields 中一样。不需要与 public function getShop() 的关系。