Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:113973 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 27939 invoked from network); 6 Apr 2021 01:01:53 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 6 Apr 2021 01:01:53 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id D208B18053A for ; Mon, 5 Apr 2021 18:00:45 -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,HTML_MESSAGE,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=3.4.2 X-Spam-Virus: No X-Envelope-From: Received: from mail-ot1-f48.google.com (mail-ot1-f48.google.com [209.85.210.48]) (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:00:44 -0700 (PDT) Received: by mail-ot1-f48.google.com with SMTP id c24-20020a9d6c980000b02902662e210895so12584474otr.9 for ; Mon, 05 Apr 2021 18:00:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=rushlow.dev; s=google; h=mime-version:references:in-reply-to:from:date:message-id:subject:to; bh=L6gEtya8Ob1T90blPlFsJyrW8egiVfZubyHCz9Wk3hY=; b=fsXm0mgiaNQjMqSXmlWmK6JrT6JyeoJChT1L/XhynqWW3YcZy3eeGpHvmTCXi/tlPT +HRu4qIAD92oASRBvgN6yArc7r240xGBuRsFDB5YeaUXdIZ4CngASuOkfTcTTXRd5te1 1imu3Z7IMR7E6zqYxE9XMwtYSovMY8jXS9tj50ki2S31jtbEeTppRR9/1TpAfzEcl084 usxky9Wxx1i8RQpglWFcTGEGP5XFZAme9vEhfNhJhBPwAll4qBNoayZy0UUK4oEimcFg 9Qydu/pDIBIjKRP7NO6Sf6S8s3LXGAzi00wJmD1hS+C/WRNZldHZXmnPvfSmR17owA9L Kgjg== 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; bh=L6gEtya8Ob1T90blPlFsJyrW8egiVfZubyHCz9Wk3hY=; b=fhMXyXJEtyItjZmMfm2euDwm4suk16Kj6aZTiYMTHVilpZdw1PfXNb1Bv8i/hNuRHI d47blAT8MKgmxyKrWnDcD/8yuEd/dmFCdBswq44uhpiX4lgn//VpghIRYIwEtarsZm5S BHauPizYUvL0M62RSGFmRIhcA4hU9MbtstwIyUotckk6SIar9FZ6HgU/24a0goKGtIrI N0o+gRdQUHpg++nJsvsiAWe+RVlbuxoIuUKPwPKr12Y/KAXyM4eMwG+ZRlxlO8i3y8sZ grzNYrHDCYR2KXWjq212Bv1+qV1g0Se/Plp2j7DYHnipvokPdlgWr8yXT2juSuuSHZ6M 6KkQ== X-Gm-Message-State: AOAM530kaUZoJiucKu2cwE5e/xzL7SdvJF6u1WCrnyhoUgshAXWh81r8 4JthKA73ahKLeGx2Wh1HDs3u0bAWpUK8XanFuvcAsLXqD0bwJQzI X-Google-Smtp-Source: ABdhPJxAvI4pLXZDIEz7VTpL8SOoPrqZZL15GCTkSI7c9b6n90Fb8RFdyK1LUVwnEtPL5crhn23o9YBVava8pdJvAI0= X-Received: by 2002:a9d:5614:: with SMTP id e20mr24051964oti.304.1617670843161; Mon, 05 Apr 2021 18:00:43 -0700 (PDT) MIME-Version: 1.0 References: <0c5e70d7-5b11-5251-4ec9-608db63105c9@gmail.com> In-Reply-To: <0c5e70d7-5b11-5251-4ec9-608db63105c9@gmail.com> Date: Mon, 5 Apr 2021 21:00:31 -0400 Message-ID: To: PHP Internals List Content-Type: multipart/alternative; boundary="000000000000f8753005bf43572a" Subject: Re: [PHP-DEV] Path forward for class_exists with different targeted PHP version implementations From: jr@rushlow.dev (Jesse Rushlow) --000000000000f8753005bf43572a Content-Type: text/plain; charset="UTF-8" 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. Thanks! Jesse Rushlow On Mon, Apr 5, 2021 at 3:30 PM Rowan Tommins wrote: > On 05/04/2021 18:14, Jesse Rushlow wrote: > > I was attempting to use class_exists(UsesPropertyPromotion::class) to > > determine if an attribute implementation existed in order to generate a > PHP > > 8 appropriate class - else fall back to generating a PHP 7 appropriate > > class. For context, this check was being written for Symfony's > MakerBundle > > which generates classes for Symfony projects. > > > Hi Jesse, > > Can you explain the use case in a bit more detail, perhaps giving some > example code you were hoping to write with class_exists()? > > I suspect there are other ways to achieve what you were trying to do, > but don't want to confuse things if I've misunderstood the requirements. > > Regards, > > -- > Rowan Tommins > [IMSoP] > > --000000000000f8753005bf43572a--