简体   繁体   English

PHP - 静态 vs 实例方法

[英]PHP - Static vs Instance Method

I'm a little bit confused as I don't have much experience in OOP in PHP.我有点困惑,因为我在 PHP 的 OOP 方面没有太多经验。 I always hear that using instance methods is a better practice than using static methods, why is that?我总是听说使用实例方法比使用静态方法更好,这是为什么呢?

I need a deep answer with an explanation, please.我需要一个深刻的答案和解释,请。

For example why this below should be done with the instance method?例如,为什么下面应该使用实例方法来完成?

Controller:控制器:

public function getProperty($id){
        $property = Property::getProperty($id);
        return $property;
}

Model:模型:

public static function getProperty($id){
        //$query = DB::table('properties')...
        //Some Code;
        return $query;         
}

I'm reading about setter/getter, instance vs static and etc. But I need a complete answer to understand the how and why of things.我正在阅读有关 setter/getter、实例与静态等的信息。但我需要一个完整的答案来了解事物的方式原因

In general, as you've already stated, instance methods are the better practice.一般来说,正如您已经说过的,实例方法是更好的做法。 That isn't to say that static methods are downright evil, they simply have a different and unique purpose.这并不是说静态方法是彻头彻尾的邪恶,它们只是具有不同且独特的目的。

It is important to note that when dealing with instance methods you are working with an object whereas with static methods you are working with a class .需要注意的是用实例的方法处理,当你与对象的工作,而用静态方法您使用的是的工作是很重要的 When using static methods you will not have access to any of your non-static properties that would normally be available with an instance.使用静态方法时,您将无法访问通常可用于实例的任何非静态属性。

Take the following code as an example:以下面的代码为例:

class Foo
{
    private $bar;
    private static $tavern;

    public function changeBar($value)
    {
        $this->bar = $value;
    }

    public function getBar()
    {
        return $this->bar;
    }

    public static function changeTavern($value)
    {
        self::$tavern = $value;
    }

    public static function getTavern()
    {
        return self::$tavern;
    }
}

Class Foo has a static property $tavern and a non-static property $bar . Foo类有一个静态属性$tavern和一个非静态属性$bar

If an instance of Foo is created then all properties and methods are available to that object .如果创建了Foo的实例,则该对象可以使用所有属性和方法。

If Foo is referenced statically then only the $tavern property, changeTavern() method and getTavern() method are available to the class .如果Foo被引用静态那么只有$tavern财产, changeTavern()方法和getTavern()方法可用于

Let's look at the following code:让我们看看下面的代码:

$foo = new Foo();
$foo->changeBar('Tipsy Turvy');
echo $foo->getBar(); // prints Tipsy Turvy

Since $foo is an instance of Foo , it has access to the entire class.由于$fooFoo一个实例,它可以访问整个类。 Calling changeBar() will modify the $bar property.调用changeBar()将修改$bar属性。 To change the $bar property directly from a static method will trigger an error since $bar is available to the object and not the class .直接从静态方法更改$bar属性将触发错误,因为$bar可用于对象而不是

// Calling this method would trigger an error
public static function changeBar($value)
{
    $this->bar = $value; // PHP will crash and burn if you try this.
}

If you want to access class properties from static methods those properties must also be declared static.如果您想从静态方法访问类属性,这些属性也必须声明为静态。 This will work in the context of the class above.这将在上述类的上下文中起作用。 You'll also note that an instance of Foo has no problem reading static properties.您还会注意到Foo的实例读取静态属性没有问题。

Foo::changeTavern('Stumble Inn');
echo Foo::getTavern(); // prints Stumble Inn
echo $foo->getTavern(); // also prints Stumble Inn

Another thing to remember about static code is that it doesn't behave like an instance.关于静态代码要记住的另一件事是它的行为不像一个实例。 When the first instance of Foo was built both properties $bar and $tavern had no value.Foo的第一个实例被构建时,属性$bar$tavern都没有价值。 If you were to create another instance of Foo you would find that only one of those properties no longer contains a value.如果您要创建Foo另一个实例,您会发现这些属性中只有一个不再包含值。 (I'm sure by now you can guess which one.) (我相信你现在可以猜到是哪一个了。)

$anotherFoo = new Foo();
echo $anotherFoo->getBar(); // prints nothing
echo $anotherFoo->getTavern(); // prints Stumble Inn
echo Foo::getTavern(); // prints Stumble Inn

So again, static code means you are working directly with a class - instances mean you are working with an object .同样,静态代码意味着您直接使用- 实例意味着您正在使用对象 It is important to note that any type of class you write that intends to have some kind of state to it should be used as an instance.重要的是要注意,您编写的任何类型的类都应该具有某种状态,都应该用作实例。

Static classes can be a little difficult to debug and test.静态类可能有点难以调试和测试。 Testing can be problematic because static properties don't change when you create a new instance.测试可能会出现问题,因为创建新实例时静态属性不会更改。 Debugging can also be difficult since the value of a static property is the same across all instances of an class.调试也很困难,因为静态属性的值在类的所有实例中都是相同的。 Make a change in one and you will make that change in all of them.对其中一个进行更改,您将对所有这些更改进行更改。 Tracking down which instance made the change is a pain.跟踪哪个实例进行了更改是很痛苦的。

Speaking metaphorically, use static classes like sugar - sparingly and only when necessary.比喻地说,使用像糖这样的静态类 - 有节制地并且仅在必要时使用。

Hope that helps shed some light on the topic.希望这有助于阐明这个话题。

Instance method is not better then static, they are simply meant to be used differently.实例方法并不比静态方法好,它们只是为了不同地使用。 For example it would be insane to make factory method non-static.例如,将工厂方法设为非静态是很疯狂的。

Generally make instance method when method has something to do with current instance of the class (uses some state of this object, configuration parameters maybe) and static if it just belongs to the class as a whole like creating a new object, processing primitives...当方法与类的当前实例有关(使用此对象的某些状态,可能是配置参数)时,通常创建实例方法,如果它只属于整个类,例如创建新对象,处理原语.. .

Eg ActiveRecords pattern often uses instance as mapping of record, so instance methods read/operate on the record, and static methods like searching, mass updating/deleting etc.例如, ActiveRecords模式通常使用实例作为记录的映射,因此实例方法读取/操作记录,以及静态方法,如搜索、批量更新/删除等。

I would agree with Cthulhu.我会同意克苏鲁。 Making a static method means you should not need to create an instance of the class to initiate the function.使用静态方法意味着您不需要创建类的实例来启动函数。

I would love to explain using a small example based on his ActiveRecord pattern.我很想用一个基于他的 ActiveRecord 模式的小例子来解释。

Let's sat we are writing our own AR pattern using a class that represents the Table "orders", which contain (like you could imagine) multiple order records.让我们坐下来,我们正在使用一个表示表“订单”的类编写我们自己的 AR 模式,该表包含(如您想象的那样)多个订单记录。

If you use PDO as an connection class, you need to initiate this somewhere.如果您使用 PDO 作为连接类,则需要在某处启动它。 In this example the initialization is initiated in the static method of the "order" class.在这个例子中,初始化是在“order”类的静态方法中启动的。 Since you need to be able to "run this" before being able to query the database to get an order.因为在能够查询数据库以获取订单之前,您需要能够“运行它”。

class order {
   public $data;

   public static $connection;

   public static function dbConnect($host, $database, $username, $password)   
   {
       try {
           self::$connection = new PDO(
               'mysql:host='.host.';dbname='.database, 
               $username,
               $password
           );
       } catch (PDOException $e) {
           print "Error!: " . $e->getMessage() . "<br/>";
           die();
       }
   }

    public function getOrderById($id)
    {
        $stmt = self::$connection->prepare('SELECT * FROM orders WHERE id = :id LIMIT 1');
        $stmt->execute(
            array('id', $id)
        );

        $this->data = $stmt->fetch();
    }
}

$order::dbConnect('localhost', 'myDb', 'user', '123test');
$order1 = new Order();
$order1->getOrderById(1);

$order2 = new order();
$order2->getOrderById(2);

print_r($order1->data);

print_r($order2->data);

Please ignore the fact that there are a lot of optimizations you could do to the actual result set or save it to the actual object.请忽略您可以对实际结果集进行大量优化或将其保存到实际对象的事实。 The main purpose of this code is to explain the fact when I would use static versus instance.这段代码的主要目的是解释我何时使用静态与实例的事实。

First of all it's not always better but in most cases it is.首先,它并不总是更好,但在大多数情况下确实如此。 There are several reasons behind not using static methods:不使用静态方法有几个原因:

  1. It's harder to put class on tests if it has static methods如果类具有静态方法,则更难对其进行测试
  2. It's harder to extend this class if you want a little different behavior for same method如果您希望同一方法的行为略有不同,则扩展此类会更困难
  3. Very often your static methods in class are just a way of making it global variable which almost always is a bad idea通常,您在类中的静态方法只是使其成为全局变量的一种方式,这几乎总是一个坏主意
  4. Refactoring this class will become hell if suddenly you decide that you need some class variable inside static method (change all Class::Method() calls to $c = new Class(); $c->Method())如果您突然决定在静态方法中需要一些类变量(将所有 Class::Method() 调用更改为 $c = new Class(); $c->Method()),则重构此类将变得非常糟糕

I strongly invite you to read a little bit more about unit tests.我强烈邀请您阅读更多有关单元测试的信息。 When some other class is using yours with static method, then putting it to tests may be a challenge.当其他一些类将您的类与静态方法一起使用时,将其进行测试可能是一个挑战。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM