Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:116181 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 78825 invoked from network); 27 Sep 2021 15:15:19 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 27 Sep 2021 15:15:19 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id C42381804E3 for ; Mon, 27 Sep 2021 08:57:48 -0700 (PDT) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=BAYES_40,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL, SPF_HELO_NONE,SPF_NONE autolearn=no autolearn_force=no version=3.4.2 X-Spam-ASN: AS15169 209.85.128.0/17 X-Spam-Virus: No X-Envelope-From: Received: from mail-pj1-f44.google.com (mail-pj1-f44.google.com [209.85.216.44]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-256) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Mon, 27 Sep 2021 08:57:48 -0700 (PDT) Received: by mail-pj1-f44.google.com with SMTP id d4-20020a17090ad98400b0019ece228690so4049322pjv.5 for ; Mon, 27 Sep 2021 08:57:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=dqxtech-net.20210112.gappssmtp.com; s=20210112; h=mime-version:from:date:message-id:subject:to; bh=QNP8tlVbn4m9Go2v70aLwCQDBhfLu16FYGn8wqb/Dvs=; b=iqn6XympQySY2uC1z7UdpZQNCCqnN/g1GCFBE+RS4s9KgIm6MvxGXhW9fW7aZ/rmDj PohS3DaBnOBTlzenD90UhkIaF+3UMZ5ePU6T8eCXkE0swJjO8KDIjMbq1Q/N/ddbHJGT gUlneH2f4DO3D5gN5rX7dCOYY4+HHGmzPqIbnkXUH8qLq6/JvGr2SDLJBAMsnTfUpOwG EWqt3rVv5Ipk/1Snb+gPpNvCqfiGO2dB6OLptD6gF2jqIdfkOT416GjpdpPfXksufETd yAKiDkzjP0hNlfP4jHdqPBN1hztoNfBlykltkovCfYN+dZYgm3RXaXubgFpXPR6dsdgF wB/w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=QNP8tlVbn4m9Go2v70aLwCQDBhfLu16FYGn8wqb/Dvs=; b=Nibd1NirhIQL3sRIKHPo06Z9K1Ed8h8GnA2U0AoZIXFMuhJRTV2Pom0W+1wkgVjyG7 MqNJYU5dWLBBBOecISxCZy9Hm+N7wvOhK2v/JyPhr0n8ha/SMGutPF1XKEsczmX3rc7A OoORd4wVZUkOz5UNbZJNatS9Fd6K3JSuxr+ubz2yK++qmJJkO/kkqmfwV+JIaLbITPMw Mgnf49zoTt+M+hV0UfZRwdBU5RZcqrHsZnKeUvL/nKrcBeqirS4JqOZ6h3cJEhIUDAXL o2V0CUeaLrFYJ/KIZNcM1fQExJQY1z1c21undVhlQgKvedxcZ2Lk0T+6tLA5BRla8HcG Hk3Q== X-Gm-Message-State: AOAM533YfsaXrU2xbGcEQsOW3ej3X4rw8bWri2zQQeY647fivOhb06hU P/QJge60enUF9uwMPNL20astXUTVkVKCka0AYuRClu7GfIt16A== X-Google-Smtp-Source: ABdhPJzXfdHTSZ4KuOHcEYj+5f4XYB5PmALc+b4pEQUBqEtgo1wRpGgxz8GQijs0RrlIdJN/XJrrh1G76fV14DyoQX8= X-Received: by 2002:a17:90a:8d82:: with SMTP id d2mr723356pjo.31.1632758264628; Mon, 27 Sep 2021 08:57:44 -0700 (PDT) MIME-Version: 1.0 Date: Mon, 27 Sep 2021 17:57:33 +0200 Message-ID: To: PHP internals Content-Type: text/plain; charset="UTF-8" Subject: Static (factory) methods in attributes and initializers From: andreas@dqxtech.net (Andreas Hennings) Hello list, currently, the default mode for attributes is to create a new class. For general initializers, with https://wiki.php.net/rfc/new_in_initializers we get the option to call 'new C()' for parameter default values, attribute arguments, etc. Personally I find class construction to be limiting, I often like to be able to use static factories instead. This allows: - Alternative "constructors" for the same class. - A single constructor can conditionally instantiate different classes. - Swap out the class being returned, without changing the factory name and signature. In fact, static factories for initializers were already mentioned in "Future Scope" in https://wiki.php.net/rfc/new_in_initializers. However this does not mention static factories for the main attribute object. For general initializers this is quite straightforward. For attributes, we could do this? // Implicitly call new C(): #[C()] # Call the static factory instead: #[C::create()] So the only difference here would be that in the "traditional" case we omit the "new " part. We probably want to guarantee that attributes are always objects. We can only evaluate this when somebody calls ->newInstance(), because before that we don't want to autoload the class with the factory. So we could throw an exception if the return value is something other than an object. I was also considering to require an explicit return type hint on the factory method, but again this can only be evaluated when somebody calls ->newInstance(), so the benefit of that would be limited. The #[Attribute] annotation would allow methods as target. Reflection: ::getArguments() -> same as before. ::getName() -> returns "$class_qcn::$method_name". ::getTarget() -> same as before. ::isRepeated() -> This is poorly documented on php.net, but it seems to just look for other attributes with the same ->getName(). So it could do the same here. ::newInstance() -> calls the method. Throws an error if return value is non-object. we could add more methods like ReflectionAttribute::isClass() or ReflectionAttribute::isMethod(), or a more generic ::getType(), but these are not absolutely required. We could also allow regular functions, but this would cause ambiguity if a class and a function have the same name. Also, functions cannot be autoloaded, so the benefit would be small. I'd rather stick to just methods. ----- Side note: I think "attributes" is a really poor name for findability. But this ship has sailed. ----- Cheers Andreas