public static function set(&$target, $key, $value, $overwrite = true)
    {
        if (is_null($key)) {
            return $target;
        }

        if (!is_array($key)) {
            if (isset($target->{$key}) || property_exists($target, $key)) {
                if ($overwrite) {
                    $target->{$key} = self::value($value);
                }

                return $target;
            }

            $keys = explode('.', $key);
        } else {
            $keys = $key;
        }

        $keep = $target;

        while (count($keys) > 1) {
            $key = array_shift($keys);

            // If the key doesn't exist at this depth, we will just create an empty array
            // to hold the next value, allowing us to create the arrays to hold final
            // values at the correct depth. Then we'll keep digging into the array.
            if (!isset($target->{$key}) || !is_object($target->{$key}) && $overwrite) {
                $target->{$key} = new \stdClass;
            } elseif (!is_object($target->{$key})) {
                return $target;
            }

            $target = &$target->{$key};
        }


        $key = array_shift($keys);
        if (!isset($target->{$key}) || $overwrite) {
            $target->{$key} = self::value($value);
        }

        return $keep;
    }