shopProductsCollection: проблемы с при`join`неными таблицами

1

Используя shopProductsCollection::addJoin() добавил таблицы, но не получается вывести значения из них используя shopProductsCollection::getProducts($fields). Из $fields удаляются все поля не относящиеся к товару (p.*). Из-за этого также невозможно отсортировать данные по полям доп.таблиц.

Из описания shopProductsCollection::getSQL() следует что можно задать тип объединения используя поле 'type', но shopProductsCollection::addJoin() не позволяет задать его. Метод нужно дополнить:

    /**
     * Adds a simple JOIN clause to product selection query.
     *
     * @param string|array $table Table name to be used in JOIN clause.
     *     Alternatively an associative array may be specified containing values for all method parameters.
     *     In this case $on and $where parameters are ignored.
     * @param string $on ON condition FOR JOIN, must not include 'ON' keyword
     * @param string $where WHERE condition for SELECT, must not include 'WHERE' keyword
     * @param string $type Type of join (LEFT, RIGHT, INNER)
     * @return string Specified table's alias to be used in SQL query
     */
    public function addJoin($table, $on = null, $where = null, $type = null)
    {
        if (is_array($table)) {
            if (isset($table['on'])) {
                $on = $table['on'];
            }
            if (isset($table['where'])) {
                $where = $table['where'];
            }
            if (isset($table['type'])) {
                $type = $table['type'];
            }
            $table = $table['table'];
        }
        $t = explode('_', $table);
        $alias = '';
        foreach ($t as $tp) {
            if ($tp == 'shop') {
                continue;
            }
            $alias .= substr($tp, 0, 1);
        }

        if (!$alias) {
            $alias = $table;
        }

        if (!isset($this->join_index[$alias])) {
            $this->join_index[$alias] = 1;
        } else {
            $this->join_index[$alias]++;
        }
        $alias .= $this->join_index[$alias];

        $join = array(
            'table' => $table,
            'alias' => $alias,
        );
        if ($on) {
            $join['on'] = str_replace(':table', $alias, $on);
        }
        if ($type) {
            $join['type'] = $type;
        }
        $this->joins[] = $join;
        if ($where) {
            $this->where[] = str_replace(':table', $alias, $where);
        }
        return $alias;
    }
    
    /**
     * Adds a LEFT JOIN clause to product selection query.
     *
     * @param string|array $table Table name to be used in JOIN clause.
     *     Alternatively an associative array may be specified containing values for all method parameters.
     *     In this case $on and $where parameters are ignored.
     * @param string $on ON condition FOR JOIN, must not include 'ON' keyword
     * @param string $where WHERE condition for SELECT, must not include 'WHERE' keyword
     * @return string Specified table's alias to be used in SQL query
     */
    public function addLeftJoin($table, $on = null, $where = null)
    {
        return $this->addJoin($table, $on, $where, 'LEFT');
    }


3 комментария

  • +1
    Enso studio Enso studio 16 апреля 2018 08:19 #

    Попутно всплыл баг в методе orderBy:

    if ($this->getModel()->fieldExists($field)) {
    	$this->getSQL();
    	if ($field == 'count') {
    		$this->fields[] = 'IF(p.count IS NULL, 1, 0) count_null';
    		return $this->order_by = 'count_null '.$order.', p.count '.$order;
    	} elseif ($field == 'stock_worth') {
    		$this->fields[] = 'IFNULL(p.count, 0)*p.price AS stock_worth';
    		$this->order_by = 'stock_worth '.$order;
    	} else {
    		return $this->order_by = 'p.'.$field." ".$order;
    	}

    Мне не понятно при каких обстоятельствах сработает stock_worth.

    • +1
      Enso studio Enso studio 16 апреля 2018 08:22 #

      Использование в методе $this->getSQL(); тоже не понятно чем обусловлено, почему не использовать $this->prepare()?

    • +1
      Enso studio Enso studio 16 апреля 2018 11:57 #

      В итоге у меня получился вот такой код:

      /**
       * Add special field to product selection query.
       *
       * @param string $field
       * @return void
       */
      public function addField($field)
      {
      	if (!in_array($field, $this->fields)) {
      		$this->fields[] = $field;
      	}
      }
      
      /**
       * Changes ORDER BY clause of product selection query.
       *
       * @param string|array $field Name of field. Alternative value options:
       *     'sort' (ignored)
       *     'rand()' or 'RAND()' — sets 'RAND()' condition for ORDER BY clause
       *     'count'
       *     'stock_worth'
       *     array($field, $order) — in this case $order parameter is ignored
       * @param string $order 'ASC' or 'DESC' modifier
       * @return string New ORDER BY clause or empty string (for 'rand()' $field value)
       */
      public function orderBy($field, $order = 'ASC')
      {
      	if (is_array($field)) {
      		if (count($field) > 1) {
      			list($field, $order) = $field;
      		} else {
      			$field = array_shift($field);
      		}
      	}
      	
      	$field = trim($field);
      	if (!$field || $field == 'sort') {
      		return '';
      	}
      	$order = strtoupper(trim($order));
      	if ($order != 'DESC') {
      		$order = 'ASC';
      	}
      	
      	if (strpos($field, '.') === false) {
      		if ($field == 'stock_worth') {
      			$this->addField('IFNULL(p.count, 0)*p.price AS stock_worth');
      		} elseif ($field == 'count') {
      			$this->addField('IF(p.count IS NULL, 1, 0) count_null');
      			$result = $this->order_by = 'count_null ' . $order . ', p.count ' . $order;
      		} elseif (strtolower($field) == 'rand()') {
      			$this->order_by = 'RAND()';
      			$result = '';
      		} elseif ($this->getModel()->fieldExists($field)) {
      			$field = 'p.' . $field;
      		}
      	}
      	
      	if (!isset($result)) {
      		$result = $this->order_by = $field . ' ' . $order;
      	}
      
      	$this->prepare();
      	
      	return $result;
      }

      попутно добавил метод для добавления полей.

      Добавить комментарий

      Чтобы добавить комментарий, зарегистрируйтесь или войдите