现代方式在php中声明一个类

时间:2010-08-13 08:05:40

标签: php class

想要确保我正确使用课程。主脚本从用户接受:

1. month
2. year
3. the type of event they want to find (microsoft or linux)

要找到微软事件的程序,必须运行正则表达式:'(ID =)+ [0-9] +' 要使程序找到linux事件,必须运行正则表达式:'(ID =)+ [A-F] +'

创建Events类似乎是组织代码的合理方式。如果可能的话,我不想从主脚本中将所需的正则表达式发送到类中。我想告诉events类它是微软还是linux事件,让类根据每个类型事件在类中预定义的变量返回处理过的数据。

我现有代码编写为:

 class Events
    {
            var $month;
            var $year;
            var $event_identifier_expression;

      public function events($month, $year)
      {
       $this->month = $month;
       $this->year = $year;
       return $this->event_identifier_expression.$month.$year;
      }
    }

我想在Events类中使用类似多个静态帮助器方法的东西。如果我将现有代码更改为下面的代码,它是否允许我独立于类外部调用microsoft_events和linux_events,这是创建类的正确方法吗? (赞赏从类外部调用静态函数的示例代码):

class Events
    {
            public function __construct()
            {var $month;
             var $year;
             var $event_identifier_expression;
            } 

      public static function microsoft_events($month, $year)
      {
       $this->month = $month;
       $this->year = $year;
       $this->event_identifier_expression = '(ID=)+[0-9]+';
       return $this->event_identifier_expression.$month.$year;
      }
      public static function linux_events($month, $year)
      {
       $this->month = $month;
       $this->year = $year;
       $this->event_identifier_expression = '(ID=)+[A-F]+';
       return $this->event_identifier_expression.$month.$year;
      }
    }

4 个答案:

答案 0 :(得分:4)

如果你想静态地使用所有东西(这使它基本上是一段漂亮的程序代码),你将不得不做这样的事情:

class Events
{
   static protected $month;
   static protected $year;

   public static function microsoft_events($month, $year)
   {
      self::$month = $month;
      self::$year = $year;
   }
   public static function linux_events($month, $year)
   {
      self::$month = $month;
      self::$year = $year;
   }
}

Events::microsoft_events(12, 2010);

请注意,您只能拥有一个实例,每次调用都会更改所有内容的值。

答案 1 :(得分:3)

$这不能在静态方法中使用 - 不能假设该类将在这里实例化...

您必须按照以下方式声明您的课程:

class Events
    {
        public static $month;
        public static $year;

        public function __construct(){    }

        public static function microsoft_events($month, $year)
        {
            self::month = $month;
            self::year = $year;
        }

        public static function linux_events($month, $year)
        {
            self::month = $month;
            self::year = $year;

            //do something?

            if(self::month == 'March' && self::year == '2010'){
                return 'Linux horoscope looks great';
            }
            return self::month . ' ' . self::year . ' is even better!';
        }
}

通话:

$returnedVar = Events::linux_events('March', '2010');

答案 2 :(得分:3)

在我的头顶,我可以建议像

/// Raw event data, e.g. database
class EventStore { 
    function getRawDataMatching($pattern) {
       // query the db
    }
 }

/// Mother of all Event types
abstract class Event {
    static function getSearchPattern() {
       // return the search pattern for the concrete event class
    }
    function __construct($rawData) {
       // initialize from the raw data
    }
}

/// Concrete event classes
class MicrosoftEvent extends Event {...}
class LinuxEvent extends Event {...}

/// Find events in the stream
class EventFinder 
{
    function __construct(EventStore $store) { ... }

    function classFor($type) {
      // return event class name for the given type
    }

    function find($date, $type) {
       $klass = $this->classFor($type);
       $pattern = $klass::getSearchPattern();
       foreach($this->store->getRawDataMatching($pattern) as $data)
            $result[] = new $klass($data)

    }
}

// main code
$store = new EventStore($connectInfo);
$finder = new EventFinder($store);
$foundEvents = $finder->find($input->date, $input->type);

当然,这是许多可能的方式之一。如果您需要进一步的评论,请告诉我。

答案 3 :(得分:3)

我建议采用不同的方法。对每种偶数类型使用不同的方法将需要您编写重复代码,这最终将导致代价高昂的可维护代码并且容易出错(即使复制/粘贴也容易出错!我在一些项目中已经看到它以证明它)。 / p>

首先,当方法要求在类成员中存储数据时,静态调用应该仅限制(或大部分);静态方法不应该设置任何东西,更少的数据由类本身的实例使用。因此,您应该使用单例模式。

其次,如果你应该有很多事件类型,每个事件都应该有适当的专业类。面向对象的设计从抽象到具体,从一般到专业。因此,您的Events不应该知道它存储了多少或哪些事件,但应该将其保留给调用者。这将使您能够拥有更加一致的界面。

这是一个示例设计:

class Events {

   static private $_instance;

   static public function getInstance() {
      // lazy loading of the class instance will not use unnecessary resources
      if (null === self::$_instance) {
         self::$_instance = new self();  // <-- valid PHP declaration
      }
      return self::$_instance;
   }

   // class members

   protected $_events;      // protected allows inheritance, use private to forbid it

   // private constructor prohibit external instances to be created
   private function __construct() {
      $this->_events = array();
   }

   // (GETTER: methods that starts with 'get'...)
   // use $year before $month for priority order ($month is more precise than $year)
   public function getEvents($type, $year = null, $month = null) {
      $_values = array();

      // if we have any event of that type...
      if (array_key_exists($type, $this->_events)) {
         foreach ($this->_events[$type] as $event) {
            // filter events to return... (if $year is null, $month is ignored)
            if ((null === $year 
              || (($year == $event->getYear())
              && (null === $month || $month == $event->getMonth()) )) ) {

               $_values[] = $event;
            }
         }
      }

      return $_values;
   }

   // (SETTER: methods that starts with 'add', 'set', etc.)
   public function addEvent(AbstractEvent $event) {
      if (!array_key_exists($event->getType(), $this->_events)) {
         $this->_events[$event->getType()] = array();
      }
      $this->_events[$event->getType()][] = $event;

      // returning $this allows chaining. 
      // While some argue the design of this, I personally like it
      return $this;
   }

}

现在我们有了容器,我们需要事件类型,首先我们有基类:

abstract class AbstractEvent {
   protected $_year;    // again, protected to enable inheritance
   protected $_month;

   public function __construct($year, $month) {
      // TODO : perform some argument check here
      $this->_year = $year;
      $this->_month = $month;
   }

   abstract public function getType();
   public function getYear() { return $this->_year; }
   public function getMonth() { return $this->_month; }
}

然后,只需将它专门化(我们创建两个特殊事件类型):

class MicrosoftEvent extends AbstractEvent {
   const TYPE = 'Microsoft';
   public function getType() { return self::TYPE; }
}

class LinuxEvent extends AbstractEvent {
   const TYPE = 'Linux';
   public function getType() { return self::TYPE; }
}

添加新活动

Events::getInstance()
  ->addEvent( new LinuxEvent(2010, 7) )
  ->addEvent( new MicrosoftEvent(2008, 8) )
  ->addEvent( new MicrosoftEvent(2010, 2) )
  ->addEvent( new LinuxEvent(2009, 1) )
  // ...
;

获取活动

// 1. get ALL Microsoft events
var_export( Events::getInstance()->getEvents(MicrosoftEvent::TYPE) );
// 2. get all events for 'Linux' in 2010
var_export( Events::getInstance()->getEvents('Linux', 2010) );
// 3. same as 1; $month will be ignored, because $year is not specified
var_export( Events::getInstance()->getEvents('Microsoft', null, 6) );
// 4. returns empty array because unknown event type
var_export( Events::getInstance()->getEvents('Foo') );

正如您所看到的,类设计的开销稍微复杂一点,但之后API更加一致。一个好的设计必须应用可重复使用的模式,这是在这里完成的。希望这会有所帮助。

******编辑****因为您的问题已经更改,这是一个经过编辑的解决方案。它要小得多,但仍遵循相同的基础设计:

class Events {

   static private $_events = array();

   // GETTER
   static public function getEventType($type) {
      // if we have any event of that type...
      if (!array_key_exists($type, self::$_events)) {
         $eventClass = $type . 'Event';
         self::$_events[$type] = new $eventClass();
      }

      return self::$_events[$type];
   }

}

然后是我们的基本事件类型类

abstract class AbstractEvent {
   abstract public function getType();
   public function getIdentifier($year, $month) {
      return $this->getType().str_pad((int) $month, 2, '0', STR_PAD_LEFT).str_pad((int) $year, 4, '0', STR_PAD_LEFT);
   }
}

现在,我们专注于类型

class MicrosoftEvent extends AbstractEvent {
   const TYPE = 'Microsoft';
   public function getType() { return self::TYPE; }
}

class LinuxEvent extends AbstractEvent {
   const TYPE = 'Linux';
   public function getType() { return self::TYPE; }
}

然后我们测试结果

var_export( Events::getEventType(MicrosoftEvent::TYPE)->getIdentifier(2008, 6) );
var_export( Events::getEventType(LinuxEvent::TYPE)->getIdentifier(2010, 2) );
var_export( Events::getEventType('Microsoft')->getIdentifier('2009', '08') );