用户
 找回密码
 入住 CI 中国社区
搜索
查看: 4964|回复: 11
收起左侧

[讨论/交流] /控制器/方法/參數1/參數2/參數3 ,參數可否傳遞物件進去

[复制链接]
发表于 2010-6-10 11:00:47 | 显示全部楼层 |阅读模式
uri 透過 router 會被解為
/控制器/方法/參數1/參數2/參數3

假如今天我的 my_method 方法 為下

function my_method( $obj ){

    $title = $obj->title;
    $subject = $obj->subject ;

}

這邊可以以物件當參數帶入嗎?
因為我看了好幾個範例都是以一個字串或是數字帶入
平常在瀏覽器也無法這樣打一個物件進去做連結


但好像帶入物件,可以使 my_method 更有彈性
就不受限它有多少參數了
還是有類似的做法嗎?
一起討論吧
发表于 2010-6-10 11:40:41 | 显示全部楼层
URL 如何传递对象?你怎么构造这样的 URL?
URL 就是一个纯字符的东西,让他传递对象,不太可能。。。
 楼主| 发表于 2010-6-10 11:54:35 | 显示全部楼层
回复 2# Hex


    對阿~ 我看 URL 的外部參數都是給個編號或是字串的
    像是 /blog/article/1
    或是 /blog/new/all

    好像只有在 php 內部參數才能丟物件
    例如視圖中 :
    $this->load->view('blog',$data);
发表于 2010-6-10 12:34:32 | 显示全部楼层
是呀,URL 只能传递简单的数据,你看见过那个网站的 URL 传递对象?
不过可以传递序列化后的对象,然后在 PHP 中反序列化一下。
发表于 2010-6-10 14:29:35 | 显示全部楼层
如果你希望后面的参数有弹性,也就是说可能有多种参数组合,那么可以考虑以下两种方式实现:

1. 给参数设置默认值:

function my_method(arg1, arg2 = 0, arg3 = '', arg4 = 'ok') {}

这样你在构造URL的时候就可以用:
/controller/method/arg1
/controller/method/arg1/arg2
/controller/method/arg1/arg2/arg3
.....

2.第二种方式是用func_get_args让PHP在runtime的时候动态获取它的参数:

PHP复制代码
 
<?php
function foo()
{
    $numargs = func_num_args();
    echo "Number of arguments: $numargs<br />\n";
    if ($numargs >= 2) {
        echo "Second argument is: " . func_get_arg(1) . "<br />\n";
    }
    $arg_list = func_get_args();
    for ($i = 0; $i < $numargs; $i++) {
        echo "Argument $i is: " . $arg_list[$i] . "<br />\n";
    }
}
 
foo(1, 2, 3);
?>
 
复制代码
 楼主| 发表于 2010-6-10 15:13:00 | 显示全部楼层
回复 5# saturn


function my_method(arg1, arg2 = 0, arg3 = '', arg4 = 'ok') {}
/controller/method/arg1
/controller/method/arg1/arg2
/controller/method/arg1/arg2/arg3

如果只想傳 arg2 跟 arg3
URL 變成
/controller/method//arg2/arg3
arg1直接空下來這樣嗎?

---------------------------------------------------------------------------

我覺得第二種方式 func_get_args 很不錯,可以不限制參數
my_method 依照參數有多少個去作邏輯判斷,再去分別處裡

因為 php 現在好像不可以讓他自己去抓要用哪個 function
my_method ( arg1 ){}
my_method ( arg1 , arg2 ){}
my_method ( arg1 , arg2 , arg3 ){}
发表于 2010-6-10 16:18:29 | 显示全部楼层
url 中间不能空着吧,我觉得。
发表于 2010-6-10 21:14:20 | 显示全部楼层
回复 6# minigogo701125

    两个segment之间是不能为空的。但你的这个描述让我想起了一种解决方案,那就是用CI中的路由来完成(下面的代码来自我写的部落格程式stblog),比如:

PHP复制代码
 
//注意路由的顺序
$route['archives/(\d{4})'] = 'home/archives/$1/0/0/p1';
$route['archives/(\d{4})/(\d{2})'] = 'home/archives/$1/$2/0/p1';
$route['archives/(\d{4})/(\d{2})/(\d{2})'] = 'home/archives/$1/$2/$3/p1';
$route['archives/(\d{4})/p([0-9]+)'] = 'home/archives/$1/0/0/$2';
$route['archives/(\d{4})/(\d{2})/p([0-9]+)'] = 'home/archives/$1/$2/0/$3';
$route['archives/(\d{4})/(\d{2})/(\d{2})/p([0-9]+)'] = 'home/archives/$1/$2/$3/$4';
 
复制代码


上面的router规则可以在源代码的config/routes.php中找到。它所做的功能就是将URL传递过来的参数做简单的分发(dispatch),将值传递到合适的method当中去。也就是说,method的初始值可以在route中完成(代码段中的右边部分,0就是我们的初始值,它并不出现在url中)。这样应该可以完美解决你的这个问题。

    你后面说的是类似Java和.NET那种Strong object-oriented 语言的overloading,在PHP中是不支持这种overload的。但可以通过我说的那种func_get_args来模拟,比如:
PHP复制代码
function test() {
    $args = function_get_args();
    swtich (count($args)) {
        case 1:
            // one argument passed
            break;
        case 2:
            // two arguments passed
            break;
        default:
            // illegal numer of arguments
            break;
    }
}
 
复制代码


BTW:PHP 5有一种特性也叫做overload,但是原理和实现与Java中的overload不通,具体可以看看PHP Manual。

由于这个论坛使用的是简体中文,所以台湾的朋友看起来可能不习惯。受苦了:)。建议hex增加个简体繁体转换插件(不知道Discuz是否提供,就是JS的那种)。
 楼主| 发表于 2010-6-11 11:11:45 | 显示全部楼层
回复 8# saturn

router.php 我需要時間慢慢體會了
因為我的功力還不足
不過好像有那麼一點感覺了

我不清楚我會不會遇到這樣傳遞參數的問題
只是突然好奇想到,來討論看看
這些討論很受用
到時候有遇到這樣的問題就可以用這幾個方式去應用

現在很多台灣人平常看電影的字幕也都是簡體中文
可能有些名詞用的字不同,但都可以體會到大概是什麼意思
发表于 2010-6-12 07:58:48 | 显示全部楼层
我觉得楼主的问题有一直可以解决的办法,我的个人看法是可以通常传递类名的形式,然后在控制器中实例化类
PHP复制代码
 
function my_method( $object ){
 
    $obj  = new $object;
    $title = $obj->title;
    $subject = $obj->subject ;
 
}
 
复制代码

然后还得结合php5的类的自动加载功能,参考一下ci第三方类库Datamapper的实现方式
PHP复制代码
 
//DataMapper::autoload静态方法首先在APPPATH的model文章就寻找类,如果没有找到就
//在子文件夹中递归搜索
spl_autoload_register('DataMapper::autoload');
        static function autoload($class)
        {
                // Don't attempt to autoload CI_ or MY_ prefixed classes
                if (in_array(substr($class, 0, 3), array('CI_', 'MY_')))
                {
                        return;
                }
 
                // Prepare class
                $class = strtolower($class);
 
                // Prepare path
                $path = APPPATH . 'models';
 
                // Prepare file
                $file = $path . '/' . $class . EXT;
 
                // Check if file exists, require_once if it does
                if (file_exists($file))
                {
                        require_once($file);
                }
                else
                {
                        // Do a recursive search of the path for the class
                        DataMapper::recursive_require_once($class, $path);
                }
        }
 
        // --------------------------------------------------------------------
 
        /**
         * Recursive Require Once
         *
         * Recursively searches the path for the class, require_once if found.
         *
         * @access      public
         * @param       string
         * @param       string
         * @return      void
         */

        static function recursive_require_once($class, $path)
        {
                if ($handle = opendir($path))
                {
                        while (FALSE !== ($dir = readdir($handle)))
                        {
                                // If dir does not contain a dot
                                if (strpos($dir, '.') === FALSE)
                                {
                                        // Prepare recursive path
                                        $recursive_path = $path . '/' . $dir;
 
                                        // Prepare file
                                        $file = $recursive_path . '/' . $class . EXT;
 
                                        // Check if file exists, require_once if it does
                                        if (file_exists($file))
                                        {
                                                require_once($file);
 
                                                break;
                                        }
                                        else if (is_dir($recursive_path))
                                        {
                                                // Do a recursive search of the path for the class
                                                DataMapper::recursive_require_once($class, $recursive_path);
                                        }
                                }
                        }
 
                        closedir($handle);
                }
        }
 
 
复制代码

本版积分规则