2011-10-06 4 views
6

웹 페이지에서 계층 적 데이터를 스크랩하고 DB에 저장하도록 설계된 PHP 프로젝트를 자주 수행합니다 (본질적으로 데이터 구조화 - 데이터는 구조화 된 방식으로 제공하지 않음). 원래 웹 페이지가 PHP OOP 디자인 - 일반 인터페이스를 구현하는 동안 특정 하위 클래스에 매개 변수 제한

  • 이 쉽게 확장을 허용 변경하는 경우에,

    • 쉽게 새 것으로 현재 HTML 구문 분석 스크립트를 바꿉니다 때마다, 나는 나에게 다음과 같은 달성 할 수있는 것 인 OOP 디자인을 마련하려고 이 프로젝트는 다른 사람들이 데이터를 수집하고 빌드하는 데에도 사용되므로 데이터를 스크랩하고 저장해야합니다. 내 목표는 "기본"데이터를 수집하는 것입니다. 다른 사람들은 무언가를 추가하거나 저장 방법을 변경하기도합니다.

    지금까지 솔루션을 찾지 못했지만 가장 가까운 곳은 이런 식으로 뭔가 :

    내가 일반적인 나무 이송 기능을 구현하는 것이 데이터 컨테이너에 대한 추상 클래스를 정의

    abstract class DataContainer { 
    
        protected $parent = NULL; 
        protected $children = NULL; 
    
        public function getParent() { 
        return $this->parent; 
        } 
    
        public function getChildren() { 
        return $this->children; 
        }    
    } 
    

    그리고 나서 실제 데이터 컨테이너가 있습니다. 상원 의원 회의에서의 참여에 관한 자료를 "앉아있는 특정 질문"수준으로 내려고 상상해보십시오. SessionContainer, SittingContainer, QuestionContainer은 모두 DataContainer입니다.

    각 세션, 앉기 및 질문 데이터는 다른 URL에서 스크랩됩니다. URL 컨텐트를 가져 오는 메커니즘을 떠나서, 실제로 컨테이너를 가져 오는 스크래퍼 클래스와 실제 구문 분석을위한 DOmDocument가 필요하다고 가정 해 봅시다. , 그리고 세션의 각을

    interface Scraper { 
        public function scrapeData(DOMDocument $Dom, DataContainer $DataContainer); 
    } 
    

    을 앉아 문제는 인터페이스를 구현 자신의 스크레이퍼를했을 : 그래서 나는이 같은 일반적인 인터페이스를 정의한다. 그러나 나는 또한 그들이 의미하는 용기 만 받아 들일 수 있도록하고 싶다. 마지막으로

    class SessionScraper implements Scraper { 
        public function scrapeData(DOMDocument $DOM, SessionContainer $DataContainer) { 
        } 
    } 
    

    , 나는 또한 스크레이퍼 인터페이스를 구현하고 단지 관련 스크레이퍼로 긁어를 배포하는 일반적인 Factory 클래스있을 것입니다 :처럼 그래서 보일 것이다. 이와 같이 :

    public function scrapeData(DOMDocument $DOM, DataContainer $DataContainer) { 
        //get the scraper from configuration array 
        $class = $this->config[get_class($DataContainer)]; 
        $craper = new $class(); 
        $class->scrapeData($DOM, $DataContainer); 
    } 
    

    이것은 실제로 코드에서 호출되는 클래스입니다. 매우 비슷하게 DB에 저장하는 방법도 있습니다. 각 데이터 컨테이너에는 DBSaver 인터페이스가 구현되는 DBSaver 클래스가있을 수 있습니다. 다시 말하지만, 모든 호출은 DBSaver 인터페이스를 구현하는 Factory 클래스를 통해 수행 될 수 있습니다.

    모든 것이 완벽하지만 문제는 인터페이스를 구현하는 클래스가 인터페이스의 정확한 서명을 구현해야한다는 것입니다. 예 : 메서드 SessionScraper::scrapeData만 허용되며SessionContainer 개체는 모두 DataContainer 개체를 받아 들여야합니다. 그러나 그것은 의미가 아닙니다! 마지막으로

    질문 :

    • 내 디자인은 잘못이고 나는 완전히 다른 방식으로 모든 것을 구조화해야 하는가? (방법?) 또는 :
    • 내 디자인이 괜찮습니다. 형식화를 통해 instanceof 및 이와 유사한 검사를 사용하는 대신 형식을 적용해야합니다.

    모든 제안/비평에 대해 미리 감사드립니다. 필자는 필요한 경우이 코드를 머리에 뒤집어 쓰는 사람에게 매우 만족합니다!

  • 답변

    2

    Container 눈에 튀어 나와 있습니다. 이 이름은 매우 일반적이므로 좀 더 동적 인 것이 필요할 수도 있습니다. 제 생각에는 Data이고 classify 이니, type입니다.

    정확한 인터페이스를 유형 힌트에 하드 코드하는 대신 동적으로 해결해야합니다. 이제 각 Containertype을했을 경우

    Scraper는/신호가 Containertype에 대한 적용 여부를 알 수 있습니다.

    스크래핑의 구체적인 형태는 실제로 특정 데이터를 구문 분석하는 데 사용전략이다. 컨테이너 은 정규화 된 데이터에 대한 인터페이스를 제공하는이 전략을으로 캡슐화합니다.

    당신은 단지 그들 만이 서로 대화 할 수 있도록 ContainerScraper 사이에 약간의 논리/계약을 추가해야합니다. 이 계약은 두 인터페이스의 인터페이스 안에 넣을 수 있습니다.

    스트레칭을 원할 경우 types을 처리 할 수있는 Scraper도 허용됩니다.

    Container의 경우 반복기 (및 재귀 반복자)를 사용할 수 있도록 일부 인터페이스를 구현해야합니다. 이것은 당신이 언급하는 일반적인 구조 일 수 있으며, SPL은 여러분의 Container 클래스의 사용성을 높일 수 있습니다.

    OOP의 모든 것을 하드 코딩 할 필요는 없습니다. PHP를 사용하면 일을 동적으로 유지할 수 있으며 특히 런타임시 일반적으로 문제를 해결할 수 있습니다.

    이렇게하면 Scrapers을 새 버전으로 쉽게 대체 할 수 있습니다. Scrapers은 이제 위에서 정의한대로 정의에 따른 유형을 가지므로 런타임시 콘크리트 클래스가 스크래핑을 수행해야합니다 (예 : 좋은 파일 시스템 구조로 .php 파일에서 동적으로로드합니다.

    그냥 2 센트입니다.

    +0

    광범위한 답변을 주셔서 감사합니다. 몇 가지 다른 아이디어도 제시되었습니다. 한 가지 설명 - 모든 데이터를 유지하는 데 하나의 데이터/컨테이너 클래스를 사용하고 하위 클래스를 만드는 대신 유형 속성별로 식별하는 것이 좋습니다. 또는 두 유형의 속성 및 하위 클래스가 될 것이고, 스크래퍼는 유형 만 고려할 것입니다. – Aurimas

    +0

    귀하의 데이터를 구체적으로 알지 못하므로 알기가 어렵습니다. 데이터가 매우 공통적 인 경우에만 다른 속성을 가지고, 당신은 많은 데이터 클래스를 만들 필요가 없습니다, 당신은 동적 속성과 함께 갈 수 있습니다. 나중에 전체 응용 프로그램에서 훨씬 좋습니다. 주로 스크래퍼가 변경되며 때로는 데이터가 변경됩니다. 일부 웹 사이트가 조금 변경 되었기 때문에 항상 새로운 데이터 클래스를 만들어야합니다. 안좋다 :) – hakre