2009-07-18 55 views
6

Tôi hiện đang tạo hệ thống blog, mà tôi hy vọng sẽ trở thành một CMS đầy đủ trong tương lai.Làm thế nào để tránh sử dụng các đối tượng toàn cục PHP?

Có hai lớp/đối tượng hữu ích để có quyền truy cập toàn cầu (kết nối cơ sở dữ liệu mysqli và lớp tùy chỉnh kiểm tra xem người dùng có đăng nhập hay không).

Tôi đang tìm cách để thực hiện điều này mà không cần sử dụng các đối tượng toàn cầu, và nếu có thể, không chuyển các đối tượng đến từng chức năng mỗi khi chúng được gọi.

Trả lời

13

Bạn có thể tạo đối tượng Tĩnh, sau đó bạn có quyền truy cập vào chúng ở bất kỳ đâu. Ví dụ:

myClass::myFunction(); 

Điều đó sẽ hoạt động ở mọi nơi trong tập lệnh. Bạn có thể muốn đọc trên các lớp tĩnh tuy nhiên, và có thể sử dụng một lớp Singleton để tạo ra một lớp thông thường bên trong một đối tượng tĩnh có thể được sử dụng ở bất cứ đâu.

mở rộng

Tôi nghĩ rằng những gì bạn đang cố gắng làm là rất giống với những gì tôi làm với lớp DB của tôi.

class myClass 
{ 
    static $class = false; 
    static function get_connection() 
    { 
     if(self::$class == false) 
     { 
      self::$class = new myClass; 
     } 
     return self::$class; 
    } 
    // Then create regular class functions. 
} 

Điều gì xảy ra sau khi bạn nhận kết nối, sử dụng $ object = myClass :: get_connection(), bạn sẽ có thể thực hiện bất kỳ chức năng nào thường xuyên.

$object = myClass::get_connection(); 
$object->runClass(); 

mở rộng

Khi bạn làm điều đó khai báo tĩnh, bạn chỉ cần gọi get_connection và gán giá trị trả về cho một biến. Sau đó, phần còn lại của các hàm có thể có cùng một hành vi như một lớp mà bạn đã gọi với $ class = new myClass (vì đó là những gì chúng ta đã làm). Tất cả những gì bạn đang làm là lưu trữ biến lớp bên trong một lớp tĩnh.

class myClass 
{ 
    static $class = false; 
    static function get_connection() 
    { 
     if(self::$class == false) 
     { 
      self::$class = new myClass; 
     } 
     return self::$class; 
    } 
    // Then create regular class functions. 
    public function is_logged_in() 
    { 
     // This will work 
     $this->test = "Hi"; 
     echo $this->test; 
    } 
} 

$object = myClass::get_connection(); 
$object->is_logged_in(); 
+0

Xin chào, cảm ơn câu trả lời của bạn, có thể lưu các biến trong các lớp tĩnh hay không. tức là chức năng gọi để kiểm tra xem người dùng có đăng nhập hay không và sau đó truy cập vào biến này vài lần sau đó trong trang? –

+2

Có, đối với một lớp tĩnh làm điều tương tự tôi đã làm để khai báo biến $ class. Điều duy nhất là bạn 'có' để khai báo mỗi biến bạn sử dụng. –

+1

Nhưng, mã tôi đưa cho bạn cho phép bạn sử dụng bất kỳ lớp thông thường nào, tốt, thường xuyên. Phần tĩnh đơn giản cung cấp cho bạn lớp, thay vì toàn cầu hóa nó. Tôi sẽ chỉnh sửa để hiển thị thêm một chút. –

1

Vâng, nếu bạn đã có một số đối tượng mà bạn tham khảo các hệ thống blog, bạn có thể soạn các đối tượng này vào đó, để chúng $blog->db()$blog->auth() hoặc bất cứ điều gì.

+0

Tôi có thể, nhưng các đối tượng cũng sẽ cần truy cập bên ngoài lớp blog. –

8

