src/Query.php
public function join(
        $foreign_table,
        $master_field = null,
        $join_kind = null,
        $_foreign_alias = null
    ) {
        // If array - add recursively
        if (is_array($foreign_table)) {
            foreach ($foreign_table as $alias => $foreign) {
                if (is_numeric($alias)) {
                    $alias = null;
                }

                $this->join($foreign, $master_field, $join_kind, $alias);
            }

            return $this;
        }
        $j = [];

        // try to find alias in foreign table definition
        if ($_foreign_alias === null) {
            list($foreign_table, $_foreign_alias) = array_pad(explode(' ', $foreign_table, 2), 2, null);
        }

        // Split and deduce fields
        list($f1, $f2) = array_pad(explode('.', $foreign_table, 2), 2, null);

        if (is_object($master_field)) {
            $j['expr'] = $master_field;
        } else {
            // Split and deduce primary table
            if ($master_field === null) {
                list($m1, $m2) = [null, null];
            } else {
                list($m1, $m2) = array_pad(explode('.', $master_field, 2), 2, null);
            }
            if ($m2 === null) {
                $m2 = $m1;
                $m1 = null;
            }
            if ($m1 === null) {
                $m1 = $this->main_table;
            }

            // Identify fields we use for joins
            if ($f2 === null && $m2 === null) {
                $m2 = $f1.'_id';
            }
            if ($m2 === null) {
                $m2 = 'id';
            }
            $j['m1'] = $m1;
            $j['m2'] = $m2;
        }

        $j['f1'] = $f1;
        if ($f2 === null) {
            $f2 = 'id';
        }
        $j['f2'] = $f2;

        $j['t'] = $join_kind ?: 'left';
        $j['fa'] = $_foreign_alias;

        $this->args['join'][] = $j;

        return $this;
    }
public function join(
        $foreign_table,
        $master_field = null,
        $join_kind = null,
        $_foreign_alias = null
    ) {
        // If array - add recursively
        if (is_array($foreign_table)) {
            foreach ($foreign_table as $alias => $foreign) {
                if (is_numeric($alias)) {
                    $alias = null;
                }

                $this->join($foreign, $master_field, $join_kind, $alias);
            }

            return $this;
        }
        $j = [];

        // try to find alias in foreign table definition
        if ($_foreign_alias === null) {
            list($foreign_table, $_foreign_alias) = array_pad(explode(' ', $foreign_table, 2), 2, null);
        }

        // Split and deduce fields
        list($f1, $f2) = array_pad(explode('.', $foreign_table, 2), 2, null);

        if (is_object($master_field)) {
            $j['expr'] = $master_field;
        } else {
            // Split and deduce primary table
            if ($master_field === null) {
                list($m1, $m2) = [null, null];
            } else {
                list($m1, $m2) = array_pad(explode('.', $master_field, 2), 2, null);
            }
            if ($m2 === null) {
                $m2 = $m1;
                $m1 = null;
            }
            if ($m1 === null) {
                $m1 = $this->main_table;
            }

            // Identify fields we use for joins
            if ($f2 === null && $m2 === null) {
                $m2 = $f1.'_id';
            }
            if ($m2 === null) {
                $m2 = 'id';
            }
            $j['m1'] = $m1;
            $j['m2'] = $m2;
        }

        $j['f1'] = $f1;
        if ($f2 === null) {
            $f2 = 'id';
        }
        $j['f2'] = $f2;

        $j['t'] = $join_kind ?: 'left';
        $j['fa'] = $_foreign_alias;

        $this->args['join'][] = $j;

        return $this;
    }
Joins your query with another table. Join will use $main_table
to reference the main table, unless you specify it explicitly.

Examples:
$q->join('address');         // on user.address_id=address.id
$q->join('address.user_id'); // on address.user_id=user.id
$q->join('address a');       // With alias
$q->join(array('a'=>'address')); // Also alias

Second argument may specify the field of the master table
$q->join('address', 'billing_id');
$q->join('address.code', 'code');
$q->join('address.code', 'user.code');

Third argument may specify which kind of join to use.
$q->join('address', null, 'left');
$q->join('address.code', 'user.code', 'inner');

Using array syntax you can join multiple tables too
$q->join(array('a'=>'address', 'p'=>'portfolio'));

You can use expression for more complex joins
$q->join('address',
$q->orExpr()
->where('user.billing_id=address.id')
->where('user.technical_id=address.id')
)

@param string|array $foreign_table  Table to join with
@param mixed        $master_field   Field in master table
@param string       $join_kind      'left' or 'inner', etc
@param string       $_foreign_alias Internal, don't use

@return $this