2009-08-27 34 views
20

Có thể trong PHP 4/5 để chỉ định tham số tùy chọn được đặt tên khi gọi, bỏ qua những thông số bạn không muốn chỉ định (như trong python) không?được đặt tên là đối số tùy chọn PHP?

Cái gì như:

function foo($a,$b='', $c='') { 
    // whatever 
} 


foo("hello", $c="bar"); // we want $b as the default, but specify $c 

Cảm ơn

+2

Trên thực tế trong mẫu mã của bạn, các '$ c = "thanh"' được gán 'bar' đến một '$ c' trong * phạm vi người gọi * (không có trong các chức năng được gọi là' foo') và sau đó chuyển giá trị được gán cho 'foo()' làm tham số thứ hai, tham số này sẽ được nhận dưới dạng biến '$ b' cục bộ. – Petruza

Trả lời

21

Không, không thể: nếu bạn muốn chuyển tham số thứ ba, bạn phải chuyển thông số thứ hai. Và các tham số được đặt tên là không thể.


Một "giải pháp" sẽ chỉ sử dụng một thông số, một mảng và luôn vượt qua ... Nhưng không phải lúc nào cũng xác định mọi thứ trong đó.

Ví dụ:

function foo($params) { 
    var_dump($params); 
} 

Và gọi nó theo cách này:

foo(array(
    'a' => 'hello', 
)); 

foo(array(
    'a' => 'hello', 
    'c' => 'glop', 
)); 

foo(array(
    'a' => 'hello', 
    'test' => 'another one', 
)); 

sẽ giúp bạn có được kết quả này:

array 
    'a' => string 'hello' (length=5) 

array 
    'a' => string 'hello' (length=5) 
    'c' => string 'glop' (length=4) 

array 
    'a' => string 'hello' (length=5) 
    'test' => string 'another one' (length=11) 

Nhưng tôi không thực sự thích giải pháp này:

  • Bạn sẽ mất phần PHPDoc
  • IDE của bạn sẽ không thể cung cấp bất kỳ gợi ý nữa ... Đó là xấu

Vì vậy, tôi muốn đi với điều này chỉ trong những trường hợp rất cụ thể - cho các chức năng với nhiều thông số tùy chọn, ví dụ ...

+0

Xin lỗi cho OT, nhưng bạn có biết bất kỳ trình soạn thảo nào cung cấp gợi ý mã cho PHP không? bất kỳ cho MacOS? cảm ơn! – Petruza

+0

gợi ý mã? Tôi sẽ nói tất cả IDE làm (netbeans, Eclipse PDT, PHPStorm, ...); không có ý tưởng về Mac; nhưng những người có thể làm việc trên Mac –

+0

@Petruza trong trường hợp bạn chưa tìm thấy nó, hãy thử Coda cho MacOS. Có một công việc tốt đẹp của hinting cho PHP. – EFC

2

Với PHP, thứ tự của các đối số là những gì quan trọng. Bạn không thể chỉ định một đối số cụ thể ngoài vị trí, nhưng thay vào đó, bạn có thể bỏ qua đối số bằng cách chuyển một NULL, miễn là bạn không nhớ giá trị trong hàm của bạn có giá trị NULL.

foo("hello", NULL, "bar"); 
+1

NULL không phải là mặc định - không phải luôn luôn, và không phải trong trường hợp này: ở đây, mặc định sẽ là một chuỗi rỗng; và không, NULL và một chuỗi rỗng không phải là "giống nhau": xem toán tử === và! ==, ví dụ ... –

+0

Ồ, tôi đã không nhận ra đó là NULL thay vì trống, vì tôi luôn sử dụng '' làm mặc định và sau đó kiểm tra xem (! $ value) – davethegr8

3

Không, không phải vậy.

Cách duy nhất bạn có thể làm điều đó một phần là bằng cách sử dụng các mảng có các khóa có tên và những gì không.

+1

CakePHP-ít nhất- sử dụng mẫu này rộng rãi –

1

Nó không phải là chính xác, nhưng nó là lừa, một số có thể nói.

class NamedArguments { 

    static function init($args) { 
     $assoc = reset($args); 
     if (is_array($assoc)) { 
      $diff = array_diff(array_keys($assoc), array_keys($args)); 
      if (empty($diff)) return $assoc; 
      trigger_error('Invalid parameters: '.join(',',$diff), E_USER_ERROR); 
     } 
     return array(); 
    } 

} 

class Test { 

    public static function foobar($required, $optional1 = '', $optional2 = '') { 
     extract(NamedArguments::init(get_defined_vars())); 
     printf("required: %s, optional1: %s, optional2: %s\n", $required, $optional1, $optional2); 
    } 

} 

Test::foobar("required", "optional1", "optional2"); 
Test::foobar(array(
    'required' => 'required', 
    'optional1' => 'optional1', 
    'optional2' => 'optional2' 
    )); 
