繁体   English   中英

如何在我的模型中通过多对多关系表改进搜索?

[英]How to Improve search by relation table many-to-many in my model?

为了简化我的问题,假设我有一个图书馆系统项目,该项目实现了图书馆中借阅,计数,搜索和添加书籍的所有功能。

对于那个项目我做了3个主要表: person (id, name, etc)loan (id, id_person, dates, etc) ,当然还有book (id, title, etc)

由于一个人可以同时借阅多本书,我还需要另一张表来链接这种多对多的关系。 rel_loan_book (id, id_book, id_loan)

现在,在我的“书本视图”中,我有一个Gridview其中包含该书的所有信息,并有一列说明该书是否可供借阅(目前不使用)。

这是我目前正在做的事情:

视图:

[
    'attribute' => 'isAvaliable',
    'value' => function($model) {
        return $model->currentLoan ? 'No' :'Yes';
    },
    'filter' => Html::activeDropDownList($searchModel, 'isAvaliable', ['1' => 'Yes', '0' => 'No'],
        ['class'=>'form-control','prompt' => '']
    )
],

型号书:

public function getCurrentLoan()
{
     return $this->hasOne(Loan::className(), ['id' => 'id_loan'])
         ->viaTable(RelLoanBook::tableName(), ['id_book' => 'id'])
         ->onCondition(['loan.status' => 'A']);
}

贷款表中的状态'A'表示它仍处于活动状态(该书未返回)。

我的问题是当我尝试通过可用或不可用的书籍进行搜索时......目前,我正在进行另一个查询,只是为了检查借来的书籍是什么,然后在我的搜索中删除(或过滤)此ID :

的BookSearch:

public $isAvaliable;

...

public function rules()
{
    return [
        [['isAvaliable'], 'safe'],
    ];
}

...

public function search($params)
{
    ...

    if ($this->isAvaliable !== '') {
        $subQuery = Book::find()->select('book.id');
        $subQuery->joinWith(['currentLoan'])
            ->andWhere(['is not' , 'loan.id', null])
            ->all();

        if ($this->isAvaliable === '1') {
            $query->andWhere(['not in', 'book.id', $subQuery]);
        } elseif ($this->isAvaliable === '0') {
            $query->andWhere(['in', 'book.id', $subQuery]);
        }
    }

    ...
}

我不认为这是最好的方法。 但是我无法想到在没有子查询的情况下进行SQL查询:

SELECT * FROM book
LEFT JOIN rel_loan_book ON rel_loan_book.book_id = book.id
LEFT JOIN loan ON loan.id = rel_loan_book.loan.id
WHERE ( /* my filters */)
AND ( /* some restriction that check if the book does OR does not have a loan with status === 'A' */)

首先,你有没有理由不贷款联络表? 这对我来说似乎更合逻辑,并且可以简化您的查询。

即:

  • 人(身份证,姓名)
  • 书(id,name,author,isbn,publisher,genre,tags)
  • 贷款(id,person_id,book_id,start_date,due_date,return_date,状态)

通过连接图书和借贷,该系统更加灵活,可以:

  • 某些书名的贷款扩展
  • 某些物品的早期退货

如果您忘记了其中一本,而图书馆拒绝归还所有书籍,那将很奇怪。 只有当他们都与一笔贷款有关时,才会发生这种情况。

稍作结构修改后,将其添加到图书模型中:

public function getIsAvailable()
{
    return !Loan::find()->where([
        'book_id' => $this->id,
        'status' => 'A'
    ])->exists();
}

如果存在处于活动状态且此书号的贷款记录,则该记录不可用。

将isAvailable属性添加到搜索过滤器:

 $query->andFilterWhere([
     ...
     'isAvailable' => $this->isAvailable,
 ]);

将getIsAvailable函数与下拉过滤器链接。

在book-view中调整isAvailable列:

[
    'attribute' => 'isAvailable',
    'value' => function($model) {
        return $model->isAvailable ? 'Yes' :'No';
    },
    'filter' => Html::activeDropDownList($searchModel, 'isAvailable', 
        [0 => 'No', 1 => 'Yes'],
        ['class'=>'form-control','prompt' => '']
    )
],

暂无
暂无

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

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