Bạn có thể chuyển đối tượng hiện tại trên toàn cầu vào hàm tạo.

<?php 
    class Foo { 
    protected $m_db; 
    function __construct($a_db) { 
     $this->m_db = $a_db; 
    } 
    } 
?> 
3

Gần đây, tôi đã cải tiến khung của mình để chuẩn bị cho phiên bản thứ hai của CMS của công ty chúng tôi. Tôi undid một lượng lớn những thứ tôi đã tạo để thay thế chúng bằng các vật thể thông thường. Để làm được điều đó, tôi đã tạo ra một số lượng lớn tính linh hoạt được sử dụng để dựa vào tôi trải qua và xâm nhập vào các tệp lõi. Bây giờ tôi chỉ sử dụng các cấu trúc tĩnh khi thay thế duy nhất là các hàm toàn cầu, mà chỉ liên quan đến chức năng cốt lõi cấp thấp.

Tôi sẽ hiển thị một vài dòng tệp bootstrap.php của mình (tất cả yêu cầu của tôi được gửi qua tệp đó, nhưng bạn có thể đạt được kết quả tương tự bằng cách bao gồm nó ở đầu mỗi tệp) ý tôi là gì Đây là một phiên bản khá lớn của những gì bạn có thể sử dụng trong tình huống của bạn, nhưng hy vọng ý tưởng này là hữu ích. (Đây là tất cả được sửa đổi một chút.)

//bootstrap.php 

... 

// CONSTRUCT APPLICATION 

{  
    $Database = new Databases\Mysql(
     Constant::get('DATABASE_HOST'), 
     Constant::get('DATABASE_USER'), 
     Constant::get('DATABASE_PASSWORD'), 
     Constant::get('DATABASE_SCHEMA') 
    ); 

    $Registry  = new Collections\Registry; 
    $Loader  = new Loaders\Base; 
    $Debugger  = new Debuggers\Dummy; // Debuggers\Console to log debugging info to JavaScript console 

    $Application = new Applications\Base($Database, $Registry, $Loader, $Debugger); 
} 

... 

Như bạn thấy, tôi có tất cả các loại tùy chọn để tạo đối tượng ứng dụng của tôi, mà tôi có thể cung cấp như một cuộc tranh cãi trong các nhà xây dựng với các đối tượng khác để cung cấp cho họ truy cập vào các nhu yếu phẩm "toàn cầu".

Đối tượng cơ sở dữ liệu tự giải thích. Đối tượng đăng ký hoạt động như một vùng chứa cho đối tượng mà tôi có thể muốn truy cập ở nơi khác trong ứng dụng. Trình tải hoạt động như một tiện ích để tải các tài nguyên khác như tệp mẫu. Và trình gỡ rối ở đó để xử lý đầu ra gỡ lỗi.

Ví dụ: tôi có thể thay đổi lớp cơ sở dữ liệu mà tôi khởi tạo và, thì tôi có kết nối với cơ sở dữ liệu SQLite. Tôi có thể thay đổi lớp của trình gỡ rối (như đã lưu ý) và bây giờ tất cả thông tin gỡ lỗi của tôi sẽ được ghi vào bảng điều khiển JavaScript của tôi.

OK, bây giờ hãy quay lại vấn đề. Làm thế nào để bạn cung cấp cho các đối tượng khác truy cập vào tất cả điều này? Bạn chỉ cần truyền nó trong một đối số cho hàm tạo.

// still bootstrap.php 

... 

// DISPATCH APPLICATION 

{ 
    $Router = new Routers\Http($Application); 
    $Router->routeUri($_SERVER['REQUEST_URI']); 
} 

... 

Không chỉ vậy, nhưng Bộ định tuyến của tôi (hoặc bất kỳ đối tượng nào tôi xây dựng với nó) cũng linh hoạt hơn. Bây giờ tôi chỉ có thể khởi tạo đối tượng ứng dụng của mình một cách khác nhau và Router của tôi sẽ hoạt động khác nhau cho phù hợp.

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