
Php-o: metaprogramming PHP to give it a saner API - Joeri
https://github.com/jsebrech/php-o
======
Mahn
Interesting concept, the chainable object specially showcases well what PHP is
missing by neglecting data types as objects. Makes you wonder whether it could
be simplified further though; ie, combining s(), a(), o() and c() into a
single one letter function that does it all, jQuery style. I think it'd have a
better chance of adoption that way.

~~~
plorkyeran
You wouldn't be able to do the JSON stuff and the string wrapping with a
single function, but otherwise that could be a good idea.

~~~
Mahn
Why not? You could test if the string is valid json, and if it is do object
wrapping, otherwise do string wrapping. This method is used often in jQuery,
figuring out what to do depending on what you pass to it. EDIT: and I guess a
second, optional argument to force a specific data type could be added for
those rare cases where you have a json string and you want to run string
functions on it.

------
chez17
As a PHP programmer the inconsistency of the string functions is not only
bothersome, it's embarrassing. This seems like an interesting fix for that.

~~~
raylu
This doesn't fix that, it just makes it worse.

 _This is an experiment in meta-programming PHP to give it a saner API._

Sweet.

 _s() turns all the standard string functions into methods with identical
behavior:

s($haystack)->pos($needle)_

OK. Cool. Sounds good.

 _- >preg_replace(), ->in_array()_

Yep. Awesome.

 _The s() function also implements JavaScript's string API:

->charAt(), ->indexOf(), ->lastIndexOf()_

...

......

.........

~~~
Joeri
The javascript API is there because it's the only one I can keep remembering,
I always forget the exact PHP functions and have to keep the php docs open.
There also didn't seem to be any naming collisions, so it is harmless. Having
developed some test and demo code on top of it, I've come to realize it feels
too alien inside of PHP to actually use, so that part is probably going away.

~~~
raylu
JavaScript uses camelCase; the C functions use_underscores. Mixing and
matching the two has been a complaint about the entire PHP library for a long
time.

------
dools
The biggest draw card here is the multibyte string handling by default and
sanitization of argument ordering in string and array functions.

The object stuff, kind of started to lose me. The chainables is cool but for
me I could have stopped reading at s() and a() and been happy.

I think it'll definitely be worth experimenting with even if just for those
two things, thanks for sharing!

------
hearth
Aside from anything else, the function call and object instantiation overhead
of this library is insane.

The string comparison function provided as an example is _4 times slower_ than
the code it's based upon, and 3 times slower than a completely equivalent
multibyte-aware version.

~~~
Mahn
Libraries like this are bound to introduce overhead, but in the javascript
world you don't hear many people complain about the overhead of jQuery, and it
is there. I think for most people a string comparison 4 times slower won't
mean much. That's not to say it's "okay" to be slow, just saying it may not be
big for those not pushing PHP to its boundaries. In fact last time I checked
Symfony and Zend had a tremendous impact in terms of overhead, but you
(almost) never hear negative comments on them. Heck, even something OOP is
slower than the same thing written in procedural style in PHP.

~~~
hearth
The example I'm talking about is the first non-trivial example in the readme -
34 lines of believable code, not an individual function of the library.

The library is used about once every 3.5 lines, which feels less dense than
most jQuery code I see, but that whole function runs 3 times slower than the
plain MB-aware equivalent.

Some of the library functions might be implemented inefficiently but from a
quick glance they're nearly all very thin wrappers.

Overhead from libraries like Symfony and ZF is quite acceptable since they
offer much higher level features which you'd have to code yourself otherwise.

However making all your code (excluding I/O) run up to 3 times slower, just to
add some syntactic sugar, is insane.

~~~
quadhome
What causes the overhead? Is there a way to get the sugar without the
calories?

~~~
hearth
A trivial example:

    
    
      $len = mb_strlen("wtf");
        # call function mb_strlen
    
      $len = s("wtf")->len();
        # call function s
          # allocate string object
          # instantiate string object
          # call string ctor
            # set property
        # call method len
            # get property
          # call function mb_strlen
        # destroy object
    

There's no way to use a syntax like this without either massive overhead, or
massive changes in the engine.

There is a somewhat similar experimental project -
<https://github.com/nikic/scalar_objects> \- but that's not meant for real
world use either.

Personally I think the language, despite its flaws, does its job fine. I don't
think it needs turning into Javascript-with-sigils.

------
skrebbel
I like the three one-letter functions and their effects. It's not entirely
unlike how jQuery spices up DOM elements, and feels natural that way.

Then, suddenly, however, there came a validation engine with annotations and
reflection and whatnot. Huh? Isn't that a whole different thing? Why is this
bundled with my nice little jQuery-for-PHP-scalars? It's not just that it
feels like it's a different problem entirely and thus should be separate, the
code _feels_ different. Like it has a different philosophy behind it.

It looks pretty nice, but why can't I use the validation engine without PHP-o?
Or the other way around?

~~~
Joeri
Author here. It's called an experiment for something. I'm going to productize
it by separating it in the way that you propose. The validator API was ripped
straight out of java, i'll see about normalizing its style.

------
daniloassis
I think this type of approach will never stick with PHP community (at least
with the "serious" developers).

This hurts so many principles and directions that PHP community is FINALLY
diving into, like SOLID and stuff. Accepting simple things like strings are
not objects is the way to improve how PHP devs build their stuff and start
focusing on important things like defining de-facto libraries and joining
forces to make them the best and most flexible available.

Don't get me wrong, the idea is pretty good (even if it's a simple try to mask
procedural PHP functions)... but it seems like a swiss knife in the end.

~~~
notJim
I don't think this is a project that I would see being used anywhere, but I do
think it introduces an interesting idea for the language's evolution. I am
glad to see it here.

------
kijin
Looks neat. Although I doubt that "hacks" like this will become popular among
PHP users any time soon, a proliferation of similar hacks might give the PHP
core devs some ideas about how to clean up the language in the next few major
versions. PHP could introduce a native object-oriented way to interact with
built-in types in PHP 6, just like they did with SPL in PHP 5. Then, in PHP 7,
they would deprecate the old functions, and in PHP 8, finally remove them in
favor of the new style. After all, new major versions are for backwards-
incompatible changes, right? The whole cycle might take a decade, but it would
be worth it.

Anyway, here are some suggestions.

1\. "echo 'error message' and exit" isn't a particularly elegant solution, and
in fact symbolizes everything that is wrong with PHP. What about throwing an
exception instead?

2\. The ability to specify the charset at object creation and convert to
another charset later would be quite helpful, because nobody can remember all
those mbstring functions. s('str', 'EUC-KR')->convert('UTF-8') maybe?

3\. Why is O.php checking whether magic quotes are enabled? Since you're not
even touching GET/POST variables, magic quotes have nothing to do with your
library. Are you going to throw an error every time you discover suboptimal
settings in the user's PHP environment?

4\. Don't modify session settings until the user calls session_start(). They
might not want to use your session handling functions, only your string and
array functions. Simply including the script should have as few side effects
as possible. This helps integration with existing apps.

5\. Some of the methods that I'd really love to see in the string class are
startsWith(), endsWith(), and contains(), copied straight from .NET. It sucks
that I have to do strpos() === FALSE every time I want to check whether a
string contains another string, or !strncmp($a, $b, strlen($a)) every time I
want to check whether a string starts with another string.

6\. While we're trying to clean up PHP's API, why not merge the case-sensitive
and case-insensitive versions of string functions into a single method with an
optional flag? This is another area where the API is terribly inconsistent,
what with 'i's thrown in at random places and sometimes even 'case' to denote
the _case-insensitive_ version.

EDIT: Related to 5 and 6, I wrote a similar library back in 2010 for fun,
which I put online just now [1]. It doesn't use the clever iterator interface
that you incorporated into your library, but I do think that my method names
make more sense.

[1] <https://gist.github.com/kijin/4736544>

~~~
apendleton
This is probably overly cynical of me, but I feel like a lot of what's keeping
PHP alive at this point is inertia, and if some major version ahead required
that literally every standard library call be differently expressed (and by
consequence, every PHP app essentially be rewritten), the case for continuing
to use the language would get weaker than I think it already is. At that
point, why not jump ship for something more powerful/performant/whatever?

~~~
kijin
Large code bases are rarely rewritten from scratch. They evolve over many
years, and over time, old code gets replaced with new code, piece by piece. If
a language evolves over a similarly long time span (10 years or more), and new
features are adopted gradually, I don't see why a backward-incompatible change
would require anything more than the usual amount of change when the last of
the old code is retired. Call it inertia if you want, but this looks to me to
be a good thing if you have a large code base to maintain.

------
neeleshs
Having to go through the pain of the almost arcane APIs everyday, I appreciate
this project and the author. Looks neat.

------
oh_no_my_eyes
the sanest thing ive seen about php in a long time.

~~~
gambler
Maybe, but if several people develop several APIs like this, it will mostly
make everyone's lives more difficult. This should be a part of the standard
distribution.

------
leeoniya
i have something similar on the back-burner that i haven't pushed public yet,
but only a single, one-letter function like jquery that takes any type. there
are soooooo many functions to abstract. even though most are one-liners, i ran
out of steam :)

certainly not something to use all the time, especially in perf-oriented code,
but it's nice sugar.

------
leepowers
Cool, love it - the multi-byte support and baked-in validation is awesome,
going to play around with this.

------
Pitarou
This library looks like it will make my life a lot easier. Many thanks, Joeri!

------
rikthevik
*facepalm

~~~
ergo14
It kind of resembles of what a wildly popular javascript lib does isn't it?

------
lkrubner
How good is PHP? I was thinking about peer review the other day, and how one
measures peer review. One of the most important metrics is the number of
citations an article acquires. If an article is published and, over the next
20 years, is only cited 3 times, we can say that it failed to influence its
field, but if an article accumulates 1,000 citations, we can say that it
definitely had some impact.

Then I thought about PHP, and how it compared with other languages. I went to
Google and started searching:

influenced by gosling java

influenced by hickey clojure

influenced by matz ruby

influenced by Stroustrup C++

influenced by larry wall perl

and then finally:

influenced by lerdorf php

You look through some of those links and you notice a difference. A lot of
people write about the brilliant things that have been said by Gosling and
Hickey and Matz and Larry Wall and Stroustrup but no one ever cites Ramus
Lerdorf as an inspiration, nor does anyone seem to think he has ever said
anything especially brilliant or insightful. I'm sure if you dig you might
find exceptions, but as a rough metric of who has influenced who, I think this
reveals something important about how computer programmers perceive the
quality of PHP and one of its core contributors.

(You could counter-argue that PHP has several core contributors, in which
case, I would counter-counter-argue by asking that you please suggest a core
contributor to PHP who is quoted with the same admiration expressed for the
other architects that I've listed here.)

~~~
jtreminio
Symfony2 gets quite a bit of love here on HN... as much love as anything PHP-
related can get.

Its creator, Fabien Potencier, is usually cited as someone bringing sanity and
quality to the PHP world.

