2008-10-03 35 views
5

Tôi có một hàm bao gồm tệp dựa trên chuỗi được chuyển đến đó tức là biến hành động từ chuỗi truy vấn. Tôi sử dụng điều này cho mục đích lọc vv để mọi người không thể bao gồm các tập tin họ không nên có thể và nếu tập tin không tồn tại một tập tin mặc định được nạp thay thế. Vấn đề là khi chức năng chạy và bao gồm phạm vi tập tin, bị mất vì bao gồm chạy bên trong một hàm. Điều này trở thành một vấn đề bởi vì tôi sử dụng một tập tin cấu hình toàn cầu, sau đó tôi sử dụng các tập tin cấu hình cụ thể cho mỗi mô-đun trên trang web. Cách tôi đang thực hiện tại thời điểm này là xác định các biến tôi muốn có thể sử dụng làm toàn cục và sau đó thêm chúng vào đầu chức năng lọc.PHP Phạm vi bảo tồn khi gọi một hàm

Có cách nào dễ dàng hơn để thực hiện điều này, tức là bằng cách bảo toàn phạm vi khi có cuộc gọi chức năng hoặc có một thứ như macro PHP?

Chỉnh sửa: Sẽ tốt hơn nếu sử dụng trích xuất ($ _ GLOBALS); bên trong hàm gọi của tôi thay vào đó?

Chỉnh sửa 2: Đối với bất kỳ ai quan tâm. Tôi nhận ra rằng tôi đã nghĩ về vấn đề hoàn toàn và thay vì sử dụng một chức năng tôi chỉ nên sử dụng một bao gồm, duh! Bằng cách đó tôi có thể giữ phạm vi của tôi và có bánh của tôi quá.

+0

Trong trường hợp của tôi phải dùng đến của bạn "Chỉnh sửa 2" và chỉ sử dụng một bao gồm không làm việc vì tôi đã có nhiều thứ hơn đang diễn ra. Về cơ bản nghĩ về nó như là một lớp "View" đòi hỏi một viewscript.php mà bởi vì chúng ta đang ở trong một phạm vi plugin, tôi muốn vượt qua phạm vi "toàn cầu" để các bản ghi mà không cần khai báo mỗi biến duy nhất là toàn cầu trong " doInclude "function. –

Trả lời

5

Edit: Được rồi, tôi đã đọc lại câu hỏi của bạn và tôi nghĩ rằng tôi có được những gì bạn đang nói về bây giờ:
bạn muốn một cái gì đó như thế này để làm việc:

// myInclude.php 
$x = "abc"; 

// ----------------------- 
// myRegularFile.php 

function doInclude() { 
    include 'myInclude.php'; 
} 
$x = "A default value"; 
doInclude(); 
echo $x; // should be "abc", but actually prints "A default value" 

Nếu bạn chỉ thay đổi một vài biến và bạn biết trước các biến sẽ được xác định trong phần bao gồm, khai báo chúng dưới dạng global trong hàm doInclude().

Ngoài ra, nếu mỗi người trong số bạn bao gồm thể xác định bất kỳ số lượng các biến, bạn có thể đặt tất cả chúng vào một mảng:

// myInclude.php 
$includedVars['x'] = "abc"; 
$includedVars['y'] = "def"; 

// ------------------ 
// myRegularFile.php 
function doInclude() { 
    global $includedVars; 
    include 'myInclude.php'; 
    // perhaps filter out any "unexpected" variables here if you want 
} 

doInclude(); 
extract($includedVars); 
echo $x;  // "abc" 
echo $y;  // "def" 

gốc câu trả lời:

loại điều này được gọi là "bao đóng" và đang được giới thiệu trong PHP 5.3

http://steike.com/code/php-closures/

Sẽ tốt hơn nếu sử dụng trích xuất ($ _ GLOBALS); bên trong hàm gọi của tôi thay vào đó?

Chúa ơi, không. nếu bạn muốn truy cập biến toàn cầu từ bên trong một hàm, chỉ cần sử dụng từ khóa global. ví dụ:

+0

