如何在模型中声明在请求中计算的属性?

huangapple go评论48阅读模式
英文:

How to declare property in model which is calculated in request?

问题

以下是您提供的内容的翻译:

在laravel laravel/framework 9.52.5/ nunomaduro/larastan 2.6.0应用程序中使用以下命令运行检查:

./vendor/bin/phpstan analyse

我收到了错误行:

访问未定义的属性 App\Models\BannerCategory::$banner_clicked_counts_count。

指向请求的部分:

$bannerCategories = BannerCategory
    ::leftJoin((new Banner)->getTable(), (new Banner)->getTable().'.banner_category_id', '=', (new BannerCategory)->getTable() . '.id')
    ->orderBy('name', 'asc')
    ->addSelect(['banner_clicked_counts_count' => BannerClickedCount
        ::selectRaw('count(*)')
        ->whereColumn('banners.banner_category_id', 'banner_categories.id')
        ->whereColumn('banner_clicked_counts.banner_id', 'banners.id')
        ->whereRaw("banners.active = true ")
        ->getByCreatedAt($dateStart->startOfDay(), '>=')
        ->getByCreatedAt($dateEnd->endOfDay(), '<=')
        ->getByPageContentId($pageContentId)
        ->getByLocale($locale)
    ])
    ->get();

$seriesData = [];
foreach( $bannerCategories as $bannerCategory ) {
    $seriesData[] = $bannerCategory->banner_clicked_counts_count; // 此行出错
    $labelsData[] = $bannerCategory->name;
}

我修改了模型 app/Models/BannerCategory.php 如下:

class BannerCategory extends Model
{
    use HasLocks;
    use Sluggable;
    use HasFactory;

    protected $table = 'banner_categories';
    protected $primaryKey = 'id';
    public $timestamps = false;
    protected $bannerClickedCountsCount = 0;
    protected $appends = ['bannerClickedCountsCount'];

    function getBannerClickedCountsCount(): int
    {
        \Log::info(varDump($this->bannerClickedCountsCount, ' -1 getBannerClickedCountsCount $this->bannerClickedCountsCount::'));
        return $this->bannerClickedCountsCount;
    }

    function setBannerClickedCountsCount(int $bannerClickedCountsCount)
    {
        \Log::info(varDump($bannerClickedCountsCount, ' -1 setBannerClickedCountsCount $bannerClickedCountsCount::'));
        return $this->bannerClickedCountsCount = $bannerClickedCountsCount;
    }
}

跟踪SQL语句:

SELECT `banner_categories`.*, (SELECT count(*) 
    FROM `banner_clicked_counts` 
    WHERE `banners`.`banner_category_id` = `banner_categories`.`id` AND `banner_clicked_counts`.`banner_id` = `banners`.`id` AND banners.active = true AND banner_clicked_counts.created_at >= '2023-04-07 00:00:00' AND banner_clicked_counts.created_at <= '2023-05-07 23:59:59') AS `bannerClickedCountsCount` 
    FROM `banner_categories` 
    LEFT JOIN `banners` on `banners`.`banner_category_id` = `banner_categories`.`id` 
    ORDER BY `name` asc 

我看到列bannerClickedCountsCount的值大于0,但是function getBannerClickedCountsCount(): int对于所有行都返回0(我记录了这个值)。我认为我以错误的方式设置了$bannerClickedCountsCount的值。哪种方法是有效的?

我想正确设置它,而不是使用larastan忽略行。

英文:

Running checks in laravel laravel/framework 9.52.5/ nunomaduro/larastan 2.6.0 app with command

./vendor/bin/phpstan analyse

I got error line :

Access to an undefined property

App\Models\BannerCategory::$banner_clicked_counts_count.                                                                                          

Pointing at request :

