nette / php-generator

🐘 Generates neat PHP code for you. Supports new PHP 8.3 features.
https://doc.nette.org/php-generator
Other
2.11k stars 138 forks source link

Define PHP version manually #39

Closed Nazariy closed 5 years ago

Nazariy commented 6 years ago

It would be nice to have option to define PHP version support manually as production environment might be different from development and certain syntax might not be supported.

dg commented 5 years ago

Can you describe it on a concrete example?

Nazariy commented 5 years ago

I'm planning to integrate this library with Framework dev tools. So far library does excellent job and covers most of scenarios, but I need to find a way to manually force library to output PHP 5.6 or 7.0 compatible code without downgrading my dev environment.

From what I can see your library is using PHP_VERSION_ID to decide if certain functionality is allowed, it would be nice if this variable could be overridden during method initialisation.

For example:

$class = new Nette\PhpGenerator\ClassType('Demo', '5.6');

or

Nette\PhpGenerator::setVersion('5.6')
dg commented 5 years ago

The output should always be compatible with PHP 5.6 if you do not use the constructions like this:

$class->addConstant('ID', 123)
    ->setVisibility('private'); // constant visiblity

$method = $class->addMethod('getValue')
    ->setReturnType('int') // method return type
    ->setReturnNullable() // nullable return type
    ->setBody('return count($this->items);');

So it is up to you.

nevmerzhitsky commented 1 year ago

In my case, I use the library to generate Eloquent's (Laravel) models. Our company has many Laravel projects which depend on different PHP versions. I want to have the same code of the generator but a different output PHP code which compatible with a particular PHP version.

For example, PHP 7.2-7.4 had different levels of support for Covariance and Contravariance and in one case of classes inheritance the output code may use explicit type declaration of a method arguments:

class Foo {
  public method test(array $arg): array;
}

class Bar extends Foo {
  public method test(ArrayAccess $arg): array;
}

but in 7.2 it's impossible and only PHPDoc could be used to specify a real type of argument (in PHP 7.4 the PHPDoc is redundant):

class Foo {
  public method test(array $arg): array;
}

class Bar extends Foo {
  /**
   * @param ArrayAccess $arg
   */
  public method test(array $arg): array;
}

(it's just a raw abstract example)

Examples of this kind of incompatibilities are a lot and the list is unfinished by nature, they will be introduced by new versions of PHP from time to time.

Well, I mean it will be great if php-generator will provide a more declarative way of describing of desired output code, and get rid of many if (PHP_VERSION_ID<>===!=XXX) {} elseif () {} else {} in my printer code.

dg commented 1 year ago

I understand, but when it comes to these things specifically, I don't have plans to implement the new features for version 7, because 7 is outdated today.

nevmerzhitsky commented 1 year ago

I know your position but my comment was not about PHP 7.X but the nature of PHP evolution. For another example, PHP 8.1 added types intersection, but prior PHP 8.1 this feature exist many years ago via PHPDocs (in smart IDEs). So the library could dump different code for PHP 8.0 and 8.1 (if a developer wants php8.0-compatible code):

It's much better to implement this inside the library (on the layer of predefined printers or as a new abstract layer before the printers) instead of checking the actual version in a custom printer of the developer.

dg commented 1 year ago

That might come in handy. Will you try to develop it? Probably the best way would be to create a new class, a transformer, that gets a ClassType and returns a new modified class.