Truy cập một biến toàn cục trong một hàm PHP


82

Theo hầu hết các quy tắc về phạm vi ngôn ngữ lập trình, tôi có thể truy cập các biến được định nghĩa bên ngoài các hàm bên trong chúng, nhưng tại sao mã này không hoạt động?

<?php
    $data = 'My data';

    function menugen() {
        echo "[" . $data . "]";
    }

    menugen();
?>

Đầu ra là [].


3
Đừng đối xử với nó như toàn cầu, vượt qua nó với chức năng như một cuộc tranh cãi
Mark Baker

2
Sách hướng dẫn ở đâu nói những điều như vậy?
dối trá


Kiểm tra ví dụ thứ hai trong trang này: php.net/manual/en/language.variables.scope.php
Amin Gholibeigian

afaik chúng ta có thể truy cập bằng cách sử dụng $ GLOBALS ['varname'] trong đó chỉ mục "varname" là $ varname bên ngoài hàm. Trongfact chúng ta có thể sử dụng print_r ($ GLOBALS) để xem tất cả các biến toàn cục.
Ahmad

Câu trả lời:


162

Nó không hoạt động vì bạn phải khai báo biến toàn cục nào bạn sẽ truy cập:

$data = 'My data';

function menugen() {
    global $data; // <-- Add this line

    echo "[" . $data . "]";
}

menugen();

Nếu không, bạn có thể truy cập nó như $GLOBALS['data']. Xem Phạm vi biến .

Ngay cả khi hơi lạc đề một chút, tôi khuyên bạn nên tránh sử dụng hình cầu và thích chuyển dưới dạng tham số.


Cảm ơn, Bạn nói đúng nhưng họ không sử dụng dòng này trong ví dụ thứ hai của cuốn cẩm nang: php.net/manual/en/language.variables.scope.php
Amin Gholibeigian

6
Trong thực tế rằng ví dụ thứ hai là có để hiển thị các độc giả những gì không phải làm:This script will not produce any output because the echo statement refers to a local version of the $a variable, and it has not been assigned a value within this scope.
Matteo Tassinari

2
Dang! Tôi đã phải đăng nhập để ủng hộ câu trả lời này chỉ vì tôi đáng sợ quên các biến php phạm vi.
Milche Patern

19

Bạn có thể thực hiện một trong những cách sau:

<?php
    $data = 'My data';

    function menugen() {
        global $data;
        echo "[" . $data . "]";
    }

    menugen();

Hoặc là

<?php
    $data = 'My data';

    function menugen() {
        echo "[" . $GLOBALS['data'] . "]";
    }

    menugen();

Điều đó đang được nói, lạm dụng các hình cầu có thể dẫn đến một số mã kém. Thông thường tốt hơn là bạn nên vượt qua những gì bạn cần. Ví dụ, thay vì tham chiếu đến một đối tượng cơ sở dữ liệu toàn cục, bạn nên chuyển vào một xử lý cho cơ sở dữ liệu và hành động theo đó. Đây được gọi là tiêm phụ thuộc . Nó làm cho cuộc sống của bạn dễ dàng hơn rất nhiều khi bạn triển khai thử nghiệm tự động (điều bạn nên làm).


12

Đó là một vấn đề về phạm vi. Nói tóm lại, nên tránh các biến toàn cục để :

Bạn cần chuyển nó dưới dạng tham số:

$data = 'My data';

function menugen($data)
{
    echo $data;
}

Hoặc có nó trong một lớp học và truy cập nó

class MyClass
{
    private $data = "";

    function menugen()
    {
        echo this->data;
    }

}

Hãy xem câu trả lời @MatteoTassinari, vì bạn có thể đánh dấu nó là toàn cục để truy cập, nhưng các biến toàn cục thường không bắt buộc, vì vậy, sẽ là khôn ngoan khi suy nghĩ lại cách viết mã của bạn.


và một cách khác là sử dụng từ khóa global (được cấp phép, đây không phải là cách tốt nhất).
Jocelyn

1
"Nên" không trả lời câu hỏi và đây có thể không phải là cách tiếp cận tốt nhất cho mọi trường hợp. Đối với các tập lệnh đơn giản, việc thay đổi các tham số xung quanh và thêm các lớp là rất khó. Giống như JavaScript, trong PHP, không phải mọi thứ đều cần phải hướng đối tượng và đặt tên lên wazoo.
Beejor

@Beejor Cho rằng OP có một chức năng được gọi là menugen()nó ngụ ý rằng sẽ có nhiều công việc hơn là chỉ tạo một menu. Ví dụ: mở rộng menu đó để thêm nhiều mục từ một nguồn khác thì sao, chọn trang hiện đang chọn trong menu thì sao. Việc có các vars và logic toàn cầu ngẫu nhiên ở khắp nơi kêu gọi thiết kế OOP. Thực tế là PHP / JS không cần phải có cấu trúc là một trong những lý do lớn nhất khiến bạn tìm thấy rất nhiều đoạn mã lộn xộn. Nó có thể được thực hiện rất tốt nhưng cho phép mọi người không có suy nghĩ về khả năng bảo trì trong tương lai.
webnoob