$bannerCategories = BannerCategory
    ::leftJoin((new Banner)-&gt;getTable(), (new Banner)-&gt;getTable().&#39;.banner_category_id&#39;, &#39;=&#39;, (new BannerCategory)-&gt;getTable() . &#39;.id&#39;)
    -&gt;orderBy(&#39;name&#39;, &#39;asc&#39;)
    -&gt;addSelect([&#39;banner_clicked_counts_count&#39; =&gt; BannerClickedCount
        ::selectRaw(&#39;count(*)&#39;)
        -&gt;whereColumn(&#39;banners.banner_category_id&#39;, &#39;banner_categories.id&#39;)
        -&gt;whereColumn(&#39;banner_clicked_counts.banner_id&#39;, &#39;banners.id&#39;)
        -&gt;whereRaw(&quot;banners.active = true &quot;)

        -&gt;getByCreatedAt($dateStart-&gt;startOfDay(), &#39;&gt;=&#39;)
        -&gt;getByCreatedAt($dateEnd-&gt;endOfDay(), &#39;&lt;=&#39;)
        -&gt;getByPageContentId($pageContentId)
        -&gt;getByLocale($locale)
    ])
    -&gt;get();

$seriesData = [];
foreach( $bannerCategories as $bannerCategory ) {
    $seriesData[] = $bannerCategory-&gt;banner_clicked_counts_count; // Error pointing at this line
    $labelsData[] = $bannerCategory-&gt;name;
}

I modified model app/Models/BannerCategory.php as :

class BannerCategory extends Model
{
    use HasLocks;
    use Sluggable;
    use HasFactory;

    protected $table = &#39;banner_categories&#39;;
    protected $primaryKey = &#39;id&#39;;
    public $timestamps = false;
    protected $bannerClickedCountsCount = 0;
    protected $appends = [&#39;bannerClickedCountsCount&#39;];
...

    function getBannerClickedCountsCount(): int
    {
        \Log::info(varDump($this-&gt;bannerClickedCountsCount, &#39; -1 getBannerClickedCountsCount $this-&gt;bannerClickedCountsCount::&#39;));
        return $this-&gt;bannerClickedCountsCount;
    }

    function setBannerClickedCountsCount(int $bannerClickedCountsCount)
    {
        \Log::info(varDump($bannerClickedCountsCount, &#39; -1 setBannerClickedCountsCount $bannerClickedCountsCount::&#39;));
        return $this-&gt;bannerClickedCountsCount = $bannerClickedCountsCount;
    }

Tracing sql-statement :

   SELECT `banner_categories`.*, (  SELECT count(*) 
    FROM `banner_clicked_counts` 
    WHERE `banners`.`banner_category_id` = `banner_categories`.`id`     AND `banner_clicked_counts`.`banner_id` = `banners`.`id`     AND banners.active = true      AND banner_clicked_counts.created_at &gt;= &#39;2023-04-07 00:00:00&#39;     AND banner_clicked_counts.created_at &lt;= &#39;2023-05-07 23:59:59&#39;)     AS `bannerClickedCountsCount` 
    FROM `banner_categories` 
    LEFT JOIN `banners` on `banners`.`banner_category_id` = `banner_categories`.`id` 
    ORDER BY `name` asc 

I see that column bannerClickedCountsCount has value > 0, but method

function getBannerClickedCountsCount(): int

returns 0 for all rows(I log this value) .
I suppose I set $bannerClickedCountsCount value in wrong way. Which way is valid ?

I would like to set it correctly, not use larastan ignore line.

答案1

得分: 1

Sure, here's the translation of the provided code snippet:

你可以使用 $model->getAttribute('attribute');
你以 BannerCategory::leftJoin 开始查询,应该检索到 BannerCategory 的实例,即使实际上它不完全包含这些内容。

$bannerCategories = BannerCategory
::leftJoin((new Banner)->getTable(), (new Banner)->getTable().'.banner_category_id', '=', (new BannerCategory)->getTable() . '.id')
->orderBy('name', 'asc')
->addSelect(['banner_clicked_counts_count' => BannerClickedCount
    ::selectRaw('count(*)')
    ->whereColumn('banners.banner_category_id', 'banner_categories.id')
    ->whereColumn('banner_clicked_counts.banner_id', 'banners.id')
    ->whereRaw("banners.active = true ")
    ->getByCreatedAt($dateStart->startOfDay(), '>=') // getByCreatedAt 方法的调用
    ->getByCreatedAt($dateEnd->endOfDay(), '<=')      // getByCreatedAt 方法的调用
    ->getByPageContentId($pageContentId)              // getByPageContentId 方法的调用
    ->getByLocale($locale)                            // getByLocale 方法的调用
])
->get();

$seriesData = [];
foreach ($bannerCategories as $bannerCategory) {
    $seriesData[] = $bannerCategory->getAttribute('banner_clicked_counts_count');
    $labelsData[] = $bannerCategory->name;
}

Please note that I've included translations for the method calls as comments within the code.

英文:

You can use $model->getAttribute('attribute');
You started the query as BannerCategory::leftJoin that should retrieve an instance of BannerCategory, even if that is not exactly what it contains.

$bannerCategories = BannerCategory
::leftJoin((new Banner)-&gt;getTable(), (new Banner)-&gt;getTable().&#39;.banner_category_id&#39;, &#39;=&#39;, (new BannerCategory)-&gt;getTable() . &#39;.id&#39;)
-&gt;orderBy(&#39;name&#39;, &#39;asc&#39;)
-&gt;addSelect([&#39;banner_clicked_counts_count&#39; =&gt; BannerClickedCount
    ::selectRaw(&#39;count(*)&#39;)
    -&gt;whereColumn(&#39;banners.banner_category_id&#39;, &#39;banner_categories.id&#39;)
    -&gt;whereColumn(&#39;banner_clicked_counts.banner_id&#39;, &#39;banners.id&#39;)
    -&gt;whereRaw(&quot;banners.active = true &quot;)

    -&gt;getByCreatedAt($dateStart-&gt;startOfDay(), &#39;&gt;=&#39;)
    -&gt;getByCreatedAt($dateEnd-&gt;endOfDay(), &#39;&lt;=&#39;)
    -&gt;getByPageContentId($pageContentId)
    -&gt;getByLocale($locale)
])
-&gt;get();

$seriesData = [];
foreach( $bannerCategories as $bannerCategory ) {
    $seriesData[] = $bannerCategory-&gt;getAttribute(&#39;banner_clicked_counts_count&#39;);
    $labelsData[] = $bannerCategory-&gt;name;
}

huangapple
  • 本文由 发表于 2023年5月7日 14:23:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/76192474.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定