2011-04-21 36 views
5

Câu hỏi này càng thêm về lý do tại sao 'làm thế nào', nhưng nó đã gây phiền nhiễu cho tôi vài ngày nay. Hiện nay tôi đang làm một số công việc với CodeIgniter và quay trở lại PHP tạm thời từ Ruby, lỗi cho tôi về ma thuật phạm vi sau đây.PHP, một phạm vi biến lẻ?

<?php $query = $this->db->get('articles', 2); 
     if ($query->num_rows() > 0) 
     { 
      foreach ($query->result_array() as $row) 
      { 
       $data[] = $row; # <-- first appearance here 
      } 
     return $data; # <--- :S what?! 
     } 

Như bạn có thể thấy, tôi không chính xác là một guru PHP, nhưng ý tưởng về lỗi phạm vi cục bộ mà bên ngoài vòng lặp foreach biến là 'có sẵn'. Vì vậy, tôi đã cố gắng này ra bên trong một cái nhìn:

<?php 

    if($a==1) 
    { 
    $b = 2; 
    } 
    echo $b; 
?> 

Những kết quả trong một thông báo lỗi:

Message: Undefined variable: b 

Tài liệu PHP nói về Phạm vi địa phương, tuy nhiên tôi vẫn tự hỏi tại sao điều này xảy ra và nếu có là những quy tắc đặc biệt mà tôi không biết. Và nó làm tôi sợ :)

Cám ơn ý kiến ​​chia sẻ,

+2

Bạn tạo biến trong ví dụ thứ hai của bạn chỉ khi $ a là 1. Vì $ a không tồn tại (PHP thực sự đặt ra lỗi ở đây), $ b sẽ không được tạo. Trong ví dụ đầu tiên, tất cả các điều kiện đã được đáp ứng để dữ liệu $ được tạo và được sử dụng làm giá trị trả về. –

+0

Ví dụ thứ hai là làm rõ hơn/quá minh rằng $ b bên ngoài dấu ngoặc nhọn có thể truy cập được - như các câu trả lời khác đã đưa ra, các dấu ngoặc nhọn không xác định phạm vi của các biến. Và điều đó, tôi không biết :) – Shyam

+0

Tôi nghĩ rằng điều này đã lỗi thời, hoặc có thể là vấn đề STRICTness. Ví dụ thứ hai của bạn làm việc cho tôi và in 2. Tôi đang làm việc với 5.4.16 với STRICT tắt – Dennis

Trả lời

11

Chỉ các hàm mới tạo phạm vi cục bộ mới. Niềng răng xoăn của mình không. Niềng răng xoăn chỉ là một cấu trúc phụ auxillary cho các cấu trúc ngôn ngữ khác (if, while hoặc foreach).

Và bất cứ nơi nào bạn truy cập bất kỳ biến nào trong phạm vi địa phương đều không quan trọng. Phạm vi cục bộ là một từ điển ẩn ẩn phía sau hậu trường (xem get_defined_vars). Bạn có thể nhận được một thông báo gỡ lỗi bằng cách truy cập các biến không xác định trước đó, nhưng đó là về nó.

Trong ví dụ cụ thể của bạn có vẻ như, bạn thậm chí chỉ hoạt động trong phạm vi toàn cầu.

+1

Câu đầu tiên làm cho nó hiểu rõ ràng! Cảm ơn! – Shyam

+0

Tuyệt. Ngoài ra còn có một thuật ngữ ngữ nghĩa chính thức cho điều đó, nhưng tôi không thể nhớ. :/ – mario

+0

@mario, [Cần dẫn nguồn] (http://xkcd.com/285) cho "* Niềng răng xoăn chỉ là cấu trúc ** phụ trợ ** cho các cấu trúc ngôn ngữ khác *" .... – Pacerier

7

foreach không tạo ra bất kỳ phạm vi biến trong PHP nên rất tự nhiên nếu biến có sẵn bên ngoài foreach

cho câu hỏi thứ hai không phải là $a bằng 1 do đó $b không được khởi tạo và thông báo khi bạn truy cập bên ngoài. Nếu bạn chỉ định giá trị 1 đến $a và kiểm tra nó, bạn sẽ tự hỏi các thông báo sẽ biến mất.

Đây không phải là phạm vi.

+0

Ví dụ thứ hai không phải là một câu hỏi, giống như một viễn cảnh như tôi mong đợi hành vi (sự thiếu kinh nghiệm của tôi với ngôn ngữ PHP). Khi các câu trả lời khác đưa ra, các dấu ngoặc nhọn không xác định phạm vi biến. Mặc dù, cảm ơn câu trả lời của bạn :) – Shyam

+0

@shyam: Không vấn đề gì, Vì tôi chỉ cố giải thích điều này –

1

Shyam, bạn đang sử dụng ngôn ngữ kịch bản chứ không phải C++. Nó là điển hình cho các ngôn ngữ kịch bản như PHP hoặc JavaScript không có phạm vi khác nhau cho mỗi khối mã. Thay vào đó có một phạm vi cho toàn bộ hàm. Điều này thực sự khá tiện lợi nếu bạn xem xét ví dụ đầu tiên của mình, nhưng rõ ràng bạn cần phải cẩn thận như có thể thấy trong phần thứ hai của mình.

+1

Thiết kế tốt cho PL bao gồm các cơ chế phạm vi (bên cạnh 'call_user_func (function() {})' xấu xí. Tại sao "điển hình cho các ngôn ngữ kịch bản không có các phạm vi khác nhau cho mỗi khối mã"? – Pacerier

1

là $ a bằng 1? Nếu không phải $ b = 2 sẽ không bao giờ được đánh giá!

3

Xem: http://php.net/manual/en/language.variables.scope.php

Trong dấu ngoặc nhọn php không nhất thiết xác định một phạm vi mới cho các biến. (ví dụ đầu tiên của bạn)

Trong ví dụ thứ 2 của bạn, $ b chỉ được đặt trên một điều kiện cụ thể. Vì vậy, có thể là 'không xác định' nếu điều kiện này không được đáp ứng.

+0

Cảm ơn bạn đã liên kết và câu trả lời của bạn! – Shyam

1

Thực ra phương pháp đầu tiên của bạn cũng sẽ gây ra lỗi cho bạn.

Bạn đang sử dụng biến chưa được khai báo dưới dạng mảng. Tôi không thể hiểu tại sao bạn không nhận được lỗi cho điều đó.

PHP không có phạm vi chặn, vì vậy cho dù đó là phạm vi bên trong IF hoặc FOREACH thì không liên quan. Nếu nó có sẵn bên trong phương thức, bạn có thể sử dụng nó bên trong phương thức.