Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:113974 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 29639 invoked from network); 6 Apr 2021 01:09:46 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 6 Apr 2021 01:09:46 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 15620180533 for ; Mon, 5 Apr 2021 18:08:40 -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=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,HTML_MESSAGE, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=3.4.2 X-Spam-Virus: No X-Envelope-From: Received: from mail-io1-f45.google.com (mail-io1-f45.google.com [209.85.166.45]) (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, 5 Apr 2021 18:08:39 -0700 (PDT) Received: by mail-io1-f45.google.com with SMTP id n198so11595175iod.0 for ; Mon, 05 Apr 2021 18:08:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=ZouMMydCIQddSYF37fjeLHYm8k/BfB4uwQeQrBcty0U=; b=rCfxR67H9dFxCQX1AeyIsaEnKPjIOdybLJPmaD+gRcWhqdioo/pIRyXp8lG7SbNkbO z5ctsFJTOJMR6ROZaHjBnSCwEAqiH11ZRzP22flm7/1zrkVmteSpS1qLGxmevrE2gu4R 1YWS7bPAK0yFmd4dfbq0aSZGiyunZdatiAwo/TOzw2rn07HqnraWAQodXMir3Bw8MNRJ asqYl1/cIxV9M/C8UXJhlLbcdehoV/lv/hTR2/ycf1HtmwIDtAUa7kOa0FLcukzf8eRn WitbcNjAq2fOF1Xa11C0saxPkOUvQkOkrqeFYpVPB/GX/hVJGr/Uf++grBwLpfKoN2mW qoVQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=ZouMMydCIQddSYF37fjeLHYm8k/BfB4uwQeQrBcty0U=; b=n2AKjaQ4R+oMzUc8gDzvVFdCkpGDrH32JeQspDVzy2Cb6OFkyMnwjpOJLTeSSJkovL zF5pn1whdqudcavRty8TEVE7PXmswitQbwTH6jTRB5UEHWx/HsU6FSmGWay4goa58X11 4M00EjSvYVMNbt7dh9GR+AmO6ZEDMFwxaUwcfIvHAFRKUKS0OPbKyl0Hggcf7czK/Au4 RHVJ9Cy/3Y56Cut759tf67vZfETISNwIVW2FF2rCYm2r0R9pUmt05S6UWL3724/Zr+3+ bq7OMKtFOYJlSXu1Qw5kKqifzRAh8TGbTIoxADXsCNzOzsprOFwLng6rK0EMrzcsTHIi bR1A== X-Gm-Message-State: AOAM5310Mcm/vh4/SSXr8/6P6rrp7+80jwZe2RMVRMh9tUog4Cgv/0gb D83LWSqKI/b0G5qqrf9YzYrC18n/nMZFOB8WFR8= X-Google-Smtp-Source: ABdhPJw7nqg2yKJPfNEWe3FBrv4cwSY0UtM0i15GZyqLOF+NcLzUYbMyBBHWuq6f5uHoxz6jJe8DRiZRfoglsutgfAI= X-Received: by 2002:a5e:dd09:: with SMTP id t9mr21117784iop.111.1617671318728; Mon, 05 Apr 2021 18:08:38 -0700 (PDT) MIME-Version: 1.0 References: <0c5e70d7-5b11-5251-4ec9-608db63105c9@gmail.com> In-Reply-To: Date: Tue, 6 Apr 2021 03:08:26 +0200 Message-ID: To: Jesse Rushlow Cc: PHP Internals List Content-Type: multipart/alternative; boundary="00000000000050f3fd05bf43746d" Subject: Re: [PHP-DEV] Path forward for class_exists with different targeted PHP version implementations From: ocramius@gmail.com (Marco Pivetta) --00000000000050f3fd05bf43746d Content-Type: text/plain; charset="UTF-8" Hey Jesse, On Tue, Apr 6, 2021, 03:00 Jesse Rushlow wrote: > Sure thing - > > In Symfony's MakeBundle we have a command "php bin/console make:command". > This ultimately generates a "App\Console\XyzUserlandCommand::class" that > allows the developer to customize in order to perform some task within > their app. e.g. run persistence operations, generate a backup, etc.. > > What we do internally to generate that userland class is determine which > features to include by checking the PHP version, dependencies available, > etc.. As an example, when the user runs "make:command"; we check if they > have PHP 8 && if "class_exists(Symfony\.....\Attributes::class)" - if both > of those === true, we import the attribute class and generate the needed > attributes for the command. Otherwise we would fall back to using > annotations if the user is running PHP 7. Where I ran into trouble was the > Attributes::class (defines the attributes to be used in userland) utilized > constructor property promotion (which is a pretty sweet addition to 8 imo). > > Up to this point if it's possible, we generally pick a > class/interface/method that introduces new functionality (Symfony > feature/bugfix) and call one of the \*_exists(class/method/interface) > functions in a conditional to determine if we can indeed use that feature. > But because in this particular case the Attributes::class also uses > constructor property promotion, when calling > class_exists(Attributes::class) in PHP 7 we get: > > > ParseError: syntax error, unexpected 'public' (T_PUBLIC), expecting > variable (T_VARIABLE) > > The work around was to "$canUseAttributes = 80000 <= \PHP_VERSION_ID && \ > class_exists(AsCommand::class)" > > All is fine and well, but this in my opinion, this feels like bad mojo from > a developers standpoint. I must now need to be aware of the exact > implementation details of the object I'm checking before I can even check > if it exists or not. I would expect any of the \*_exists() to tell me if > the class/method/interface exists regardless of the implementation. My > first thought would be if the implementation is not compatible with the PHP > version some sort of \RuntimeException::class would be thrown by PHP. But > that is where my knowledge of PHP internals is disconnected from developing > software in PHP. > > I created a simple reproducer repo > https://github.com/rushlow-development/attribute-test (forgive the repo > name, it really has nothing to do with attributes.) and for an even simpler > example https://3v4l.org/4cMW4 > > I apologize in advance for the wall of text - but I'm curious if there is a > way to either improve our native functions, improve the docs, and/or create > new functions for use cases like this. > `*_exists()` functions triggering autoloading is intentional and required. Perhaps you are trying to reflect in unsafe symbols, which explicitly need to skip autoloading, as you are not yet sure about what you will encounter. This is exactly what https://github.com/Roave/BetterReflection was built for: perhaps you can help in getting up to speed with 8.x featured, and then it can be used in the bundle internals (rather than relying on runtime side-effects)? > --00000000000050f3fd05bf43746d--