복붙노트

PHP 클래스에 코드를 포함 할 수 있습니까?

PHP

PHP 클래스에 코드를 포함 할 수 있습니까?

나는 PHP 클래스를 만들고 싶습니다. Myclass.php라고 말하면됩니다. 이제 그 클래스 안에 클래스 자체와 인스턴스 변수를 정의하고 싶습니다. 그러나 모든 메소드는 Myclass_methods.php 파일에서 가져와야합니다. 그 파일을 수업 본문에 포함시킬 수 있습니까?

왜 나는 이것을 분리하고 싶은 좋은 이유가 있습니다. 즉, 클래스의 비즈니스 로직을 변경할 수있는 백엔드를 갖지만 다른 모든 것들은 그대로 유지해야합니다. 이 시스템은 나를 위해 모든 ORM과 다른 것들을 유지합니다.

그러나 이것이 나쁜 생각이라면, 비즈니스 로직을 편집 한 후에 전체 클래스 파일을 다시 생성하는 것이 더 나을 수도 있습니다 (이 경우 사용자 정의 메소드).

성능 질문 : 한 번 요청하는 동안 Myclass.php가 한 번만 포함되면 실제로 Myclass_methods.php도 한 번만 포함되어야합니다. 잘못되었을 수도 있습니다. 전문가?

해결법

  1. ==============================

    1.아니요. 클래스 본문에 파일을 포함 할 수 없습니다. 클래스를 정의하는 파일에서 메소드 본문 또는 클래스 본문 외부에 파일 만 포함 할 수 있습니다.

    아니요. 클래스 본문에 파일을 포함 할 수 없습니다. 클래스를 정의하는 파일에서 메소드 본문 또는 클래스 본문 외부에 파일 만 포함 할 수 있습니다.

    당신의 설명에서 나는 당신이 이것을 원한다 :

    <?php // MyClass.php
    class MyClass
    {
        protected $_prop;
        include 'myclass-methods.php';
    }
    
    <?php // myclass-methods.php
    public function myMethod()
    {
       $this->$_prop = 1;
    }
    

    이 코드를 실행하면

    Parse error: syntax error, unexpected T_INCLUDE, expecting T_FUNCTION
    

    그래도이게 가능하니?

    <?php // MyClass.php
    class MyClass
    {
        protected $_prop;
        public function __construct() // or any other method
        {
            include 'some-functions.php';
            foo($b); // echoes 'a';
        }
    }
    
    <?php // some-functions.php
    $b = 'a';
    function foo($str)
    {
       echo $str;
    }
    

    이렇게하면 include 파일의 내용을 클래스 범위가 아닌 메서드 범위로 가져옵니다. 포함 파일에는 함수와 변수를 포함 할 수 있지만 메소드는 포함 할 수 없습니다. 스크립트 전체에 스크립트를 넣을 수는 없으며 메서드가 수행하는 작업을 변경할 수도 있습니다.

    <?php // MyClass.php
        // ...
        public function __construct($someCondition)
        {
            // No No Code here
            include ($someCondition === 'whatever') ? 'whatever.php' : 'default.php';
        }
        // ...
    
    <?php // whatever.php
        echo 'whatever';
    
    <?php // default.php
        echo 'foo';
    

    그러나 클래스에이 방식으로 패치를 적용하여 다른 동작을 표시하는 것은 OOP에서 수행해야하는 방식이 아닙니다. 그것은 단지 잘못되어 눈이 피가 날 것입니다.

    동적으로 동작을 변경하려고하기 때문에 클래스를 확장하는 것도 좋은 옵션이 아닙니다 (아래 이유 참조). 당신이 정말로하고 싶은 것은 인터페이스를 작성하고 클래스가이 인터페이스를 구현하는 객체를 사용하도록함으로써 적절한 메소드가 사용 가능한지 확인하는 것입니다. 이를 Strategy Pattern이라고하며 다음과 같이 작동합니다.

    <?php // Meowing.php 
    interface Meowing
    {
        public function meow();
    }
    

    이제 당신은 모든 야옹 행동 (Meowing Behaviors)이 준수해야하는 계약, 즉 야옹 방법을가집니다. 다음으로 야옹 행위 정의 :

    <?php // RegularMeow.php
    class RegularMeow implements Meowing
    {
        public function meow()
        {
            return 'meow';
        }
    }
    

    이제 사용하려면 다음을 사용하십시오.

    <?php // Cat.php
    class Cat
    {
        protected $_meowing;
    
        public function setMeowing(Meowing $meowing)
        {
            $this->_meowing = $meowing;
        }
    
        public function meow()
        {
            $this->_meowing->meow()
        }
    }
    

    Meowing TypeHint를 setMeowing에 추가하면 전달 된 매개 변수가 Meowing 인터페이스를 구현하는지 확인할 수 있습니다. 다른 Meowing Behavior를 정의 해 보겠습니다.

    <?php // LolkatMeow.php
    class LolkatMeow implements Meowing
    {
        public function meow()
        {
            return 'lolz xD';
        }
    }
    

    이제 다음과 같이 쉽게 동작을 교환 할 수 있습니다.

    <?php
    require_once 'Meowing.php';
    require_once 'RegularMeow.php';
    require_once 'LolkatMeow.php';
    require_once 'Cat.php';
    
    $cat = new Cat;
    $cat->setMeowing(new RegularMeow);
    echo $cat->meow; // outputs 'meow';
    // now to change the behavior
    $cat->setMeowing(new LolkatMeow);
    echo $cat->meow; // outputs 'lolz xD';
    

    추상적 인 BaseCat과 meow 메소드를 정의하고 그로부터 구체적인 RegularCat과 Lolkat 클래스를 파생시킴으로써 상속으로 위의 문제를 해결할 수도 있지만, 달성하고자하는 것을 고려해야합니다. 당신의 고양이가 그들이 야옹을하는 방식을 절대로 바꿀 수 없다면 상속을 사용하십시오. 그러나 RegularCat과 Lolkat이 임의의 야옹을 할 수 있다면 Strategy 패턴을 사용하십시오.

    PHP의 더 많은 디자인 패턴을 보려면 다음 리소스를 확인하십시오.

  2. ==============================

    2.관련 기본 기능으로 핵심 클래스를 작성한 다음 필요한 메소드로이를 확장하는 아이디어가 아닐 수도 있습니다. 이는보다 논리적 인 접근 방식처럼 보입니다.

    관련 기본 기능으로 핵심 클래스를 작성한 다음 필요한 메소드로이를 확장하는 아이디어가 아닐 수도 있습니다. 이는보다 논리적 인 접근 방식처럼 보입니다.

  3. ==============================

    3.우선,이 문제가 메소드를 포함하는 기본 클래스, 데이터를 포함하는 하위 클래스 및 동적 클래스 로딩을 사용하여 가장 잘 해결되지 않은 이유가 너무 명확하지 않다고 말하는 것으로 시작하겠습니다. 나는 너에게 좋은 이유가 있다고 가정 할 것이다.

    우선,이 문제가 메소드를 포함하는 기본 클래스, 데이터를 포함하는 하위 클래스 및 동적 클래스 로딩을 사용하여 가장 잘 해결되지 않은 이유가 너무 명확하지 않다고 말하는 것으로 시작하겠습니다. 나는 너에게 좋은 이유가 있다고 가정 할 것이다.

    제공자가 PHP 5.4를 지원하면 특성을 사용하여 원하는 것을 할 수 있습니다.

    코드 파일 :

    if ($pet === 'dog') include 'dog.php';
    elseif ($pet === 'cat') include 'cat.php';
    else die('Unknown pet');
    
    class Pet {
      use PetSounds;
    }
    
    $myPet = new Pet();
    $myPet->speak();
    

    cat.php 파일

    trait PetSounds {
      function speak() { echo 'meow'; }
    }
    

    파일 dog.php

    trait PetSounds {
      function speak() { echo 'woof'; }
    }
    

    두 include 파일의 이름을 동일하게 지정하고 서로 다른 하위 디렉토리에 넣고 set_include_path ()를 사용하거나 __autoload () 함수를 정의하여 파일 사이에서 선택할 수 있습니다. 나가 말한대로,이 동일한 문제는 상속을 사용하여 잘 해결 될 수 있었다. 하지만 여러 상속 유형 문제가있는 경우, 예를 들어 3 가지 헤어 유형을 가진 5 가지 색상의 애완 동물 4 종류가 있고 60 가지 클래스의 각각에 대해 서로 다른 조합의 방법이 필요한 경우 올바른 해결책입니다 .

    5.4는 현재 릴리스 후보 (2012 년 2 월 24 일 기준)이며 출시 된 이후에도 대부분의 호스트가 여러 달 동안 지원하지 않을 것입니다. 5.3이 출시되기 전에 석방 된 지 18 개월이 걸렸습니다. 그때까지는 완전히 분리 된 완전한 클래스 파일을 작성해야합니다. 그러나 형질에 대한 궁극적 인 변화를 염두에두고 클래스를 포맷 할 수 있습니다.

    지금 당장 당신은 마술 방법을 사용하여 원하는 것을 부분적으로 얻을 수 있으며 사용 가능한 경우 특성으로 쉽게 업그레이드 할 수 있습니다.

    코드 파일 :

    if ($pet === 'dog') include 'dog.php';
    elseif ($pet === 'cat') include 'cat.php';
    else die('Unknown pet');
    
    class Pet {
      public function __call($name, array $arguments)
      {
        array_unshift($arguments, $this);
        return call_user_func_array("TraitFunc_$name", $arguments);
      }
    }
    
    $myPet = new Pet();
    $myPet->speak();
    

    cat.php 파일

    function TraitFunc_speak(Pet $that) { echo 'meow'; }
    

    파일 dog.php

    function TraitFunc_speak(Pet $that) { echo 'woof'; }
    

    그러나 함수가 private 및 protected 클래스 속성 및 메서드에 액세스 할 수 없으며이 메서드를 사용하여 __get ()과 같은 마법 메서드를 제공 할 수 없다는 점에서 제한적입니다. 형질은 그 두 가지 한계점을 모두 해결할 것입니다.

  4. ==============================

    4.이것을 위해 형질을 사용하는 것은 어떻습니까? 그게 수용 가능한 선택일까요? 이것은 내가 현재 실험하고있는 것으로, 꽤 오랫동안 작동하는 것 같습니다.

    이것을 위해 형질을 사용하는 것은 어떻습니까? 그게 수용 가능한 선택일까요? 이것은 내가 현재 실험하고있는 것으로, 꽤 오랫동안 작동하는 것 같습니다.

    내가하는 일의 단순화 된 버전은 기본적으로 이와 같습니다. 공유 코어 파일과 여러 프로젝트가있는 응용 프로그램이 있습니다. 그 프로젝트 내에서 나는 모듈을 가지고있다. 핵심 레벨에서 전체 프로젝트에 사용할 수 있지만 특정 프로젝트에만 사용할 수있는 기능을 갖고 싶습니다.

    내 프로젝트 컨트롤러

    if(is_file(PROJECT_PATH.'/project_extensions.trait.php')){
      // additional functions for this specific project
      require_once(PROJECT_PATH.'/project_extensions.trait.php');
    }else{
      // no additional functions
      trait Extensions{};
    }
    
    
    Class Project{
      USE Extensions;
    
      // default functions shared between all projects
      function shared_stuff(){
    
      }
    }
    

    확장 프로그램 파일

    trait Extensions{
      // project-specific extensions
      function this_project_only(){
        echo 'Project Only';
      }
    }
    

    프로젝트의 모듈 파일

    class MyModule extends Modules{ // modules extends projects in a different class not relevant here
    
      function do_something(){
        echo $this->project_only();
      }
    }
    
  5. ==============================

    5.PHP5.4 릴리스부터 다음과 같이 동적 객체를 생성 할 수 있습니다. https://github.com/ptrofimov/jslikeobject

    PHP5.4 릴리스부터 다음과 같이 동적 객체를 생성 할 수 있습니다. https://github.com/ptrofimov/jslikeobject

    그러나 이것은 거의 모범 사례입니다.

  6. ==============================

    6.낡은 질문을 되 살리지 만 이것은 매우 간단한 해결책입니다. 클래스에 독점적 인 공통 함수 호출이 필요합니까? 그렇지 않은 경우 클래스와 동일한 범위 내에 공통 기능 파일을 포함 시키십시오. 클래스에 메서드를 만들어야하지만 공통 함수 만 호출하면됩니다. 다음은 간단한 SOAP 서버 예제입니다.

    낡은 질문을 되 살리지 만 이것은 매우 간단한 해결책입니다. 클래스에 독점적 인 공통 함수 호출이 필요합니까? 그렇지 않은 경우 클래스와 동일한 범위 내에 공통 기능 파일을 포함 시키십시오. 클래스에 메서드를 만들어야하지만 공통 함수 만 호출하면됩니다. 다음은 간단한 SOAP 서버 예제입니다.

    <?php
    
    include 'post_function.php';
    
    $server = new SoapServer( null, array('uri' => "http://localhost/") );
    $server->setClass(  'postsoapclass' );
    $server->handle();
    
    
    class postsoapclass
    {
        public function animalNoise( $animal )
        {
            return get_animal_noise($animal);
        }
    }
    
    ?>
    

    post_function.php

    <?php
    
    function get_animal_noise($animal)
    {
        if(strtolower(trim($animal)) == 'pig')
        {
            return 'Oink';
        }
        else 
        {
            return 'This animal is mute';
        }
    }
    
    ?>
    
  7. ==============================

    7.나는 같은 소프트웨어의 무료 버전과 프리미엄 버전을 유지하는 경우에 설명하고있는 것을해야만했다. @ Gordon이 지적했듯이, 당신은 정확히 이것을 할 수 없습니다 :

    나는 같은 소프트웨어의 무료 버전과 프리미엄 버전을 유지하는 경우에 설명하고있는 것을해야만했다. @ Gordon이 지적했듯이, 당신은 정확히 이것을 할 수 없습니다 :

    class SomeClass {  
    
      premium_file = "premium.php";
      if (file_exists($premium_file)) {
        require($premium_file);
      }
    

    대신 나는 이것을한다.

      premium_file = "premium.php";
      if (file_exists($premium_file)) {
        require($premium_file);
      }
    
      class SomeClass {
        ...
    

    참조하려는 함수의 경우 기본 클래스에서 클래스 메서드를 만들고 $ this 포인터를 매개 변수로 전달하여 포함 된 파일의 메서드를 호출합니다. 함수가있는 곳을 한눈에 알 수 있도록 아래와 같이 함수의 이름 앞에 접두사를 붙입니다.

      class SomeClass {
        ... 
        // Premium functions
        public function showlist() {
          premium_showlist($this);
        }
    
  8. from https://stackoverflow.com/questions/1957732/can-i-include-code-into-a-php-class by cc-by-sa and MIT license