PHP中JavaScript样式的对象文字

The object literal notation in JavaScript looks like:

JavaScript中的对象文字表示法如下所示:

var fido = {name: "Fido", barks: true};

or

要么

var fido = {};
fido.name = "Fido";
fido.barks = true;

从assoc数组到对象 (From assoc arrays to objects)

In PHP you would call that an associative array.

在PHP中,您将其称为关联数组。

$fido = array(
  'name' => "Fido",
  'barks' => true
);

And you can easily make it an object too:

您也可以轻松地使其成为对象:

$fido = (object)$fido;
echo gettype($fido); // "object"

Or if you want to start with a blank object and add stuff to it:

或者,如果您想从一个空白对象开始并向其添加内容:

$fido = (object)array();

or

要么

$fido = new StdClass();

and then

接着

$fido->name = "Fido";
$fido->barks = true;

A little explanation maybe: objects in JavaScript are hashes, maps, whatever you decide to call them. Objects in PHP were an afterthought in the language and (at least initially) were not much more than "fancy arrays". Fancy associative arrays (hashes, maps, whatever you call them).

可能有一些解释:JavaScript中的对象是散列,映射,无论您决定调用它们如何。 PHP中的对象是该语言中的事后思考,并且(至少在最初)仅是“ fancy arrays”。 花式关联数组(哈希,映射,无论您如何称呼它们)。

Objects in PHP need a class, but the new stdClass() lets you start quickly without the class {...} jazz. Same for casting an array (upgrading it in its fanciness) to an object with (object)array().

PHP中的对象需要一个类,但是new stdClass()可让您快速new stdClass() ,而无需使用class {...}爵士乐。 使用(object)array()将数组强制转换为对象(升级(object)array()

So far - so good. What about methods?

到现在为止还挺好。 那方法呢?

方法有人吗? (Methods anyone?)

JavaScript doesn't care about properties versus methods. It's all members of an object (like elements of an assoc array). Only if a member happens to be a function, it's invokable.

JavaScript不在乎属性与方法。 它是对象的所有成员(如assoc数组的元素)。 仅当成员恰好是一个函数时,它才可以调用。

fido.say = function () {
  if (this.barks) {
    return "Woof!";
  }
};
 
fido.say(); // "Woof!"

Turns out, since PHP 5.3 there are closures in PHP too. So you can do:

事实证明,从PHP 5.3开始,PHP中也有闭包。 因此,您可以执行以下操作:

$fido->say = function() {
  if ($this->barks) {
    return "Woof";
  }
};

The difference is that $fido->say() won't work. Two reasons for that:

不同之处在于$fido->say()将不起作用。 这有两个原因:

  1. say is not a method. It's a property. For PHP it matters. You can however assign the property say to a new variable $callme. This variable is now a closure object. As such you can invoke it:

    say不是方法。 这是财产。 对于PHP来说很重要。 但是,您可以将属性say分配给新变量$callme 。 现在,此变量是一个闭包对象。 这样,您可以调用它:

    $callme = $fido->say;
    echo $callme();
    

    Note the $ in $callme().

    注意$$callme()

  2. the above will also fail because $this is an weird context and doesn't point to the object $fido. But you can use $self and point it to the global object $fido.

    上面的方法也会失败,因为$this是一个怪异的上下文,并且不指向对象$fido 。 但是您可以使用$self并将其指向全局对象$fido

So that's a little .... unpretty, but it works:

所以有点....不太漂亮,但是可以用:

$fido = (object)array();
$fido->name = "Fido";
$fido->barks = true;
 
$fido->say = function() {
  $self =& $GLOBALS['fido'];
  if ($self->barks) {
    return "Woof";
  }
};
 
$callme = $fido->say;
echo $callme(); // "Woff!"

还有一点魔法 (And a sprinkle of magic)

We can make this prettier with the help of a little PHP magic. PHP has some magic methods going on and one of these is the __call() method. If you implement it in a class, then it will be invoked whenever someone tries to call a method that doesn't exist.

我们可以借助一点点PHP魔术使它更漂亮。 PHP有一些不可思议的方法,其中一种是__call()方法。 如果您在类中实现它,那么当有人尝试调用一个不存在的方法时,它将被调用。

In our case $fido->say is not a method. So __call can intercept $fido->say() calls and invoke the $fido->say property as a closure object. Closures are callable and call_user_func() and call_user_func_array() work fine with them. So all in all we should make this work:

在我们的例子中, $fido->say不是一种方法。 因此__call可以拦截$fido->say()调用并调用$fido->say属性作为关闭对象。 闭包是可调用的,并且call_user_func()call_user_func_array()可以正常使用。 所以总而言之,我们应该使这项工作:

$fido = new JSObject();
$fido->name = "Fido";
$fido->barks = true;
 
$fido->say = function($self) {
  if ($self->barks) {
    return "Woof";
  }
};
 
echo $fido->say();

As you can see, very JavaScript-esque. Except that $this is $self and will always be the first argument passed to every method. The secret sauce to make this happen is the JSObject() class.

如您所见,非常具有JavaScript风格。 除了$this$self ,它将始终是传递给每个方法的第一个参数。 实现此目的的秘诀是JSObject()类。

class JSObject {
  function __call($name, $args) {
    if (is_callable($this->$name)) {
      array_unshift($args, $this);
      return call_user_func_array($this->$name, $args);
    }
  }
}

Nice and easy. Namely:

好,易于。 即:

  1. __call takes the name of the missing method and any arguments.

    __call使用缺少的方法的名称和任何参数。

  2. It checks whether there's a callable property with the same name (a closure object property).

    它检查是否存在具有相同名称的可调用属性(闭包对象属性)。
  3. It adds $this to the arguments list and calls the closure.

    它将$this添加到参数列表并调用闭包。

Yupee! Now you can haz moar class-less JS-like PHP objects 🙂

雅皮! 现在,您可以消除无类的类似于JSPHP对象🙂

(Note that $this->$name is not a typo and should not be $this->name because it's a dynamic property name.)

(请注意, $this->$name $this->name $this->$name不是错字,也不应该是$this->name因为它是动态属性名。)

还有一件事 (And one more thing)

If we add a constructor to JSObject, it can accept any properties at creation time. So you can be even closer to JavaScript and allow both creating an "empty" object and adding to it later, or creating an object and adding properties simultaneously.

如果我们向JSObject添加构造函数,则它可以在创建时接受任何属性。 因此,您甚至可以更接近JavaScript,并允许创建“空”对象并在以后添加它,或者允许同时创建对象和添加属性。

The slightly modified JSObject:

稍微修改的JSObject

class JSObject {
  function __construct($members = array()) {
    foreach ($members as $name => $value) {
      $this->$name = $value;
    }
  }
  function __call($name, $args) {
    if (is_callable($this->$name)) {
      array_unshift($args, $this);
      return call_user_func_array($this->$name, $args);
    }
  }
}

And example use:

和示例使用:

$fido = new JSObject(array(
  'name' => "Fido",
  'barks'=> true,
  'say'  => function($self) {
    if ($self->barks) {
      return "Woof";
    }
  }
));
 
echo $fido->say(); // "Woff"

This is pretty close to what you can have in JavaScript (adding $ and ' even though we can do without them), only changing a few things like -> to . and => to :

这非常接近您在JavaScript中可以实现的功能(即使没有$'也可以添加$' ),仅将->更改为.=>:

$fido = {
  'name' : "Fido",
  'barks': true,
  'say'  : function() {
    if (this.barks) {
      return "Woof";
    }
  }
};
$fido.say(); // Woof

JS and PHP look like twins now don't they.

JS和PHP看起来像双胞胎,现在不是了。

confoo.ca上PHP开发人员JS (JS for PHP devs at confoo.ca)

This was extracted from a talk I gave at the confoo.ca conference a week or so ago. Below are the slides:

摘录自我一周左右在confoo.ca会议上的演讲。 以下是幻灯片:

Tell your friends about this post on Facebook and Twitter

FacebookTwitter上告诉您的朋友有关此帖子的信息

翻译自: https://www.phpied.com/javascript-style-object-literals-in-php/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值