Cách ghi lại các phương thức magic (_call và _callStatic) cho IDE


80

Sau nhiều năm vui vẻ viết mã bằng notepad ++ và tuyệt vời, tôi đã được khuyên nên sử dụng PHP IDE. Tôi đang thử phpStorm và nó có vẻ tốt. Hoàn thành mã và tài liệu là một tính năng tuyệt vời nhưng không hoạt động với tôi khi các phương pháp ma thuật được sử dụng. Có một công việc xung quanh để có được phpStorm để hiểu những gì đang xảy ra trong các phương pháp ma thuật?

Tình huống của chúng tôi là như thế này:

abstract class a {
    public static function __callStatic($method,$args)
    {
        if(strpos($method,"get_by_") === 0)
        {
            //do stuff
        } elseif(strpos($method,"get_first_by_") === 0) {
            //do stuff
        } elseif($method == "get_all") {
            //do stuff
        }
    }
}

class b extends a {
    // some more stuff
}

b::get_by_user_id(27);
b::get_first_by_id(156);
b::get_all();

Phương thức callStatic ma thuật cho phép chúng ta lấy một tập hợp các đối tượng thông qua 1 hoặc nhiều đối số tạo nên lời gọi hàm.

Tôi thấy rằng có một câu lệnh @method để sử dụng trong những trường hợp này nhưng phpStorm chỉ chọn câu lệnh đầu tiên trong số những câu lệnh này. Hơn nữa, tôi chỉ có thể đặt kiểu trả về thành hỗn hợp ở nơi mà tôi muốn có thể đặt nó thành bất kỳ lớp nào mà nó được gọi (b trong ví dụ của tôi).

Bất kỳ ý tưởng hoặc đề xuất sẽ được nhận rất biết ơn, cảm ơn.


1
TẠI SAO MỌI NGƯỜI SUY NGHĨ VƯỢT QUA _callLÀ Ý TƯỞNG TỐT? !!
Brian Gordon

Phải nói, đã +1 nhận xét của Brian trong trường hợp bất kỳ người nào lành mạnh sẽ tìm thấy câu hỏi này. Magic method dành cho tất cả các mục đích và mục đích: không thể ghi lại (cố gắng ghi lại một (n) [tham số | precondition | postcondtion | ngoại lệ] cho một magic method), không thân thiện với IDE (cố gắng gỡ lỗi từng bước một magic method), có khả năng tái cấu trúc (xin vui lòng, thậm chí không xem xét việc cố gắng cấu trúc lại một phương pháp ma thuật trong một phần mềm đã được sử dụng) và LAZY (ok, điều cuối cùng có thể được hiểu là một ý kiến).
Luke A. Leber

16
-1 cho ý kiến ​​trong bình luận của @ LukeA.Leber vì nó chứng tỏ sự thiếu tầm nhìn. Mặc dù các phương pháp ma thuật không phải là cách để viết ít mã hơn (nếu bạn lười sử dụng chúng), các phương thức ma thuật làm cho các kiến ​​trúc có thể trở nên đơn giản đến mức không thể hoặc sẽ phức tạp đến mức sẽ không đáng để viết. Và chúng hoàn toàn thân thiện với IDE khi sử dụng PHPDoc. Lưu ý rằng hầu hết thời gian bạn không cần các phương thức ma thuật, nhưng khi bạn cần chúng thì không có phương thức thay thế nào (trong PHP.) Khi chúng được sử dụng theo cách rất có cấu trúc bằng cách sử dụng chúng là một giải pháp hoàn chỉnh hợp lệ.
MikeSchinkel

5
Đừng nghĩ ghi đè __calllà một ý kiến ​​tồi. Đó là tất cả về việc thực hiện. Việc triển khai được hiển thị trong câu hỏi ở trên chắc chắn không phải là cách tốt nhất, nhưng đối với API có khả năng chuỗi, nó cho phép rất nhiều tính linh hoạt.
Steve Bauman

Câu trả lời:


143

Sử dụng nhận xét PHPDoc cấp lớp - cụ thể là thẻ @method - hoạt động tốt trong PhpStorm:

/**
 * @method static someClass get_by_user_id(int $id) Bla-bla
 * @method static someClass get_first_by_id(int $id) 
 */
abstract class a {
...

Ở trên:

  • @method - Thẻ PHPDoc
  • static - nói rằng đây là phương thức tĩnh
  • someClasshoặc $this- loại trả lại
  • get_by_user_id - tên phương thức
  • (int $id) - chữ ký phương thức: ([[type] [parameter]<, ...>])
  • Bla-bla - một số mô tả tùy chọn

Thông tin thêm về @method:

PS Mặc dù @method statichoạt động tốt trong PhpStorm (cho IDE biết rằng phương thức là tĩnh), nó có thể chưa được hỗ trợ bởi công cụ phpDocumentor thực tế (xin lỗi, đã không sử dụng nó một thời gian).


Ngoài ra : (tất nhiên là trong PhpStorm) Settings | Inspections | PHP | Undefined | Undefined method --> Downgrade severity if __magic methods are present in class- nó sẽ không giúp hoàn thành mã cho các phương thức như vậy theo bất kỳ cách nào, nhưng sẽ không đánh dấu các phương thức ma thuật đó là lỗi "phương thức không xác định".


Phiếu của phpDocumentor về việc sử dụng RegEx / một phần tên cho @property/ @methodthẻ (nó có thể hữu ích như thế nào đối với tài liệu và nó có thể mang lại ít trợ giúp như thế nào cho IDE thực tế khi xử lý hoàn thành mã):


2
Cảm ơn, đây có vẻ như là một gợi ý hợp lý và nó chắc chắn hoạt động trong phpStorm, nhưng tôi hơi khó chịu khi viết ra hàng trăm dòng @method có khả năng ở đầu mỗi lớp. Bạn thấy phương thức get_by_ * có thể được thêm vào trước bởi bất kỳ tham số đối tượng nào để lấy các đối tượng thuộc loại đó bằng tham số đã chỉ định. Ngay cả khi loại trừ khả năng get_by_ _and_ tôi sẽ kết thúc với khoảng 1500 @methodstrên 140 lớp khác nhau. Không có cách nào chung chung hơn để cung cấp tài liệu?
Rob Forrest

Không. Tất cả các phương thức ma thuật phải được khai báo cụ thể (đó là điểm chính của tài liệu theo cách này) - PHPDoc không hiểu tên từng phần (ví dụ get_by_*(int $id)). Đối với IDE (kiểm tra mã, không hoàn thành!), Bạn có giải pháp thay thế (tắt cảnh báo). Đối với phpDocumentor (hoặc công cụ thay thế) - không có giải pháp nào với tôi (có thể nó ở đó, nhưng tôi không biết về nó). Bạn có liên kết đến github - gửi vé mới và yêu cầu thêm chức năng khớp "tên từng phần" như vậy - hãy xem họ sẽ nói gì (rất có thể sẽ bị từ chối). Nếu nó sẽ được triển khai, thì IDE cũng có thể có nó sau này.
LazyOne

github.com/phpDocumentor/phpDocumentor2/issues - nhưng vui lòng kiểm tra xem phiếu tương tự không tồn tại trước khi đăng vé của bạn.
LazyOne

Cảm ơn vì tất cả những điều đó. Có một vé hiện đang mở liên quan đến điều này nhưng tất cả dường như đã im lặng. Tôi đã mắc kẹt một nhận xét ở đó và chúng ta sẽ xem điều gì xảy ra với nó.
Rob Forrest

2
Chỉ cần cho các tài liệu tham khảo, vé của phpDocumentor (những người dùng khác biết những gì vé bạn đang nói về; cũng thêm nó vào câu trả lời chính nó): github.com/phpDocumentor/phpDocumentor2/issues/689
LazyOne

4

Hơi liên quan đến câu hỏi ban đầu:

Bạn cũng có thể xác định điều này trong tệp meta phpstorm. Dưới đây là một ví dụ cho phương pháp nhà máy (v2016.3):

// Define in .phpstorm.meta.php
namespace PHPSTORM_META {
    $STATIC_METHOD_TYPES = [
        \Factory::create('') => [],
    ];
}

// Then use in code
$factory = new \Factory();
$user = $factory->create(\User::class);
// Here you get autocomplete.
$user->subscribe();

Bằng cách này, bạn không phải khóa mọi khả năng khi phép thuật xảy ra.

Có một số tài liệu để biết chi tiết.


Điều này không hoạt động với __call. Nó cũng không được lập thành văn bản và PHP không hợp lệ. PHPStorm chỉ cung cấp hỗ trợ cho nơi bạn có các phương thức được xác định tĩnh trả về hỗn hợp các loại tùy thuộc vào đầu vào.
jgmjgm
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.