ps Down biểu quyết câu trả lời cũng hơi lệch. Câu trả lời cung cấp một giải pháp cho vấn đề của OP, chỉ vì bạn không thích nó, không làm cho nó sai.
webnoob

1
@Beejor - Vấn đề với lập luận đó là mọi người có thể nghĩ rằng họ cần một biến toàn cục vì họ không biết cái nào tốt hơn và sẽ không biết cái nào tốt hơn trừ khi họ được nói.
webnoob

10

Một cách khác để làm điều đó:

<?php

$data = 'My data';

$menugen = function() use ($data) {

    echo "[".$data."]";
};

$menugen();

CẬP NHẬT 2020-01-13: do Peter Mortensen yêu cầu

Kể từ PHP 5.3.0, chúng tôi có hỗ trợ các hàm ẩn danh có thể tạo các bao đóng. Một bao đóng có thể truy cập vào biến được tạo bên ngoài phạm vi của nó.

Trong ví dụ, bao đóng có thể truy cập $datavì nó đã được khai báo trong usemệnh đề.


Đây là giải pháp hoạt động duy nhất trong trường hợp của tôi, trong đó tôi có một hàm được định nghĩa là một biến bên trong một hàm khác. Toàn cầu không hoạt động ở đó.
Kar.ma

Một lời giải thích sẽ được theo thứ tự. Ví dụ, điều này "sử dụng" để làm gì? Những phiên bản PHP nào mà thứ "sử dụng" này được hỗ trợ? (Vui lòng trả lời bằng cách chỉnh sửa câu trả lời của bạn , không phải ở đây trong nhận xét (nếu thích hợp). Cảm ơn trước.)
Peter Mortensen

Không biết tại sao ans đã được phê duyệt không hiển thị bất kỳ đầu ra nào trong trang plugin quản trị Wordpress nhưng ans này hoạt động tốt.
Naimur Hasan

3

Trong nhiều năm, tôi đã luôn sử dụng định dạng này:

<?php
    $data = "Hello";

    function sayHello(){
        echo $GLOBALS["data"];
    }

    sayHello();
?>

Tôi thấy nó đơn giản và dễ làm theo. $ GLOBALS là cách PHP cho phép bạn tham chiếu đến một biến toàn cục. Nếu bạn đã sử dụng những thứ như $ _SERVER, $ _POST, v.v. thì bạn có tham chiếu đến một biến toàn cục mà không biết nó.


Cái nào? $GLOBAL(văn bản) hoặc $GLOBALS(mã mẫu)? (Xin vui lòng đáp ứng bằng cách chỉnh sửa câu trả lời của bạn , chứ không phải ở đây trong ý kiến (nếu thích hợp).)
Peter Mortensen

đó là $ GLOBALS không phải $ GLOBAL. Phải có một "S". Sau đó, tham chiếu tên biến của bạn giống như một khóa cho một mảng kết hợp.
Thi thiên Kalu

Vui lòng cập nhật câu trả lời của bạn bằng cách chỉnh sửa nó (để bắt đầu chỉnh sửa , hãy nhấp vào " chỉnh sửa " , giữa "chia sẻ""gắn cờ" . Ba câu trả lời đó ở bên trái - bên trái của "đã chỉnh sửa""đã trả lời" , sau câu trả lời chính nó, phía trên nhận xét này, và trên cả ba nhận xét ở đây). Thông tin trong bình luận có thể biến mất bất cứ lúc nào. Đây không phải là một diễn đàn - thông tin có thể (và nên) được cập nhật ở đây. Thực sự cảm ơn bạn rất nhiều trước.
Peter Mortensen


0
<?php

    $data = 'My data';

    $menugen = function() use ($data) {

        echo "[ $data ]";
    };

    $menugen();
?>

Bạn cũng có thể đơn giản hóa

echo "[" . $data . "]"

đến

echo "[$data]"

echo "[" . $data . "]"echo "[ $data ]"không giống nhau (hai khoảng trắng thừa trong đầu ra cho phần sau).
Peter Mortensen

-1

Nếu muốn, bạn có thể sử dụng hàm "xác định", nhưng hàm này tạo ra một hằng số không thể thay đổi sau khi đã xác định.

<?php
    define("GREETING", "Welcome to W3Schools.com!");

    function myTest() {
        echo GREETING;
    }

    myTest();
?>

Hằng số PHP


Điều này xác định một hằng số toàn cục, không phải một biến.
Beejor

3
Không thể thay đổi hằng số khi đã xác định.
Beejor
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.