2012-01-23 28 views
13

Tôi đang tìm cách để đặt phạm vi require_once() thành phạm vi toàn cầu, khi require_once() được sử dụng bên trong một hàm. Một cái gì đó giống như đoạn mã sau nên làm việc:Có cách nào để đặt phạm vi require_once() một cách rõ ràng thành toàn cục không?

file `foo.php ':

<?php 

$foo = 42; 

mã thực tế:

<?php 

function includeFooFile() { 
    require_once("foo.php"); // scope of "foo.php" will be the function scope 
} 

$foo = 23; 

includeFooFile(); 
echo($foo."\n"); // will print 23, but I want it to print 42. 

Có cách nào để thiết lập một cách rõ ràng phạm vi require_once()? Có cách giải quyết tốt không?

+3

Phạm vi của 'require_once' được đặt rõ ràng nơi bạn xác định việc sử dụng nó. – hakre

+0

Tôi có thể nghĩ về một công việc kinh khủng xung quanh, nếu bạn muốn ... – DaveRandom

+1

Không có. Bạn cần phải liệt kê các biến được đặt bí danh vào phạm vi toàn cục. Hoặc là trong hàm hoặc trên đỉnh tập lệnh bao gồm của bạn. – mario

Trả lời

1

Bạn có thể sử dụng chức năng hacky này tôi đã viết:

/** 
* Extracts all global variables as references and includes the file. 
* Useful for including legacy plugins. 
* 
* @param string $__filename__ File to include 
* @param array $__vars__  Extra variables to extract into local scope 
* @throws Exception 
* @return void 
*/ 
function GlobalInclude($__filename__, &$__vars__ = null) { 
    if(!is_file($__filename__)) throw new Exception('File ' . $__filename__ . ' does not exist'); 
    extract($GLOBALS, EXTR_REFS | EXTR_SKIP); 
    if($__vars__ !== null) extract($__vars__, EXTR_REFS); 
    unset($__vars__); 
    include $__filename__; 
    unset($__filename__); 
    foreach(array_diff_key(get_defined_vars(), $GLOBALS) as $key => $val) { 
     $GLOBALS[$key] = $val; 
    } 
} 

Nó di chuyển bất kỳ vars mới được xác định trở lại vào toàn cầu ace khi tập tin include trả về. Có một báo trước rằng nếu tệp được bao gồm chứa một tệp khác, nó sẽ không thể truy cập bất kỳ biến nào được xác định trong tệp gốc qua $GLOBALS vì chúng chưa được toàn cầu hoá.

5

Ngoài từ "toàn cầu hóa" biến của bạn, không có cách nào để làm điều này:

global $foo; 
$foo = 42; 

HOẶC

$GLOBALS['foo'] = 42; 

Sau đó, giá trị của bạn nên được 42 khi bạn in nó ra.

CẬP NHẬT

Về sự bao gồm các lớp học hoặc các chức năng, lưu ý rằng tất cả các chức năng và các lớp học luôn coi toàn cầu trừ khi chúng ta đang nói về một phương pháp học. Tại thời điểm đó, phương thức trong một lớp chỉ có sẵn từ định nghĩa lớp và không phải là một hàm toàn cục.

+0

Tôi vừa thử câu trả lời của bạn và nó hoạt động tốt. Không có bất kỳ vấn đề gì, nếu tập tin 'foo.php' chứa các hàm hoặc các lớp, phải không? –

+0

Không, không sao cả ... đọc bản cập nhật tôi sẽ đăng trong vài giây ... –

+1

Thx Mathieu. Giải pháp của bạn hoạt động tốt cho ứng dụng của tôi. –

1

Đang chờ xử lý các yêu cầu chính xác của bạn, bạn có thể sử dụng constants. Yêu cầu tệp của bạn trong phạm vi toàn cục, nhưng bên trong nó đặt một hằng số.

IE file.php:

define('MY_CONSTANT', 42); 

Sau đó, bất cứ nơi nào trong kịch bản của bạn chỉ cần sử dụng MY_CONSTANT để tham khảo các giá trị, bạn sẽ không thể chỉnh sửa khi nó đã được thiết lập mặc dù. Ngoài ra, bạn có thể toàn cầu hóa biến của bạn như câu trả lời khác nói, nhưng nó không rõ ràng 100% những gì bạn đang cố gắng để đạt được khác hơn là chỉ đơn giản là lấy một giá trị từ các tập tin bao gồm? Trong trường hợp này hằng số nên được tốt.

Cập nhật: Bây giờ bạn đã giải thích rằng bạn muốn một đối tượng thuộc tính có sẵn ở khắp mọi nơi, tôi đề nghị bạn nhìn vào việc tạo ra một static class, mà một lần thuyết minh trong phạm vi toàn cầu của bạn có thể được sử dụng bất cứ nơi nào trong ứng dụng của bạn. Đọc trang hướng dẫn được liên kết, nó có một ví dụ về xương trần.

+0

Tôi nghĩ rằng người dùng muốn có thể cập nhật giá trị hiện tại, nhưng nếu nó chỉ là hằng số bên ngoài, thì phương pháp của bạn là tốt nhất rõ ràng –

+0

Trong ứng dụng của tôi '$ foo' sẽ là một đối tượng. Các đối tượng không thể được lưu trữ trong các hằng số, phải không? –

+0

Không, bạn có thể tạo một lớp tĩnh, cập nhật câu trả lời của tôi ngay bây giờ ... – Dunhamzzz

2

Bạn sẽ cần phải khai báo toàn cầu trong foo.php của bạn:

<?php 
global $foo; 
$foo = 42; 
?> 

Nếu không nó có thể là không thể.

Bạn có thể thử để chơi xung quanh với extract(), get_defined_vars(), global$GLOBALS trong các kết hợp khác nhau có thể ... như lặp qua tất cả các biến được định nghĩa và kêu gọi toàn cầu về chúng trước khi đòi hỏi một tập tin ...

$vars = get_defined_vars(); 
foreach($vars as $varname => $value) 
{ 
    global $$varname; //$$ is no mistake here 
} 
require... 

Nhưng tôi không chắc chắn nếu bạn đến nơi bạn muốn đi ...

+0

Ah btw ... tôi có đề cập đến điều này là khủng khiếp không, mọi thứ ở đây chỉ nên được sử dụng làm ví dụ sai cách KHÔNG làm những việc ... có lẽ là giải pháp rất hay cho vấn đề cơ bản mà bạn đang cố gắng giải quyết, lạm dụng không gian tên toàn cầu;) – bardiir

2

Như phạm vi được định nghĩa một cách rõ ràng nơi bạn sử dụng require và như thế, bạn sẽ cần phải xác định những gì để làm với các biến bên trong phạm vi của hàm:

function includeFooFile() { 
    require_once("foo.php"); // scope of "foo.php" will be the function scope 

    foreach (get_defined_vars() as $k => $v) 
    { 
     $GLOBALS[$k] = &$v; 
    } 
} 

Ví dụ này sẽ chăm sóc của cả hai, các biến và tham chiếu có thể là những gì bạn đang tìm kiếm. Demo. Xin lưu ý rằng require_once sẽ chỉ hoạt động một lần và sẽ chỉ xác định các biến một lần.

3

này chắc chắn là không một tác phẩm "đẹp" xung quanh nhưng nó sẽ làm việc:

function includeFooFile() { 
    require_once("foo.php"); 
    foreach (get_defined_vars() as $key => $value) { 
    // Ignore superglobals 
    if (!in_array($key, array('GLOBALS','_SERVER','_GET','_POST','_FILES','_COOKIE','_SESSION','_REQUEST','_ENV'))) { 
     $GLOBALS[$key] = $value; 
    } 
    } 
} 

Tuy nhiên, tập tin bao gồm bạn không thể xác định bất kỳ chức năng hoặc các lớp học (và có thể một số thứ khác như rõ rằng tôi không thể hiện tại đang nghĩ đến) vì nó sẽ dẫn đến lỗi phân tích cú pháp, vì bạn không thể lồng lớp hoặc chức năng.

EDIT dường như bạn có thể bao gồm các chức năng trong tệp của mình. Tôi đã luôn luôn nghĩ rằng bạn không thể nhưng sau khi thử nghiệm có vẻ như bạn có thể.

+1

Điều này có vẻ là một giải pháp hữu ích cho vấn đề của tôi. Bây giờ tôi sẽ thử nó ... –

+1

Yeah! Nó hoạt động tốt, vì vậy tôi sẽ chấp nhận câu trả lời của bạn. –

+0

@DaveRandom: Điều này không hỗ trợ bí danh và superglobals đã được ghi đè, vì vậy không cần phải kiểm tra những lý thuyết đó. Thực tế, 'get_defined_vars()' không trả về các giá trị đó trong phạm vi hàm cục bộ. – hakre

1

Tôi đã không thử nó (kể từ khi sử dụng vars toàn cầu là một ý tưởng tồi tbh) nhưng điều này có khả năng có thể làm việc:

require_once '...'; 
$GLOBALS = array_merge($GLOBALS, get_defined_vars()); 

Hoặc bạn chỉ có thể làm điều đó bằng tay:

foreach (get_defined_vars() as $k => $v) { 
    $GLOBALS[$k] = $v; 
} 
+0

Tại sao bạn nghĩ sử dụng các vars toàn cầu là một ý tưởng tồi? –

+0

Đó là một giáo điều :) bạn có thể google cho nó, có nhiều giải thích đủ, phù hợp nhất với bất kỳ ngôn ngữ nào. Về cơ bản, ngay cả khi bạn cần dữ liệu có thể truy cập được trên toàn cầu, hãy đặt nó ở đâu đó nơi nó không thể can thiệp vào nội dung khác. Trong PHP một biến lớp tĩnh là một lựa chọn tốt (imho). –

Các vấn đề liên quan