Join values from expression to one string
@param callable|string|null $join
@param string $glue
@return string
549832
public function joinString($join=null, $glue=", ")
    {
        $join = LambdaUtils::toSelectCallable($join);
        $temp = $this->select($join)->toArray();
        return implode($glue, $temp);
    }
374858
public static String implode(String glue, Object[] pieces)
    {
        if ( pieces == null ) {
            return null;
        }
        
        StringBuffer sb = new StringBuffer();
        for ( Object o : pieces ) {
            if ( sb.length() > 0 ) {
                sb.append(glue);
            }
            
            sb.append(o.toString());
        }
        
        return sb.toString();
    }
525513
public function implode($value, $glue = null)
		{
			$first = $this->first();

			if (is_array($first) || is_object($first)) {
				return implode($glue, $this->lists($value));
			}

			return implode($value, $this->items);
		}
42856
public function combine() {

		if(count($this -> values) > 0) {

			if(null !== $this -> glue) {
				return implode($this -> glue, $this -> values);
			}

			return vsprintf($this -> format, $this -> values);
		}
	}
664837
protected function parseJoin($join)
    {
        $result = implode(' ', $join);
        foreach($join as $item)
        {
            $this->params = array_merge($this->params, $item->getBinds());
        }
        return $result;
    }
44770
function leftJoin($relation, $expr = null)
    {
        return $this->join($relation, $expr, Join::LEFT);
    }
76844
public function toString(?JoinClauseStrategy $join = null, bool $useClause = true): string
    {
        return $this->fromToString($join, $useClause);
    }
975287
public function join($query)
    {
        $clause = '';
        $repository = $query->getRepository();
        $resources = $repository->getResources();
        $links = $resources->getLinks();
        foreach ($links as $link) {
            $type = strtoupper($link->resource->getLinkType());
            switch ($type) {
                case 'STRONG' : $type = 'INNER';break;
                case 'WEAK'   : $type = 'LEFT'; break;
            }
            $query->join($type, $link->resource->getName().' AS '.$this->_store->quoteName($link->resource->getAlias()), array(
                $link->child.'='.$link->parent,
            ));
        }

        $this->_links($query, $query->link);

        if (!empty($query->join)) {
            $joins = array();
            foreach ($query->join as $join) {
                $tmp = '';

                if (!empty($join['type'])) {
                    $tmp .= $join['type'].' ';
                }

                $tmp .= 'JOIN '.$join['resource'];
                $tmp .= ' ON '.implode(' AND ', $join['condition']);

                $joins[] = $tmp;
            }

            $clause = implode(' ', $joins);
        }

        return $clause;
    }
1283544
private function createJoin(string $operation, $join): string
    {
        $operation = strtolower($operation);
        if ($operation == 'left') {
            $operation = 'LEFT JOIN ';
        } elseif ($operation == 'right') {
            $operation = 'RIGHT JOIN ';
        } elseif ($operation == 'inner') {
            $operation = 'INNER JOIN ';
        } elseif ($operation == 'outer') {
            $operation = 'OUTER JOIN';
        } else {
            trigger_error('连接操作符无法识别:' . $operation, E_USER_ERROR);
        }

        //字符串
        if (is_string($join)) {
            //检查其中是否有别名要求
            $matches = null;
            if (!preg_match('/.+(\sas\s).+/i', $join, $matches)) {
                return $operation . $this->createTableName($join);
            }

            //分解原名与别名
            $parts = explode($matches[1], $join);
            if (count($parts) != 2) {
                trigger_error('要连接的表名无法识别:' . $join, E_USER_ERROR);
            }

            //返回带别名的JOIN语句
            return $operation . $this->createTableName($parts[0]) . ' AS ' . $this->createTableName($parts[1]);
        }

        //必须是字符串或数组
        if (!is_array($join)) {
            trigger_error('要连接的表必须使用字符串或数组表示:' . json($join), E_USER_ERROR);
        }

        //数组必须只有一个键值对
        if (count($join) > 1) {
            trigger_error('一次只能连接一个表:' . json($join), E_USER_ERROR);
        }

        $k = array_keys($join)[0];
        $v = array_values($join)[0];

        //只有值,无键
        if (is_int($k)) {
            return $operation . $this->createTableName($v);
        }

        //键值表示别名
        return $operation . $this->createTableName($k) . ' AS ' . $this->createTableName($v);
    }
1102325
public function join(Join $join)
    {
        $takenAliases = $this->getTakenAliases();

        if (in_array($join->getAlias(), $takenAliases, true)) {
            throw InvalidArgumentException::format(
                'Invalid join supplied to %s::%s: alias \'%s\' is already taken, taken aliases are (%s)',
                get_class($this), __FUNCTION__, $join->getAlias(), Debug::formatValues($takenAliases)
            );
        }


        $this->joins[] = $join;

        return $this;
    }
343485
public function addJoin($join)
    {
        if (!$this->joins->contains($join)) {
            $this->joins[] = $join;
        }

        return $this;
    }
264278
public function innerJoin($join, $on = null)
    {
        $this->getJoins()->innerJoin($join, $on);

        return $this;
    }
1125337
private void appendJoin(StringBuffer where, StringBuffer buf, Join join)
    {
        buf.append(",");
        appendTableWithJoins(join.right, where, buf);
        if (where.length() > 0)
        {
            where.append(" AND ");
        }
        join.appendJoinEqualities(where);
    }
279811
@SuppressWarnings({ "rawtypes", "unchecked" })
    public static String join(final Map value, final String delim) {
        if (value == null || value.isEmpty()) {
            return "";
        }
        final StringBuilder buf = new StringBuilder();
        for (final Iterator<Map.Entry<String, String>> i = value.entrySet().iterator(); i.hasNext();) {
            final Map.Entry<String, String> e = i.next();
            buf.append(e.getKey()).append(EQUAL).append(e.getValue());
            if (i.hasNext()) {
                buf.append(delim);
            }
        }
        return buf.toString();
    }
619020
public static function implode($glue, $pieces)
	{
		$pieces = static::asArray($pieces);

		return static::is_array($pieces) ? implode($glue, $pieces) : NULL;
	}
1286180
protected function processJoin(Join $join, $context): Join
    {
        $table = $this->processTable($join->table, $context);
        $criteria = [];
        foreach ($join->criteria as $index => $criterion) {
            $criteria[$index] = $this->processCriterion($criterion, $context);
        }

        if ($table === $join->table && $criteria === $join->criteria) {
            return $join;
        } else {
            return new Join($join->type, $table, $join->tableAlias, $criteria);
        }
    }
1258041
protected function parseJoin($join, $options = [])
    {
        $joinStr = '';
        if (!empty($join)) {
            foreach ($join as $item) {
                list($table, $type, $on) = $item;
                $condition = [];
                foreach ((array)$on as $val) {
                    if (strpos($val, '=')) {
                        list($val1, $val2) = explode('=', $val, 2);
                        $condition[] = $this->parseKey($val1, $options) . '=' . $this->parseKey($val2, $options);
                    } else {
                        $condition[] = $val;
                    }
                }

                $table   = $this->parseTable($table, $options);
                $joinStr .= ' ' . $type . ' JOIN ' . $table . ' ON ' . implode(' AND ', $condition);
            }
        }
        return $joinStr;
    }