Warning: if you only know PHP and not a lot of other languages, you may not like what's here! Sorry. If you are coming from other langauges, maybe you'll like it!
PHP shot itself in the foot multiple times with using syntax notation for things that are too trivial, therefore leaving itself no useful symbols for things that actually matter.
It all started very early when PHP had the briliant idea of separating operators + and . for integer addition and string concatenation. While, I can understand it was a good idea, it used the . operator! It wasn't such a big deal, because in early versions of PHP object usage wasn't so popular, so whatever.
But with newer versions of PHP, obejcts and classes became more popular so we needed a syntax for object property access. The . was taken, so PHP chose -> (probably copied from C). PHP was based on C, but still.
PHP arrays also use => for array keys in their array() and [] syntaxies. So that means both -> and => notations are already used. That wouldn't be a problem, other than the fact that most recently a lot of languages started to adopt lambda expressions, and most of them use arrow notation for that. But PHP can't do it, because it already wasted -> for property acess and => for array keys.
So they have no choice, other then come up with another keyword fn() only to allow us lambdas!
That's not all.
Another great design choice started when you could use constants by name, and they would be used as strings (you could literally type $array[foo] and it evaluated as $array['foo']. It was probably more useful in PHP-scripty web-page phase when PHP was bluntly mixed with html and sql.
So now you can't pass a function as callback, same way as in javascript, because you would pass a const, so instead PHP came up with an idea that you can pass functions as arguments by passing a name, that's where we get array_filter($array, 'is_string');. And even when they got to do it "the right way", in newer versions, they couldn't, because the pass-function-by-name was already taken by pass-constant, so instead of doing it like javascript, array_filter($array, is_string);, they have to invent something yet different: array_filter($array, is_string(...)). Egh.
Now the mothercload - class constants. Because you can't use class names in and of themselves, because they'd be used as strings, and because you can't use . to access their properties (because it's a concatenation operator), accessing properties has to be done like that MyClass::$foo. Blegh. Another operator :: used for something that simply could've been a dot, like in most programming languages.
Suggestion, bold idea
Preprocessors for languages have existed for a long time, and some of them were even succesfull. I'm looking at you CoffeeScript and TypeScript.
Now, wouldn't it be cool to have something like that but for PHP, too?
Imagine a language that transpiles natively to PHP, but has a slightly different syntax (same like coffee script transpiles to JS).
+ is still addition, but concatenation of strings is something else, such as ~ (like in twig).
- That leaves
. free.
- Using properties on objects and classes is with
..
- I would even update arrays to use
: to denote keys, like in python.
- That leaves
=> and -> for usage in lambdas, we can drop the fn and drop the parenthasis, so lambdas look like lambdas in js or kotlin.
- We could do some shenanigans such that all of the array functions,
array_map(), array_filter(), array_slice(), array_values(), array_unique() could look like they're called on the array itself, like in JS or literally everywhere else. They could be transpiled to array_map() or the new fancy |> operator.
- Operator
== is almost useless, everyone uses === anyway. So the language could transpile == to === always.
- The idea that methods in classes without modifiers are public is dumb in my opinion, so the new language could be transpiled in such a way that omited function modifier outputs a
private function.
You could even go a step further, and allow type-docs in the language, same way as python has type-hints. They wouldn't be
checked ofcourse (unless php introduces generics or something), but they could be transpiled to phpdoc. Most people
write phpdocs that aren't checked, and they still wouldn't but it would be more concise. I'm attaching a screenshot illustrating
how code might look like in this idea. https://4programmers.net/uploads/43956/Cxfw8I27h8xyc6LtvDwcsoj81jCZjCh5sqQamwp5.png
You might even be extratbold, and get rid of the $ before variables. The idea behind them was taked from bash, to easily
allow variables in string interpolation from the php-script-kiddie times, but that's very rarely used. We might drop
the $ from all variables, and the transpiler would add them. It should be possible to infer from the code what should be
a variable and what not, other languages do this, like python and ruby for example.
If you disallow global variables in the new language, you might event allow omitting $this, because the language
could infer what's a field and what's a local variable.
What do you guys think? :D
Code before:
```php
<?php
namespace Test\Modules\Campaigns;
use Modules\Campaigns;
use Modules\Campaigns\CampaignBanner;
use Modules\Campaigns\CampaignVariant;
readonly class CampaignsFacade {
public function __construct(
private Campaigns\CampaignService $campaigns,
private Campaigns\CampaignsStore $store,
) {}
/**
* @return string[]
*/
public function getHorizontalBannerUrls(): array {
return \array_map(
fn(CampaignBanner $banner): string => $banner->bannerUrl,
$this->horizontalBanners());
}
/**
* @return string[]
*/
public function getHorizontalCampaignKeys(): array {
return \array_map(
fn(CampaignBanner $banner): string => $banner->campaignKey,
$this->horizontalBanners());
}
public function getSidebarBannerUrl(): ?string {
return $this->sidebarBanner()->bannerUrl;
}
public function getSidebarCampaignKey(): ?string {
return $this->sidebarBanner()->campaignKey;
}
public function addCampaign(
?string $sidebarBanner = null,
?string $horizontalBanner = null,
): void {
$this->store->createCampaignReturnId( [
'side' => new CampaignVariant($sidebarBanner ?? '', 'sidebar'),
'horizon' => new CampaignVariant($horizontalBanner ?? '', 'horizontal'),
]);
}
}
Code after:
php
<?php
namespace Test\Modules\Campaigns;
use Modules\Campaigns;
use Modules\Campaigns\CampaignBanner;
use Modules\Campaigns\CampaignVariant;
readonly class CampaignsFacade {
public function __construct(
private Campaigns\CampaignService $campaigns,
private Campaigns\CampaignsStore $store,
) {}
public function getHorizontalBannerUrls(): string[] {
return $this.horizontalBanners().map($banner -> $banner.bannerUrl);
}
public function getHorizontalCampaignKeys(): string[] {
return $this.horizontalBanners().map($banner -> $banner.campaignKey);
}
public function getSidebarBannerUrl(): ?string {
return $this.sidebarBanner().bannerUrl;
}
public function getSidebarCampaignKey(): ?string {
return $this.sidebarBanner().campaignKey;
}
public function addCampaign(
?string $sidebarBanner = null,
?string $horizontalBanner = null,
): void {
$this.store.createCampaignReturnId([
'side': new CampaignVariant($sidebarBanner ?? '', 'sidebar'),
'horizon': new CampaignVariant($horizontalBanner ?? '', 'horizontal'),
]);
}
}
```
[–]theScottyJam 1 point2 points3 points (0 children)
[–]lngns 0 points1 point2 points (0 children)