我可以包括代码到一个PHP类?我可以包括代码到一个PHP类?(Can I include code

2019-05-08 20:59发布

我想打一个PHP类,可以说Myclass.php。 现在,类中我想仅仅定义类本身和一些实例变量。 但所有的方法都必须来自Myclass_methods.php文件。 可我只是包括文件放入类体?

我有我为什么要单独这个很好的理由。 总之,我将有一个后端中,我可以改变一个类的业务逻辑,而其他所有的东西必须保持不变。 该系统维护所有ORM和其他的东西给我。

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

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

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

这样做,这样,将导入包括文件的内容到方法的范围,而不是类范围。 您可以包括在包含文件中的函数和变量,而不是方法。 你可以,但不应该把整个脚本到它以及和改变方法做什么,例如,

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

由于要动态改变行为,扩展类也不是一个好的选择(参见下面的原因)。 你真的会想要做的就是写一个接口 ,使您的类使用对象实现了这个接口,从而确保适当的方法是可用的。 这就是所谓的策略模式和工作方式如下:

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

你现在明白了所有的喵喵叫声行为必须服从,即有喵方法合同。 接下来定义喵喵叫的行为:

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

通过添加喵喵叫TypeHint到setMeowing,您确保传递PARAM实现喵喵叫声接口。 让我们来定义另一喵喵叫的行为:

<?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和喵方法,然后从推导具体RegularCat和Lolkat类,你要考虑你想要达到的目标。 如果你的猫绝不会改变他们喵的方式,继续使用继承,但是如果你的RegularCat和Lolkat应该是能够做到任意的叫声,然后使用策略模式。

欲了解更多的设计模式在PHP中,检查这些资源:

  • http://www.php.net/manual/en/language.oop5.patterns.php
  • http://www.ibm.com/developerworks/library/os-php-designptrns/
  • http://www.fluffycat.com/PHP-Design-Patterns/
  • http://sourcemaking.com/design_patterns


Answer 2:

会不会反而是一个想法,建立与相关基本功能的核心类,然后用所需的方法扩展这一点 - 这似乎是一个更合乎逻辑的做法。



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

你能做出这样即使命名都包括文件一样,将它们放在不同的子目录,并使用通过set_include_path()或定义一个__autoload()函数,它们之间进行选择清洁剂。 就像我,虽然说,这个同样的问题可以通过继承来解决更好。 如果你有多重继承的类型问题,虽然,举例来说如果你出现四种宠物有5种机身颜色有三个类型的头发,你需要为每个60种不同类的方法的不同组合,这是一个正确的解决方案。

5.4目前只是一个发布候选(截至2/24/2012),甚至一旦释放大多数主机不支持很多个月了 - 我的花了18个月后,5.3发布,他们会支持它。 在那之前,你必须编写完全独立的,完整的类文件。 但是,您可以在考虑最终改变性状格式化类。

现在你可以部分地得到你想要使用什么神奇的方法,并有一个简单的升级特性可用时。

代码文件:

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

你在你的函数不能访问私有和受保护类的属性和方法,但是有限的,你不能用这种方法来提供魔术方法如__get()。 性状将解决这两个限制。



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


Answer 5:

由于PHP5.4版本中,您可以创建这样的动态对象 : https://github.com/ptrofimov/jslikeobject

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



Answer 6:

回想起一个老问题,但是这是一个相当简单的解决方案。 你所需要的常用函数调用来独占你的课? 如果没有,那么只需在同一范围内的类中的常用功能的文件(S)。 您将需要创建类的方法,但他们将只需要调用常用功能。 这里有一个简单的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';
    }
}

?>


Answer 7:

我不得不这样做,你的情况是描述什么,我保持一个免费版本和相同软件的高级版本。 因为,@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);
    }


Answer 8:

我碰到这个最近来了,并用一个解决方案,在我的情况下帮助了上来。 我想很多功能的一类,但是类变得臃肿,于是就想类的功能分离出成组的可读性。 它花了一些时间来完成,但由于该类的功能并不依赖于$这个(多),我删除了“$这个”从类的功能,创造了几个辅助文件,包括那些功能。 当$,这是必要的,我还是动功能到一个辅助文件,通过传递$此的功能,提升公共设置/获取功能在必要。 这是一个黑客,但它一定要帮助别人

`MyClass类{风险X;

    function myClass()
    {
        $this->x = 0;
    }

    function myFunc1Group1()
    {
        $x = $this->x;
        $x++;
        $this->x = $x;
    }
    function myFunc2Group1(){}

    function myFunc1Group2(){}
    function myFunc2Group2(){}
}

`

可以四处努力

`MyClass类{风险X;

    function myClass()
    {
        $this->x = 0;
    }

    function doSomething()
    {
        // not called on $this but takes $this as a parameter
        myFunc1Group1($this);
    }
}

`

和辅助功能设置1

function myFunc1Group1($THIS_OBJECT) { $x = $THIS_OBJECT->getX(); $x++; $THIS_OBJECT->setX($x); } function myFunc2Group1($THIS_OBJECT){}

和辅助功能设置2等

也许不是在所有情况下的最佳途径,但帮了我很多。 基本上类函数只构造和代表,以及计算投入的帮手。



文章来源: Can I include code into a PHP class?
标签: php oop class