【问题标题】:Yii2, SELECT from two joined tables as ActiveRecordYii2,从两个连接表中选择作为 ActiveRecord
【发布时间】:2021-11-02 10:21:41
【问题描述】:

有 2 张桌子:

  1. product_url (id,product_id,url)

  2. 购物 (id,url,tag)

(!)我从 SUBSTRING_INDEX as Array 上的两个连接表(product_url + shop)中进行 ActiveQuery 选择。

$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;
...

【问题讨论】:

  • 这能回答你的问题吗? Subquery in SELECT using Yii2 ActiveRecord
  • @rob006 不,因为我在模型中有 $tag 属性。
  • 我很确定你没有,因为 var_dump 没有在 ProductUrl 中显示 tag 属性,并且您粘贴的代码中没有 sn-p 证明此属性的存在。
  • 您的->all() 调用返回ProductUrl 实例的数组。如果ProductUrl 没有tag 属性,那么Yii 无法存储tag 列以供查询并简单地删除它。这就是为什么你需要明确定义ProductUrl::$tag
  • 你也可以使用关系,但是$this->hasOne() 中的["SUBSTRING_INDEX(url,'/',3)" => "SUBSTRING_INDEX(url,'/',3)"] 是不正确的——这些必须是列,因为 Yii 将使用它们来映射对象。如果你以这种方式使用表达式是不可能的。

标签: php activerecord yii yii2


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多