2014-04-11 47 views
5

Đây là câu hỏi tiếp theo về câu hỏi trước của tôi.Chức năng gán một tham số không phải là rỗng

Run a function without a parameter but needed a variable outside of the function - PHP

tôi nhận được câu trả lời này

function foo($arg1 = null, $arg2 = null) { 
    // if they are not set retrieve from a session 
    $arg1 = ($arg1 !== null) ? $arg1 : $_SESSION['arg1']; 
    // rinse repeat. 
} 

Vì vậy, tôi đã nghĩ, có lẽ tôi có thể làm giảm dòng mã bằng cách ngăn chặn gọi biến giống nhau trên mỗi chức năng duy nhất.

Tôi đã nghĩ ra điều này.

function foo($arg1 = $_SESSION['user_id'], $arg2 = $_SESSION['campaign_id']) { 
    //do something 
} 

Thật không may, tôi đã nhận được lỗi này.

Parse error: syntax error, unexpected T_VARIABLE 

Có lý do gì khiến kết quả này không? Tôi vừa thay thế các số null bằng biến có giá trị trong đó.

Có cách nào để gán một hàm có tham số đã có giá trị thay vì gán một giá trị rỗng không?

P.S.

Tôi đang cố gắng xuất dữ liệu bằng cách sử dụng echo $campaign->getName(), vì vậy không có tham số nào được cung cấp khi gọi hàm.

Vì vậy, tôi đang cố gắng để gọi một chức năng một cái gì đó như thế này

function foo($arg1 = $_SESSION['user_id'], $arg2 = $_SESSION['campaign_id']) { 
    //do something 
} 

Nếu có cách nào để làm điều đó mà không gọi biến tương tự hơn và hơn nữa.

Mọi trợ giúp sẽ được đánh giá cao. :)

+0

Vui lòng liên kết câu hỏi trước của bạn, vì chúng tôi không biết bạn đang nói về điều gì. [sửa] câu hỏi của bạn) –

+0

Có bạn đi, đã đặt nó vào.: D –

+0

Trong trường hợp cụ thể của một cái gì đó như '$ _SESSION ['user_id']' - tức là một giá trị mà nên duy trì liên tục trong suốt thời gian thực hiện của tập lệnh - bạn * có thể * định nghĩa nó như là một hằng số 'define ('APP_USER_ID', $ _SESSION ['user_id']);' và sau đó hằng số có thể được sử dụng như giá trị mặc định 'function foo ($ arg = APP_USER_ID) {} '. Mặc dù điều này có vẻ là một lựa chọn hấp dẫn (và thực tế khá phổ biến trong thế giới thực), nhưng không * được khuyến khích vì các lý do dựa vào tình trạng toàn cầu, như được nêu trong một vài câu trả lời dưới đây. – DaveRandom

Trả lời

8

tl; dr

Đừng cố gắng đó (nó thực sự thậm chí không làm việc như bạn nhìn thấy), sử dụng DI (dependency injection) thích hợp và thông qua bên ngoài biến (toàn cầu) của bạn như thông số:

// functions should be deterministic — require the arguments in favour of using dynamic defaults 
function foo($arg1 /* require it */, $arg2 = 1 /* static scalars as default is no problem */) { 
    // your code 
} 
foo($_SESSION["user_id"]); // always pass dynamic arguments, don't fetch them in the function 

Giới thiệu

Nó không phải là có thể sử dụng bất cứ thứ gì như mặc định như cái gọi là vô hướng tĩnh. Đây là các hằng số (chuỗi, số nguyên, v.v.), hằng số và (kể từ PHP 5.6) hoạt động trên các hằng số/hằng số này.

Vậy ...

tôi đã có ý tưởng tuyệt vời cùng hơn hai năm trước đây và nộp một báo cáo lỗi ... https://bugs.php.net/bug.php?id=60544

Hôm nay tôi nghĩ đó là một ý tưởng không quá tuyệt vời. Giá trị mặc định được cho là tĩnh bởi ngôn ngữ. Tôi nghi ngờ những người thiết kế PHP đã không có lý do của họ.

Nhưng vẫn có một cách ...

Làm thế nào bạn có thể làm điều đó (không khuyến khích)

Cách giải quyết duy nhất ở đây là sử dụng hằng số.

function foo($arg = ARG) { 
    var_dump($arg); 
} 

Tại thời điểm khi bạn chắc chắn rằng giá trị sẽ không thay đổi nữa, xác định hằng số trước khi cuộc gọi đầu tiên của hàm:

define("ARG", $_SESSION["user_id"]); 

Sau đó, bạn có thể sau đó chỉ cần gọi nó qua foo();.

Điều này có thể do đánh giá các hằng số ở đây một cách lười biếng.

Hạn chế của phương pháp này là bạn phải xác định hằng số một lần và sau đó nó sẽ vẫn không đổi cho phần còn lại của thời gian chạy tập lệnh.

Nhưng tôi vẫn mạnh mẽ không khuyên bạn nên. Đó là hackish và có nhược điểm lớn.

