yiisoft / yiisoft/active-record

Disambiguing column's table on ActiveQuery select/where/order etc.

Open
#33 50 comments 0 reactions 1 assignee View on GitHub

@cebe is already working on this.

Since Aug 2, 2015.

status:under discussion
Dominant language
PHP
Stars
119
Forks
38
Avg merge
1h 11m
Merged PRs (30d)
1

Description

I have several tables that have columns with same name. Let's say shelf, book, chapter, have the same field name.

I have a page that will show list of chapter that will also show the name of the book as well as the shelf.

Naturally this is the query I used for the ActiveDataProvider

Chapter::find()
  ->joinWith([
      'book' => function($query) {
          $query->joinWith([
              'shelf'
          ])
      }
  ])

But I only wanted to show the name in the GridView, so this is what I do to avoid the SELECT *.

Chapter::find()
  ->addSelect(['name', 'bookId'])
  ->joinWith([
          'book' => function($query) {
              $query->addSelect(['name', 'shelfId'])
                         ->joinWith([
                                'shelf' => function($query){
                                    $query->addSelect(['name']);
                                }
                         ]);
          }
  ])

On my Yii2 (c21895d4dd4c18d5bab37e0b7b359668f8aa8b67) this will output error Column 'name' in field list is ambiguous. So I have to put something like this

Chapter::find()
  ->addSelect(['Chapters.name', 'bookId'])
  ->joinWith([
          'book' => function($query) {
              $query->addSelect(['Books.name', 'shelfId'])
                         ->joinWith([
                                'shelf' => function($query){
                                    $query->addSelect(['Shelves.name']);
                                }
                         ]);
          }
  ])

Do I really have to do this for every query like this? Or is there any simpler way I don't know?

I'm thinking that if I can disambiguate the table name right from the addSelect method, it would be much easier. I extend the ActiveQuery and do something like this.

    private $_tableName;
    private function getTableName() {
        //since the `from` will be resolved in the `prepare` method.
        if (!isset($this->_tableName)) {
            $class = $this->modelClass;
            $this->_tableName = $class::tableName();
        }
        return $this->_tableName;
    }
    public function addSelect($columns) {
        if (is_array($columns)) {
            $columns = array_map(function($column) {
                return (strpos($column, ".") == false) ? $this->getTableName() . ".{$column}" : $column;
            }, $columns);
        } else {
            $columns = (strpos($column, ".") == false) ? $this->getTableName() . ".{$columns}" : $columns;
        }
        return parent::addSelect($columns);
    }

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.