简体   繁体   English

如何从行中获取 self 值以在 self eloquent model 中的另一个 select 查询中使用?

[英]How get self value from row to use in another select query in the self eloquent model?

I'm new at the laravel, Just started at few days ago and I already searched about this but nothing found about my question.我是 laravel 的新手,几天前才开始,我已经搜索过这个,但没有找到关于我的问题的信息。 For example... I have the offers and offers_prices table.例如...我有offer 和 offer_prices

offers:提供:

+----+-----------+
| id |   name    |
+----+-----------+
|  1 | Product 1 |
|  2 | Product 2 |
|  3 | Product 3 |
|  4 | Product 4 |
+----+-----------+

offers_prices:优惠价格:

+----+------------+-------+---------------------+
| id |  offer_id  | price |     created_at      |
+----+------------+-------+---------------------+
|  1 |          1 | 65.90 | 2020-12-17 16:00:00 |
|  2 |          1 | 64.99 | 2020-12-17 17:00:00 |
|  3 |          1 | 58.90 | 2020-12-17 18:00:00 |
|  4 |          1 | 60.99 | 2020-12-17 19:00:00 |
+----+------------+-------+---------------------+

To get the current offer price ( 60.99 ) I have created the function below to get it from a relationship eloquent model:为了获得当前的报价( 60.99 ),我创建了下面的 function 以从关系 eloquent model 中获得它:

Models/Offer.php型号/报价.php

public function price() {
    return parent::hasOne(OfferPrices::class)
        ->where("date", "<=", \Carbon\Carbon::now()->toDateTimeString())
        ->orderBy("date", "DESC")
        ->limit(1);
}

And now I want to get the most recent previous price but higher than current price like in the query below:现在我想获得最新的先前价格,但高于当前价格,如下面的查询:

SELECT *
FROM offers_prices
WHERE offers_prices.offer_id = 1
AND
offers_prices.price > (
    SELECT offers_prices.price
    FROM offers_prices
    WHERE offers_prices.offer_id = 1
    AND offers_prices.date <= NOW()
    ORDER BY offers_prices.date DESC
    LIMIT 1
)
AND offers_prices.date <= NOW()
ORDER BY offers_prices.date DESC
LIMIT 1;

It means that the recent previous and higher than current price can't be 58.90 because it's lower than current (60.99) .这意味着最近的上一个和高于当前的价格不能是58.90 ,因为它低于当前(60.99) Must be 64.99 .必须是 64.99 How can I do it?我该怎么做? I have tried creating another function in the self eloquent model:我尝试在自我 eloquent model 中创建另一个 function:

Models/Offer.php型号/报价.php

public function prev_high_price() {
    return parent::hasOne(OfferPrices::class)
        ->where("date", "<=", \Carbon\Carbon::now()->toDateTimeString())
        ->where("price", ">", $this->price()->price)
        ->orderBy("date", "DESC")
        ->limit(1);
}

But it doesn't work..但它不起作用..

You're using the hasOne relationship for a database relationship that looks more like a hasMany .您将hasOne关系用于看起来更像hasMany的数据库关系。 Your Offers can have many Prices .您的Offers可以有多个Prices Your table naming is outwith convention too as you're not using a pivot table but have named your offers_prices table as if it was.您的表命名也超出了约定,因为您没有使用 pivot 表,而是将您的offers_prices表命名为就好像它是一样的。

Off topic to the question but relevant to your situation, it's advisable to not store currency values as floats or doubles.与问题无关但与您的情况相关,建议不要将货币值存储为浮点数或双精度数。 Store them as integers in the lowest denominator.将它们作为整数存储在最低分母中。

To answer your question, given the following two migrations:要回答您的问题,请考虑以下两个迁移:

Offers table migration提供表迁移

class CreateOffersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('offers', function (Blueprint $table) {
            $table->id();
            $table->timestamps();
            $table->string('name');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('offers');
    }
}

Prices table migration价格表迁移

class CreatePricesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('prices', function (Blueprint $table) {
            $table->id();
            $table->timestamps();
            $table->foreignId('offer_id');
            $table->integer('price');
            $table->foreign('offer_id')->references('id')->on('offers');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('prices');
    }
}

Define the following in your Offer model:在您的Offer model 中定义以下内容:

class Offer extends Model
{
    use HasFactory;

    public function prices()
    {
        return $this->hasMany(Price::class);
    }

    public function lastPrice()
    {
        return $this->prices()->orderBy('id', 'desc')->limit(1);
    }

    public function lastHighPrice()
    {
        return $this->prices()
            ->where('id', '<', $this->lastPrice()->first()->id)
            ->orderBy('price', 'desc')
            ->limit(1);
    }
}

Run your migration and database seeders (if you have any, otherwise just add data manually).运行您的迁移和数据库播种器(如果有,否则只需手动添加数据)。 In your terminal and whilst you're current working directory is your Laravel project, fire up tinker :在您的终端中,当您当前的工作目录是您的 Laravel 项目时,启动tinker

php artisan tinker

From inside tinker, you can now play around with your data and models.在 tinker 内部,您现在可以使用您的数据和模型。

// get a collection of all prices for the Offer with id 1
Offer::find(1)->prices

// get a collection with the last price for the offer with id 1
Offer::find(1)->lastPrice

// get a collection with the previous highest price for the offer with id 1
Offer::find(1)->lastHighPrice

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM