php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #67171 Object Notation (like mysqli::fetch_object)
Submitted: 2014-05-01 18:02 UTC Modified: 2014-05-01 19:41 UTC
From: fleshgrinder at gmx dot at Assigned:
Status: Duplicate Package: Unknown/Other Function
PHP Version: Irrelevant OS:
Private report: No CVE-ID: None
 [2014-05-01 18:02 UTC] fleshgrinder at gmx dot at
Description:
------------
It would be great to see something like the new array notation for objects as well, as it would greatly improve writing easy to understand code and allow IDEs to help developers write code faster. I was thinking about this for some time and I think I came to a solution that would meet these requirements, now it would only need somebody who knows how to implement this in PHP.

We already have the new array syntax, like in JavaScript:

$array = [ "key" => "value" ];

To generate an object from the array one has to do the following:

$object = (object) [ "key" => "value" ];

It would be great if this could be shortened to the following (like in JavaScript):

// Of course the syntax doesn't matter, but read on why I wrote it like this.
$object = { $key => "value" };

This would result in an \stdClass instance:

var_dump($object);
object(stdClass)#1 (1) { ["key"]=> string(5) "value" }

This would already be an improvement, as one can now easily enable IDE users with auto-completion:

/* @var $object \MyStubClass */
$object = { $key => "value" };

But we could even go a step further with this and allow something like the following:

class Foo {

  /**
   * Documentation that is displayed in IDEs.
   *
   * @var string
   */
  public $property1;

  /**
   * Documentation that is displayed in IDEs.
   *
   * @var string
   */
  public $property2;

  /**
   * Not accessible!
   */
  protected $protectedProperty;

  /**
   * Not accessible!
   */
  private $privateProperty;

}

$foo = {\Foo
  $property1 => "value",
  $property2 => "value",
};

var_dump($foo);

object(Foo)#1 (2) { ["property1"]=> string(5) "value" ["property2"]=> string(5) "value" } 

# Where's the benefit?

Well, imagine something like Drupal's Form API https://api.drupal.org/api/drupal/developer!topics!forms_api_reference.html/8 where you have to pass associative arrays with various offsets. You'll have absolutely no clue what offsets are available to you if you don't have the documentation page available. With the above, this wouldn't be any problem. See the "Test script" section for a real world Drupal Form API example that would greatly help any developer who uses an IDE.

# Why do you propose this exact syntax?

Defining the class name directly after the opening curly brace should be easy to parse, because you'll always get the {\ combination which should be pretty unique.

The dollar before the keys is used for IDEs, so that they know that this supposed to be an existing property within the class. This would allow proper auto-completion support for properties, e.g. {\Foo $ and now if we hit Ctrl + Space the IDE kicks in (or it kicks in after its own time out, doesn't matter).

The => combination was only used because developers are already used to it from arrays since many, many years. Of course the JavaScript syntax would be a valid alternative and faster to write (e.g. { $key: "value" });

It's important to note the last comma I included in all examples, as we know it from arrays. This has to work to minimize errors and mistakes, like with arrays.

# Anything else?

The whole thing should work like mysqli::fetch_object() by setting the properties to their values BEFORE calling the classes __constrcut() method. Of course this also means that we need the possibility to pass properties to the __construct() method.

class Bar extends Foo {

  public function __constrcut($mandatoryParam) {}

}

$bar = {\Bar
  $property1 => "value",
  $property2 => "value",
}("mandatory param value");

This would (again) allow IDEs to auto-complete. The fact that the braces are left out if no parameters should be passed to the __constrcut() method is no problem, in fact it's even identical to the new keyword usage...

new Foo;

new Foo();

... are equivalent.

PS: I don't really know if this is the right place to post this kind of huge feature request, or if the developer mailing list would have been better. But there is that "Feature Request" option and well, what is it for if not for feature requests.

PPS: Can't wait to hear your feedback!

Test script:
---------------
// We want to create a <code>"text_format"</code> form element in Drupal 8.
//
// Usually that would look like this (with the new array syntax):

$form['body'] = [
  "#type"          => "text_format",
  "#title"         => t("Body"),
  "#default_value" => $body->value,
  "#format"        => $body->format,
  "#weight"        => 0,
];

// With the proposed syntax, the CMS could declare a class first:

namespace \Drupal\FormElement {

  abstract class AbstractFormElement {

    public $type;

    public $title;

    public $defaultValue;

    public $description;

    public $attributes = [];

    public $required = false;

    public $tree = false;

    public $parents = [];

    public $weight;

  }

  class Textarea extends AbstractFormElement {

    public $type = "textarea";

    public $cols = 60;

    public $resizeable = true;

    public $rows = 5;

    // Automatically instantiated when this class is instantiated!
    public $ajax = {\Drupal\Form\Event $event => "blur" };

  }

  class TextFormat extends AbstractFormElement {

    public $type = "text_format";

    public $format;

  }

}

// As you can see it's easy to define default values and easy for a developer
// to comprehend where which property is coming from, which default value it
// has, etc. etc.. Plus we could also provide documentation for each property
// directly within the class and the developer has proper documentation at his
// finger tips if using a real IDE.

// Let's continue and create the same form element as we did before, but now
// with the new syntax.

$form['body'] = {\Drupal\FormElement\TextFormat
  $title        => t("Body"),
  $defaultValue => $body->value,
  $format       => $body->format,
  $weight       => 0,
};

// See how we could even leave out the first offset, because it's already pre-
// filled in the class. Plus it's now a real instance of {@see \Drupal\FormElement\TextFormat}
// which means that type hints will work.


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2014-05-01 19:41 UTC] requinix@php.net
-Status: Open +Status: Duplicate
 [2014-05-01 19:41 UTC] requinix@php.net
Duplicate of
* Req #62044 for short object syntax
* Req #66900, Req #53266 for setting properties on construction

See also RFCs
* https://wiki.php.net/rfc/objectarrayliterals (inactive)
* https://wiki.php.net/rfc/automatic_property_initialization (declined)

PS: The internals list would probably be better, but before you go there be sure to spend time looking around at what has been discussed previously. Because I can assure you this topic has come up before. Recently, even.

A couple mail archives come to mind:
* http://php.markmail.org/search/?q=#query:%20list%3Anet.php.lists.internals
* http://marc.info/?l=php-internals
 [2014-05-01 19:56 UTC] fleshgrinder at gmx dot at
Many thanks for your answer. My searches weren't thorough enough, well to be honest I only searched for very few keywords via Google which returned everything but nothing from the PHP websites.

As there are already so many requests for this, it might simply be a matter of time for it to come to one of the next PHP versions.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Mar 28 15:01:29 2024 UTC