I disagree with you on this point. I worked with PHP for two years on some legacy systems, as well as some Laravel-based systems. While Laravel yields results that are worlds away from PHP build in the 90's, I still wasted dozens of hours because of poor constructs that the language is unfortunately coupled to. I documented each instance where I wasted a significant amount of time due to issues like scoping issues, closure problems, arrays-that-are-arrays-sometimes-but-maps-other-times, etc.
PHP has gotten better. But there are so many good choices that provide much better tooling, guarantees, etc. Examples: Ruby, Go, and Elixir. Heck, even Perl is more sane about its data types in some ways by enforcing consistent comparisons with `==` vs. `eq` and much more robust data structures.
I agree that every language has it's quirks. But I think PHP has so many that it seriously gets in the way often. I don't think it offers any significant velocity gains over using, say, Ruby.
a = []
a.foo = 'bar' // works!
b = {}
b[0] = 42 // also works!
I happen to think these designs are both INSANE, but even if you like them, PHP has no advantage here.[1] So how do arrays have numerical keys? Well... actually they don't. I was trying to make JS look better than it is in my original comment. Actually, array keys are stringified versions of numbers, and values are automatically cast to string when you put them in indexing braces.
Object.keys([1, 2])
--> ["0", "1"]
As you can imagine, this leads to gotchas when you assume that a JS object can have, say, a date as a key b = {}; b[new Date()] = 10;
Object.keys(b)
--> [
"Sat Nov 09 2019 23:15:58 GMT-0800 (Pacific Standard Time)"
]https://www.stefanjudis.com/today-i-learned/property-order-i...
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
Arrays are objects of class Array which have special literals, override the toString() method, and update the non-enumerable "length" property on certain operations.
Try calling Object.keys([1, 2, 3]), or even better try Object.getOwnPropertyNames([1, 2, 3])
In Zend/zend_types.h[1] of PHP source:
typedef struct _zend_array zend_array;
typedef struct _zend_array HashTable;
struct _zend_array {
...
};
That being said AFAICT, HashTable and zend_array are used interchangeably throughout the source. I am not a C programmer, but I did write a couple of PHP extensions and that was my general understanding. Perhaps it is a compatibility issue or just used to abstract types differently in various areas of the C API.Check out [2] for a deeper understanding of how arrays are handled internally in PHP.
[1]: https://github.com/php/php-src/blob/php-7.3.11/Zend/zend_typ...
[2]: https://nikic.github.io/2014/12/22/PHPs-new-hashtable-implem...
"An array in PHP is actually an ordered map."
god, the time i spent going paranoid debugging a stray "undefined array index 0" just to find out
array_filter(
is_uppercase,
['a', 'B', 'c', 'D']
)
returns [1 => 'B', 3 => 'D']
and not ['B', 'D']
like every other `filter(...)` i've used...EDIT to be fair, i see the rationale – having the index of the filtered element is useful sometimes, and requires some contortions with the usual impl of filter. it's quite neat, because you get both the index and the elements! but it's just... surprising as the default, and PHP's conflation of maps and lists obscures it – all the docs say is "array keys are preserved", which makes sense in retrospect, but doesn't really jump out for something with this much impact
Yet there are still many ugly sides to PHP, and Laravel illustrates most of them. There is so much magic that IDE can't follow: some classes have a `__call()` magic function that redirect methods calls to other instances. Some functions return values of varying types, with no common interface.
I've worked with several PHP frameworks, and Laravel is by far the worst. Its awful documentation plays a big role in this (no real reference doc, just a tutorial ; no links to classes or function in the doc ; the API doc is a joke ; the acclaimed "laracasts" are useless for serious work). The fact that this framework is dominant in the PHP community is worrying.
I don't think it's about preferring one approach or the other.
A good library/framework should have both instructional documentation and reference documentation. They have different use-cases and are not interchangeable.
And then the trouble starts. Remember what properties your models had? No? Well so doesn't your IDE. There is just too much magic going on to keep things maintainable.
If you like a framework like Laravel you should go with Symfony instead. But don't use annotations. Keeps things separated so you and your colleagues can find routing and database information at logical places instead of all over the place in classes.
Not ideal - since it’s not enforced in anyway (the same as local scope type doc declarations). But can be useful.
We use Symfony at work and we turned off the annotations package, use XML mapping for our models.
Of course, Symfony and Doctrine do have some frustation points.
I use Symfony for quite some time and at one point I stopped using Doctrine data mapper. The DBAL and the query builder are enough.
I work for a web development company and We have been successfully using Yii for years now, including for medium size projects (in terms of LOC and exposure).
Just my two cents
Laravel is lauded by many for its fantastic documentation. It's not comprehensive, but it's still pretty extensive, easy to read, and the gaps are only for niche situations.
As far as the API docs, what is your complaint about them?
javascript has too many hidden ways to shoot yourself in the foot, and just hasn't evolved for developer happiness the way php and ruby have.
[1] https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
Let me advice you to benchmark it "accuracy" on your machine setup, don't rely what is on that page.
Make sure the error with --jit-verbose=1 which will show whether it uses MJIT correctly.
ruby --jit-verbose=1
- N-Body single core
Ruby 2.6.3 6:22.00s
RubyJIT 2.6.3 3:58.18s
PHP 7.3.xx 4:10.90s
…
JIT success (511.7ms): initialize@nbody.rb:14 -> /tmp/_ruby_mjit_p5804u105.c
JIT success (397.5ms): block in offset_momentum@nbody.rb:68 -> /tmp/_ruby_mjit_p5804u106.c
JIT success (607.0ms): block in energy@nbody.rb:50 -> /tmp/_ruby_mjit_p5804u108.c
JIT compaction (53.6ms): Compacted 111 methods -> /tmp/_ruby_mjit_p5804u111.so
Successful MJIT finish
real 6m4.201s
user 6m42.813s
sys 0m4.041s
$ time /opt/src/php-7.3.11/bin/php -n nbody.php 50000000
-0.169075164
-0.169059907
real 5m24.915s
user 5m24.808s
sys 0m0.020ruby 2.7.0dev (2019-11-23T07:06:30Z master b563439274) [x86_64-darwin18]
gtime -v /usr/local/bin/ruby --jit -W0 nbody.rb 50000000 -0.169075164 -0.169059907
Command being timed: "/usr/local/bin/ruby --jit -W0 nbody.rb 50000000"
User time (seconds): 249.30 System time (seconds): 0.58 Percent of CPU this job got: 100% Elapsed (wall clock) time (h:mm:ss or m:ss): 4:08.97
---
PHP 7.3.11 (cli) (built: Oct 24 2019 11:29:52) ( NTS ) Copyright (c) 1997-2018 The PHP Group Zend Engine v3.3.11, Copyright (c) 1998-2018 Zend Technologies with Zend OPcache v7.3.11, Copyright (c) 1999-2018, by Zend Technologies
gtime -v php -n nbody.php 50000000
-0.169075164 -0.169059907
Command being timed: "php -n nbody.php 50000000" User time (seconds): 248.02 System time (seconds): 0.49 Percent of CPU this job got: 99% Elapsed (wall clock) time (h:mm:ss or m:ss): 4:09.82
but i'd pick php over js any day! (probably even over python/django, unless data mining is a core concern)
From the original post: [quote] Supporting union types in the language allows us to move more type information from phpdoc into function signatures, ... [/quote]
For example: I don't think anyone would seriously defend the idea that brainfuck is a reasonable language to write production code in.