Làm thế nào bạn có thể làm điều đó tốt hơn

Bạn đã chỉ ra cho chúng ta một cách làm thế nào để làm điều đó:

$arg1 = ($arg1 !== null) ? $arg1 : $_SESSION['arg1']; 

Đó hoàn toàn là cách chính xác. Nếu bạn thực sự muốn làm điều đó.

Nhưng bạn vẫn còn không nên làm điều đó. Bạn đang truy cập phạm vi toàn cầu (superglobals) từ một hàm.

Làm thế nào bạn nên làm điều đó

Có một lý do tại sao các nhà thiết kế ngôn ngữ đã không thực hiện khả năng này và nó là như nhau tại sao chúng ta không nên cố gắng để phá vỡ rằng trong bất kỳ cách nào bởi hằng số hoặc truy cập phạm vi toàn cầu trong các chức năng.

Bạn thực sự nên sử dụng đúng cách tiêm phụ thuộc và chuyển các giá trị bên ngoài (toàn cục) cho các hàm thông qua tham số. (xem ví dụ trong tl; dr phần)

Thể loại mã bạn đang đề xuất có thể dễ dàng dẫn đến mã khó gỡ rối vì mọi người có thể không truy cập được trạng thái toàn cầu. Đó là lý do tại sao chức năng phải có đầu ra xác định cho một đầu vào cụ thể (ngoại trừ nếu chúng được cho là không xác định, ví dụ: một hàm đọc một tệp), làm tăng đáng kể khả năng thử nghiệm và tính di động.

6

Bạn không thể.

Bạn chỉ có thể gán literals cho các giá trị mặc định, giá trị không đổi không thể thay đổi trong thời gian chạy. Điều đó có nghĩa là, "actual strings", số (42), mảng được mã hóa cứng ([1, 2, 3]), NULL. Và không phải $variables, function() {} hoặc bất kỳ thứ gì khác có thể thay đổi khi chạy.

Bạn cũng vậy.

Nếu bạn hoạt động phụ thuộc vào một ID người dùng và ID chiến dịch, bạn nên chuyển chúng vào chức năng của bạn, và không phải dựa vào họ đang ở PHIÊN vì bạn không thể biết nếu họ thực sự đang ở đó!.

Không dựa vào hình cầu.


Tại sao không chuyển các tham số cho hàm? Nó cần chúng, phải không? Bạn có mong đợi hàm sau hoạt động mà không có tham số không?

add($x, $y) 

Và chỉ vì những thông số đó được đưa từ SESSION, cơ sở dữ liệu hoặc thế giới vượt ra ngoài?

số Chức năng cần hai tham số, và như vậy, nó nên xincho hai tham số.

+0

Chắc chắn là câu trả lời tốt hơn. Gắn bó với những điều cơ bản. Cung cấp các biến của bạn hoặc sử dụng giá trị mặc định litaral. –

1

Tôi có tin xấu cho bạn, dưới hình thức ngắn hơn không phải lúc nào cũng tốt hơn. Điều này chủ yếu là vì bạn đang đề cập đến các giá trị $ _SESSION như hằng số, và điều đó không thực sự tốt. Mã tốt, vững chắc dài hơn vì tất cả việc kiểm tra và xác thực giúp tránh các lỗi không cần thiết. Điều này về cơ bản là những gì bạn cần làm:

function foo($arg1 = null, $arg2 = null) { 
    // if condition 
    if (!$arg1 && isset($_SESSION['arg1'])) 
     $arg1 = $_SESSION['arg1']; 

    // tenary condition 
    $arg2 = (!$arg2 && isset($_SESSION['arg2'])) ? $arg2 : $_SESSION['arg2']; 
} 

Nếu bạn thực sự muốn, bạn có thể tìm kiếm mã sẽ rút ngắn mã này nhưng không thực sự khác nhiều. Tất cả các xác thực đó là phải và không được bỏ qua.

1

Nhìn vào câu hỏi trước của bạn, tôi đoán bạn có một số phương pháp yêu cầu ID chiến dịch và ID người dùng. Tôi khuyên bạn nên chuyển ID chiến dịch và ID người dùng cho hàm tạo của lớp Chiến dịch. Sau đó, bạn có thể gọi bất kỳ phương pháp nào và luôn có quyền truy cập vào chúng:

<?php 

$campaign = new Campaign($db, $_SESSION['user_id'], $_SESSION['campaign_id']); 

class Campaign { 
    private $db; 
    private $user_id; 
    private $campaign_id; 

    public function __construct($db, $user_id, $campaign_id) { 
    $this->db = $db; 
    $this->user_id = $user_id; 
    $this->campaign_id = $campaign_id; 
    } 

    public function getName() { 
    $query = $this->db->prepare("SELECT name FROM campaign WHERE campaign_id = :campaign_id AND user_id = :user_id"); 
    $status = $query->execute(array(':campaign_id' => $this->campaign_id, ':user_id' => $this->user_id)); 
    return ($query->rowCount() == 1) ? $query->fetchObject()->name : false; 
    } 
} 
Các vấn đề liên quan