0

Đây là những gì tôi đã sử dụng. Một định nghĩa một hàm lấy một đối số mảng tùy chọn trong đó nêu rõ các đối số được đặt tên tùy chọn:

function func($arg, $options = Array()) { 
    $defaults = Array('foo' => 1.0, 
        'bar' => FALSE); 
    $options = array_merge($default, $options); 

    // Normal function body here. Use $options['foo'] and 
    // $options['bar'] to fetch named parameter values. 
    ... 
} 

Bạn thường có thể gọi mà không cần bất kỳ đối số tên:

func("xyzzy") 

Để chỉ định một tên đối số tùy chọn, vượt qua nó trong tùy chọn mảng:

func("xyzzy", Array('foo' => 5.7)) 
1

Bạn có thể giữ phpdoc và khả năng đặt mặc định bằng cách truyền đối tượng thay vì mảng, ví dụ:

class FooOptions { 
    $opt1 = 'x'; 
    $opt2 = 'y'; 
    /* etc */ 
}; 

đó cũng cho phép bạn làm kiểu kiểm tra nghiêm ngặt trong cuộc gọi chức năng của bạn, nếu bạn muốn:

function foo (FooOptions $opts) { 
    ... 
} 

Tất nhiên, bạn có thể trả tiền cho rằng với tính cách rườm rà thêm thiết lập phản đối các FooOptions. Không có chuyến đi hoàn toàn miễn phí, thật không may.

6

Không, PHP không thể chuyển đối số theo tên.

Nếu bạn có một chức năng mà mất rất nhiều tranh cãi và tất cả đều có giá trị mặc định, bạn có thể xem xét đưa ra các chức năng chấp nhận một mảng các đối số thay vì:

function test (array $args) { 
    $defaults = array('a' => '', 'b' => '', 'c' => ''); 
    $args = array_merge($defaults, array_intersect_key($args, $defaults)); 

    list($a, $b, $c) = array_values($args); 
    // an alternative to list(): extract($args); 

    // you can now use $a, $b, $c  
} 

See it in action.

0

Không thực sự. Có một vài lựa chọn thay thế cho nó bạn có thể sử dụng.

test(null,null,"hello") 

Hoặc vượt qua một mảng:

test(array('c' => "hello")); 

Sau đó, chức năng có thể là:

function test($array) { 
    $c = isset($array[c]) ? $array[c] : ''; 
} 

Hoặc thêm một chức năng ở giữa, nhưng tôi sẽ không đề nghị này:

function ctest($c) { test('','',$c); } 
0

Hãy thử function test ($a="",$b="",&$c=""){}

Đưa & trước $c

0

Tôi không nghĩ như vậy ... Nếu bạn cần phải gọi, ví dụ, substr chức năng, có 3 params, và muốn thiết chiều dài $ nếu không có đặt $ start, bạn sẽ bị buộc phải làm như vậy.

substr($str,0,10); 

một cách tốt đẹp để ghi đè này là luôn luôn sử dụng mảng cho các thông số

0

câu trả lời đơn giản. Không, bạn không thể.
Bạn có thể thử đi xung quanh nó bằng cách truyền vào một đối tượng/mảng hoặc sử dụng một số mẫu phun phụ thuộc khác.

Ngoài ra, cố gắng sử dụng null chứ không phải là chuỗi rỗng vì nó là rõ ràng hơn để kiểm tra sự tồn tại của họ sử dụng is_null()

ví dụ:

function test ($a=null,$b=null,$c=null){ 
if (is_null($a) { 
    //do something about $a 
} 
if (is_null($b) { 
    //do something about $b 
} 
if (is_null($c) { 
    //do something about $c 
} 
} 

để gọi đây là:

test(null,null,"Hello"); 
0

Trong rất ngắn, đôi khi có, bằng cách sử dụng các biến phản ánh và gõ. Tuy nhiên tôi nghĩ rằng điều này có lẽ không phải là những gì bạn đang sau.

Một giải pháp tốt hơn cho vấn đề của bạn có lẽ là để vượt qua trong vòng 3 lập luận như các chức năng xử lý các thiếu một bên hàm của bạn mình

<?php 
    function test(array $params) 
    { 
    //Check for nulls etc etc 
    $a = $params['a']; 
    $b = $params['b']; 
    ...etc etc 
    } 
0

Bạn không thể làm điều đó một cách python. Anway, bạn có thể vượt qua một mảng kết hợp và so với sử dụng các mục mảng bằng tên của họ:

function test ($args=array('a'=>'','b'=>'','c'=>'')) 
{ 
    // do something 
} 

test(array('c'=>'Hello')); 

này không làm giảm đánh máy, nhưng ít nhất nó mô tả nhiều hơn, có tên người lập luận rõ ràng và dễ đọc trong gọi điện.

+1

Ermmm, đó không phải là cú pháp php hợp lệ! –

+0

Xin lỗi, nó phải được sửa ngay bây giờ. –

1

Thông thường bạn không thể nhưng tôi nghĩ có rất nhiều cách để chuyển đối số đã đặt tên cho hàm PHP. Cá nhân tôi chuyển tiếp vào định nghĩa sử dụng mảng và chỉ cần gọi những gì tôi cần phải vượt qua:

class Test{ 
    public $a = false; 
    private $b = false; 
    public $c = false; 
    public $d = false; 
    public $e = false; 
    public function _factory(){ 
     $args = func_get_args(); 
     $args = $args[0]; 
     $this->a = array_key_exists("a",$args) ? $args["a"] : 0; 
     $this->b = array_key_exists("b",$args) ? $args["b"] : 0; 
     $this->c = array_key_exists("c",$args) ? $args["c"] : 0; 
     $this->d = array_key_exists("d",$args) ? $args["d"] : 0; 
     $this->e = array_key_exists("e",$args) ? $args["e"] : 0; 
    } 
    public function show(){ 
     var_dump($this); 
    } 
} 


$test = new Test(); 
$args["c"]=999; 
$test->_factory($args); 
$test->show(); 

dụ sống ở đây: http://sandbox.onlinephpfunctions.com/code/d7f27c6e504737482d396cbd6cdf1cc118e8c1ff

Nếu tôi phải vượt qua 10 đối số, và 3 trong số đó là các dữ liệu tôi thực sự cần, thậm chí không SMART để vượt qua thành chức năng giống như

return myfunction(false,false,10,false,false,"date",false,false,false,"desc"); 

với cách tiếp cận tôi đưa ra, bạn có thể thiết lập bất kỳ của 10 đối số vào một mảng:

$arr['count']=10; 
$arr['type']="date"; 
$arr['order']="desc"; 
return myfunction($arr); 

Tôi có một bài đăng trong blog của mình giải thích quy trình này để biết thêm chi tiết.

http://www.tbogard.com/2013/03/07/passing-named-arguments-to-a-function-in-php

2

Tính đến PHP 5.4 bạn có cú pháp mảng viết tắt (không nessecary để xác định mảng với "mảng" cồng kềnh và thay vào đó sử dụng "[]").

Bạn có thể bắt chước tên tham số trong nhiều cách, một tốt và cách đơn giản có thể là:

bar('one', ['a1' => 'two', 'bar' => 'three', 'foo' => 'four']); 
// output: twothreefour 

function bar ($a1, $kwargs = ['bar' => null, 'foo' => null]) { 
    extract($kwargs); 
    echo $a1; 
    echo $bar; 
    echo $foo; 
} 
+0

Nhưng không phải '$ bar' sẽ không được xác định nếu tôi gọi là' bar ('one', ['x' => 'blah']); '? Ngay cả trong kịch bản này, 'trích xuất()' có vẻ nguy hiểm và không cần thiết… – binki

0

Đây là một công trình xung quanh:

function set_param_defaults($params) { 
    foreach($params['default_values'] as $arg_name => $arg_value) { 
    if (!isset($params[$arg_name])) { 
     $params[$arg_name] = $arg_value; 
    } 
    } 

    return $params; 
} 

function foo($z, $x = null, $y = null) { 
    $default_values = ['x' => 'default value for x', 'y' => 'default value for y']; 
    $params = set_param_defaults(get_defined_vars()); 

    print "$z\n"; 
    print $params['x'] . "\n"; 
    print $params['y'] . "\n"; 
} 

foo('set z value', null, 'set y value'); 
print "\n"; 
foo('set z value', 'set x value'); 

Hoặc: Cá nhân tôi sẽ đi với phương pháp này.

function foo($z, $x_y) { 
    $x_y += ['x' => 'default value for x', 'y' => 'default value for y']; 

    print "$z\n"; 
    print $x_y['x'] . "\n"; 
    print $x_y['y'] . "\n"; 
} 

foo('set z value', ['y' => 'set y value']); 
print "\n"; 
foo('set z value', ['x' => 'set x value']); 

In ra cho cả hai ví dụ.

gọi 1st:

  • giá trị đặt z
  • giá trị mặc định cho x
  • bộ y giá trị

2 cuộc gọi:

  • bộ giá trị z
  • se t x value
  • giá trị mặc định cho y
0

Chỉ cần sử dụng mẫu mảng liên kết Drupal sử dụng. Đối với các đối số mặc định tùy chọn, chỉ chấp nhận đối số $options là một mảng kết hợp. Sau đó, sử dụng toán tử mảng + để đặt bất kỳ khóa bị thiếu nào trong mảng.

function foo ($a_required_parameter, $options = array()) { 
    $options += array(
     'b' => '', 
     'c' => '', 
    ); 
    // whatever 
} 

foo('a', array('c' => 'c’s value')); // No need to pass b when specifying c. 
Các vấn đề liên quan