Đây chính xác là vấn đề tôi đã gặp phải. Tôi đang cố gắng để phát triển một plugin cho một kịch bản, nhưng tiếc là kịch bản nào làm một số điều kỳ lạ với globals. Đó là một nỗi đau để theo dõi tất cả các hình cầu khác nhau mà tôi cần và khai báo chúng trong hàm "doInclude". Oh well ... Tôi nghĩ $ GLOBALS sẽ hoạt động, nhưng điều đó không hiệu quả vì thứ tự các chức năng và bao gồm. Đó là cuộc sống của một nhà phát triển plugin tôi đoán. –

0

Khi nói đến tùy chọn cấu hình (đặc biệt là đường dẫn tệp và như vậy), tôi thường chỉ định nghĩa chúng bằng đường dẫn tuyệt đối bằng cách sử dụng hàm define(). Một cái gì đó như:

define('MY_CONFIG_PATH', '/home/jschmoe/myfiles/config.inc.php'); 

Bằng cách đó, chúng luôn có thể truy cập trên toàn cầu bất kể phạm vi thay đổi và trừ khi tôi chuyển sang cấu trúc tệp khác, nó luôn có thể tìm thấy mọi thứ.

+0

Tôi có hầu hết các biến cấu hình được thiết lập trong thời trang này, nhưng tôi có mảng mã quốc gia, đối tượng cơ sở dữ liệu v.v. không thể được xác định theo cách này. – Joshua

0

Nếu tôi hiểu đúng, bạn có một mã dọc theo dòng:

function do_include($foo) { 
    if (is_valid($foo)) 
    include $foo; 
} 

do_include(@$_GET['foo']); 

Một giải pháp (mà có thể hoặc có thể không đơn giản, tùy thuộc vào codebase) là để di chuyển bao gồm ra trong toàn cầu phạm vi:

if (is_valid(@$_GET['foo'])) 
    include $_GET['foo']; 

cách giải quyết khác tồn tại (như bạn đề cập: tuyên bố globals, làm việc với mảng $ _GLOBALS trực tiếp, vv), nhưng lợi thế của giải pháp này là bạn không cần phải nhớ quy ước như vậy trong tất cả các tệp được bao gồm.

0

Tại sao không trả về một giá trị từ bao gồm bạn và sau đó thiết lập giá trị của bao gồm cuộc gọi đến một biến:

config.php

return array(
    'foo'=>'bar', 
    'x'=>23, 
    'y'=>12 
); 

script.php

$config = require('config.php'); 
var_dump($config); 

Không cần phải làm hỏng địa điểm với các biến toàn cầu

0

Có cách nào dễ dàng hơn để làm điều này, tức là bằng cách giữ gìn phạm vi khi một cuộc gọi chức năng được thực hiện

Bạn có thể sử dụng:

function doInclude($file, $args = array()) { 
    extract($args); 
    include($file); 
} 

Nếu bạn không muốn vượt qua một cách rõ ràng các biến, bạn có thể gọi doInclude với get_defined_vars như là đối số, Eg .:

doInclude('test.template.php', get_defined_vars()); 

Cá nhân tôi muốn vượt qua một mảng rõ ràng, chứ không phải sử dụng điều này, nhưng nó sẽ làm việc.

+0

Điều này không trả lời được câu hỏi, mà là nói "bạn đang làm sai." Cảm ơn Steve. Đôi khi có những tình huống mà nó * sẽ * được tốt đẹp để chạy một chức năng bằng cách sử dụng một phạm vi mong muốn (tức là toàn cầu) 'call_user_func_array_with_scope ('function', $ args, $ this)' sẽ được thuận tiện nếu nó tồn tại ... (Hoặc đi qua " null "hoặc toàn cầu để trả nó ra phạm vi toàn cầu. Sẽ có ích khi xây dựng một plugin để làm việc bên trong một số ràng buộc được xác định rõ ràng. –

0

Bạn có thể khai báo các biến trong tập tin bao gồm như là toàn cầu, đảm bảo họ có phạm vi toàn cầu:

//inc.php 
global $cfg; 
$cfg['foo'] = bar; 

//index.php 
function get_cfg($cfgFile) { 
    if (valid_cfg_file($cfgFile)) { 
     include_once($cfgFile); 
    } 
} 
... 
get_cfg('inc.php'); 
echo "cfg[foo]: $cfg[foo]\n"; 
Các vấn đề liên quan