我可以包含代码到PHP类吗?

我想做一个PHP类,让我们说Myclass.php。 现在在这个类里面我只想定义类本身和一些实例variables。 但是所有的方法都必须来自Myclass_methods.php文件。 我可以将该文件包含到类体中吗?

我有很好的理由,为什么我要分开这个。 简而言之,我会有一个后端,在这个后端中我可以改变一个类的业务逻辑,而所有其他的东西都必须保持不变。 系统为我维护所有的ORM和其他东西。

但是,如果这是一个坏主意,在编辑业务逻辑之后重新生成整个类文件(在这种情况下是用户定义的方法)可能会更好。

性能问题:如果在一个请求中包含Myclass.php一次,实际上Myclass_methods.php也应该只包含一次。 可能是错的。 专家?

不可以。您不能在课程正文中包含文件。
在定义一个类的文件中,你只能在方法体中或者在类体外包含文件。

从你的描述我想你想这个:

<?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文件中包含函数和variables,但不包括方法。 你可以但不应该把整个脚本也放进去,并改变方法的作用,例如

 <?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中完成的。 这只是错误的,应该让你的眼睛stream血。

既然你想dynamic地改变行为,扩展类也不是一个好的select(见下文为什么)。 你真正想要做的是写一个接口,并让你的类使用实现这个接口的对象,从而确保适当的方法是可用的。 这就是所谓的战略模式 ,像这样工作:

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

现在你得到了所有Meowing Behaviors必须服从的合同,即有一个喵喵的方法。 接下来定义一个Meowing行为:

 <?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行为:

 <?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类,你必须考虑你想实现什么。 如果你的猫永远不会改变他们喵喵的方式,继续使用inheritance,但如果你的RegularCat和Lolkat应该能够做任意的喵,那么使用策略模式。

有关PHP中的更多devise模式 ,请查看以下资源:

用相关的基本function创build核心类并不是一个好主意,然后用所需的方法扩展它 – 这看起来更合乎逻辑。

我将首先说我不太清楚为什么使用包含方法,包含数据的子类和dynamic类加载的基类不能最好地解决这个问题。 我会假设你有一个很好的理由。

一旦你的提供者支持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'; } } 

通过命名两个包含文件相同,将它们放在不同的子目录中,并使用set_include_path()或定义一个__autoload()函数在它们之间进行select,可以使它更清晰。 就像我说的那样,使用inheritance可以更好地解决同样的问题。 如果你有一个多inheritancetypes的问题,例如,如果你有四种types的宠物,五种颜色,三种头发types,你需要60个不同类别的不同方法的组合,这是正确的解决scheme。

5.4目前只是发布候选版本(截至2012年2月24日),甚至一旦发布,大多数主机都不会支持它好几个月 – 我发布了5.3个发布之后的18个月才支持它。 在此之前,您必须编写完全独立且完整的类文件。 然而,你可以devise你的课程,最终改变你的特质。

现在,你可以使用魔法方法部分得到你想要的东西,并在有可用的情况下轻松升级到特征。

代码文件:

 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'; } 

然而,你的function是有限的,因为你的函数不能访问私有和受保护的类属性和方法,你不能使用这个方法来提供诸如__get()之类的魔术方法。 性状将解决这两个限制。

那么使用这个特性呢? 这是一个可以接受的select吗? 这是我目前正在试验的东西,它似乎工作很长一段时间。

我正在做的简化版本基本上是这样的。 我有一个共享核心文件和多个项目的应用程序。 在这些项目中,我有模块。 我想要在核心层面上为整个项目提供可用的function,但仅限于该特定项目。

我的项目控制器

 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(); } } 

我可以将该文件包含到类体中吗?

没有。

PHP5.4发布以来,您可以创build如下所示的dynamic对象 : https : //github.com/ptrofimov/jslikeobject

但这几乎不是最好的做法。

振兴一个老问题,但这是一个相当简单的解决scheme。 你需要通用的函数调用来排除你的类吗? 如果没有,只需将您的通用函数文件包含在与您的课程相同的范围内即可。 你将需要在你的类中创build方法,但他们只需要调用通用函数。 这是一个简单的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'; } } ?> 

我必须做你所描述的情况下,我维护一个免费版本和高级版本的相同的软件。 因为,正如@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 { ... 

对于要引用的函数,在主类中创build类方法,并调用包含文件的方法,将$this指针作为parameter passing。 所以我可以一目了然地告诉函数在哪里,我将前缀所包含函数的名称如下所示:

  class SomeClass { ... // Premium functions public function showlist() { premium_showlist($this); }