2010-02-27 35 views
5

Tôi đang làm việc trên một lớp cần truy cập thông qua các cuộc gọi hàm tĩnh cũng như các phương thức đối tượng. Một điều tôi đã tìm thấy là tôi đang nhân đôi logic trên nhiều chức năng.

Giản dụ:

class Configurable{ 

    protected $configurations = array(); 

    protected static $static_configurations = array(); 

    public function configure($name, $value){ 

     // ...lots of validation logic... 

     $this->configurations[$name] = $value; 

     } 

    public static function static_configure($name, $value){ 

     // ...lots of validation logic (repeated)... 

     self::$static_configurations[$name] = $value; 

     } 

    } 

Tôi đã tìm thấy một giải pháp cho điều này, nhưng nó cảm thấy thực sự bẩn:

class Configurable{ 

    protected $configurations = array(); 

    protected static $static_configurations = array(); 

    public function configure($name, $value){ 

     // ...lots of validation logic... 

     if (isset($this)){ 
      $this->configurations[$name] = $value; 
      } 
     else{ 
      self::$static_configurations[$name] = $value; 
      } 

     } 

    } 

tôi cần những chức năng tĩnh cũng vì vậy mà tôi có thể thiết lập cấu hình trong suốt ứng dụng. Ngoài ra, điều tốt đẹp với kỹ thuật này là tôi có thể sử dụng cùng một tên phương thức trong cả hai phạm vi.

Có vấn đề gì với phạm vi kiểm tra như thế này không? Các vấn đề về hiệu năng, các vấn đề tương thích về phía trước, vv Tất cả đều hoạt động với tôi trên PHP 5.2 và tôi không cần hỗ trợ < 5.

Trả lời

2

Vấn đề với phương pháp thứ hai là nó sẽ dẫn đến lỗi khi báo cáo lỗi được đặt thành E_STRICT. Ví dụ:

tiêu chuẩn nghiêm ngặt: Phương pháp Non-static Foo :: bar() không nên được gọi là tĩnh trong /home/yacoby/dev/php/test.php trên đường dây 10

Một điểm với PHP6 là các lỗi E_STRICT được chuyển đến E_ALL. Nói cách khác E_ALL sẽ bao gồm tất cả các lỗi bao gồm không cho phép bạn gọi các phương thức tĩnh không tĩnh.

Một phương pháp thay thế có thể là di chuyển logic xác thực sang một hàm tĩnh. Bằng cách đó, hàm tĩnh và hàm tĩnh có thể gọi logic hợp lệ.

+1

OK, ngoài lỗi nghiêm ngặt, có bất kỳ vấn đề nào với phương pháp thứ hai không? Tôi có lẽ sẽ thay đổi nó trên lời khuyên của bạn anyway, nhưng tôi muốn hiểu những vấn đề thực sự với việc sử dụng mã như thế này. Đây có phải là một tính năng có khả năng bị xóa khỏi các phiên bản PHP trong tương lai hay bạn sẽ luôn có thể gọi các phương thức tĩnh không phải là tĩnh? – Rowan

+1

Lỗi 'E_STRICT' có xu hướng là" Điều này có vẻ như một ý tưởng thực sự tồi tệ, nhưng chúng tôi sẽ cho phép bạn cố gắng làm điều đó. " Không có gì đảm bảo rằng một thứ như vậy sẽ luôn hoạt động, nhưng chúng có thể sẽ được chuyển thành 'E_NOTICE' hoặc' E_WARN' trước khi hoàn toàn không được chấp nhận nữa. – MightyE

+0

Cảm ơn bạn đã làm rõ @MightyE – Rowan

2

Phương pháp tĩnh sẽ yêu cầu một số đối số khác với đối số khách quan của chúng - đối số bổ sung sẽ là ngữ cảnh thực thi. Nếu không có ngữ cảnh thực thi thì chỉ chỉ có ý nghĩa để gọi nó là tĩnh.

Cách tiếp cận ưa thích của tôi cho rằng tôi đang xây dựng một thư viện với nhiều giao diện như thế này, là tạo một lớp tĩnh và một lớp động. Có một proxy các cuộc gọi đến khác. Ví dụ:

class DynamicClass { 
    protected $foo; 
    protected $bar; 
    public function baz($arg1) { 
     return StaticClass::bar($this->foo, $arg1); 
    } 
    public function zop($arg1, $arg2) { 
     return StaticClass::zop($this->foo, $this->bar, $arg1, $arg2); 
    } 
    // Context-less helper function 
    public function womp($arg1) { 
     return StaticClass::womp($arg1); 
    } 
} 

class StaticClass { 
    public static function baz(&$fooContext, $arg1) { ... } 
    public static function zop(&$fooContext, &$barContext, $arg1, $arg2) { ... } 
    public static function womp($arg1) { ... } 
} 

Tùy thuộc vào cách bạn chuyển ngữ cảnh đến lớp tĩnh - bạn sẽ phải làm bất cứ điều gì hợp lý với bạn. Công việc được thực hiện trong hầu hết các hàm nên khá nhỏ (nếu bạn đang làm rất nhiều, thì có lẽ bạn nên chia nhỏ các công việc thành các hàm nhỏ hơn như một quy tắc), và do đó chỉ nên yêu cầu một số đối số ngữ cảnh. Hoặc bạn có thể tạo ra một mảng bối cảnh đầy đủ và thông qua đó xung quanh ở khắp mọi nơi (hoặc Populating nó trong DynamicClass ngay trước mỗi cuộc gọi, nếu không theo dõi tất cả DynamicClass tính trong mảng đó để bạn có thể nhanh chóng & dễ dàng vượt qua nó xung quanh.


Mặc dù có vẻ như bạn có thể được hưởng lợi từ mẫu thiết kế Singleton Từ những gì tôi có thể thấy, bạn đang cố gắng tạo ra một hình ảnh toàn cầu Configurable và cũng có tùy chọn để tạo riêng từng địa chỉ Configurable s. một phiên bản có thể truy cập toàn cầu của một lớp mà bạn có thể đảm bảo rằng bạn chỉ có một (không vi phạm nguyên tắc thiết kế OOP và phải dựa vào $ _GLOBALS v.v.).Ví dụ:

class DynamicClass { 
    protected $foo; 
    protected $bar; 

    public function baz($arg1) { ... } 
    public function zop($arg1, $arg2) { ... } 

    public static function getSingleton() { 
     static $instance = null; 
     if ($instance === null) $instance = new DynamicClass(); 
     return $instance; 
    } 
} 

Bất kể bạn ở đâu, bạn có thể truy cập vào cùng một trường hợp với DynamicClass::getSingleton(). Bạn cũng có tùy chọn tạo các phiên bản không phải singleton một lần. Bạn về cơ bản có được tốt nhất của cả hai thế giới trong khi chỉ phải viết tất cả các phương pháp của bạn với quyền truy cập động trong tâm trí độc quyền.

2

Tôi không tìm thấy nó quá ngớ ngẩn để cho phép gọi một phương thức trên một thể hiện và tĩnh. trường hợp của tôi:

TestRecord::generateForm(); // Generate an empty form. 

    $test = new TestRecord($primaryKey); 
    [...] 
    $test->generateForm();  // Generate an edit form with actual $test values. 

phía tĩnh của giao dịch lớp học của tôi với trống/logic mới, khi dụ bên có nghĩa dữ liệu trực tiếp được sử dụng.

PHP 5.3 cho phép để đạt được điều này bằng cách sử dụng __call, __callStaticstatic:::

public function __call($name, $args) 
{ 
    if ($name == 'generateForm') { 
    $this->fields = static::createFields(); // Action 1 : static. 
    $this->fillFields();      // Action 2 : instance. 
    static::renderForm($this->fields);  // Action 3 : static. 
    } 
} 

public static function __callStatic($name, $args) 
{ 
    if ($name == 'generateForm') { 
    $fields = static::createFields();  // Action 1 : static. 
              // Action 2 : none. 
    static::renderForm($fields);   // Action 3 : static. 
    } 
} 

Note: Các static:: vòng loại cuối ràng buộc được sử dụng vì 3 phương pháp hành động của tôi (createFields, fillFieldsrendreForm) được thực hiện dưới dạng protected trong các lớp con của trang này, là abstract. Điều này là có thể bởi vì PHP cho phép các thành viên được bảo vệ được truy cập theo cả hai hướng: từ cơ sở đến phân lớp, nhưng từ lớp con đến siêu lớp là tốt. Điều này khác với các ngôn ngữ OO khác, theo như tôi biết.

-1

như trong lõi php chúng tôi sử dụng index.php?var=, do đó, để làm điều tương tự trong oop php những gì chúng ta nên sử dụng.

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