Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Why should that be an error? First we are explicitly forcing a string to an integer and then comparing it with type sensitivity to another integer.


We could debate that for a long time, but my point was different: There's no sane function in today's PHP that parses ints and handles errors (defaulting to 0 doesn't count).


    /**
     * Cast to int, fail if not a valid integer
     * @throws \UnexpectedValueException
     * @param mixed $thing
     * @return int
     */
    function as_int($thing): int                                                                                             
    {                                                                                                                        
        if (!filter_var($thing, \FILTER_VALIDATE_INT))                                                                       
            throw new \UnexpectedValueException("Value is not an integer.");                                                 
        return (int)$thing;                                                                                                  
    }
While, yeah, it'd be nice if there were something like this built in... it's a couple lines of code. If that's your major complaint, I'd be happy to whip up a whole suite of proper functions to cast to primitives while throwing errors on invalid values since it's just swapping FILTER_VALIDATE_INT for the various types.


I think this illustrates my problem with PHP well: There are ways to do common tasks properly, but they're often hidden, obscure or basically require creating your own "stdlib extension", as seen here (I only heard about filter_var from this discussion, and I specifically searched for string conversion functions).

Your function proves my point: It looks correct, but actually breaks for as_int("0"), since filter_var with FILTER_VALIDATE_INT doesn't acutally validate the int, but parse it, and zero is falsy.


Above usage of filter_var is wrong, there is no need to cast $thing to int, filter_var already returns the filtered int or false on failure. The correct usage is therefore

    /**
     * Cast to int, fail if not a valid integer
     * @throws \UnexpectedValueException
     * @param mixed $thing
     * @return int
     */
    function as_int($thing): int                                                                                             
    {   
       $int = filter_var($thing, \FILTER_VALIDATE_INT);
       if ($int === false) {
         throw new \UnexpectedValueException("Value is not an integer.");
       }
       return $int;
    }
Thus the critique against PHP that is lacks a proper integer parsing function is simply not true, filter_var has been part of PHP since 5.2 released in 2006, over 16 years ago. filter_var works as advertised, because I use it almost every time i write PHP and that is to mostly to parse integers but sometimes also for other types. And I don't even wrap it with my own as_int function, using it inline with an simple if-check afterwards is actually cleaner. And if you prefer that filter_var returns null on failure instead of false you can simply add FILTER_NULL_ON_FAILURE as the third argument to filter_var.

And this is the recurring thing with PHP critique, vast majority of the time it just in imagination because nobody bothers to look it up.

https://www.php.net/manual/en/function.filter-var.php


> And this is the recurring thing with PHP critique, vast majority of the time it just in imagination because nobody bothers to look it up.

I see this from the other side: Good languages guide programmers toward good solutions. Criticism of the simplest or obvious solution is valid, because the language determines what that solution is.

Conversely, arguing that it's possible to write good code is largely meaningless. It doesn't mean that the language is good, just that it isn't completely unfit for purpose. Just look at the number of people who commented about other int parsing methods: Are they bad programmers, because they didn't know to look for filter_var when parsing ints, or is PHP a bad language because something so simple is hard to find a solution for?


Why so many failed to answer this questions is probably due to multiple reasons, here are a few

1) Some programmers are just either too lazy or too arrogant to read the manual, thus bad programmers. As a senior programmer that has helped numerous juniors in their work, this is probably one of the most common mistakes I see, they write code without checking how the API works, or they ask me why something isn't working when it can be easily found in the manual. This is not specific to PHP and I have seen this in everything from PHP to C++.

2) PHP is dynamic language, similar to JavaScript, types were not something you historically bothered with, thus parsing to int is not something the community has a large shared knowledge about, similar how it is rare in JavaScript. However with the introduction of primitive type hinting it has become more common to do proper parsing, hopefully PHP programmers will learn eventually. Thus it is a thing with dynamic languages, not specific to PHP.

3) Why can't programmers find the filter_var method in the manual and/or in the standard library? This I considered as valid criticism of PHP, the standard library is not structured because of the C like flat structure and many of the stdlib functions are weirdly named, like filter_var, what is filter to begin with?

The solution is to build a better stdlib, not throw out the language. I think the community can build a well designed stdlib if PHP implements operator overloading. The performance issues is no longer valid, PHP 7+ has great performance, thus worrying about losing important cycles is not really true anymore.

PHP as a language works well to build good solutions, I have done so in many projects. The critique here evolves around the stdlib, that is not something new.


The stdlib is part of the language, and while theoretically someone could take PHP and pair it with a new standard library, they could also take the PHP VM and pair it with a new syntax and parser with not much more effort. Just as its standard library is one of Python's biggest strengths and almost lacking one is one of JavaScript's biggest faults. Even if a community project is created to replace PHP's stdlib and offer a better alternative, unless everyone adopts it, it will always be just a niche alternative.

PHP needs to actually have a good standard library in its default distribution. Maybe looking to large frameworks like Symfony to develop one isn't a bad idea, but they've largely left the stdlib alone, so just waiting for them to start developing a complete replacement isn't going to work.

(For all its faults, JS' parseInt function is perfectly serviceable, but that's beside the point.)


My proposal would be to let the community build a stdlib and after it is battle tested merge it with core PHP.

It has been proposed before to have PHP source shipped with PHP (and also the possibility mix C and PHP) and think that would be the best option.

One option could be to have slower evolved stdlib in core and a faster community version with composer.

Reason why I’m proposing to develop it outside of core is because a rfc based process is not necessarily the best approach to design a good & well functioning api (and empirically that is true).

It is better to deliver a complete stdlib (or major sub parts) as one or multiple rfc.

And by doing like this you allocate resources better, the few with knowledge about PHP internals can keep focusing on that while the community, a much larger group, can design a stdlib.

And PHP has done a lot of great work on making user land and stdlib on equal footing, so now you can implement strpos(…) to exactly match the stdlib version thanks to union types, similar argument parsing and using same type rules (type errors) between the too.

Only major thing I know of that differs when exposing an api, that is either from a PHP C extension or PHP code, is operator overloading.

A rfc proposal to add it was unfortunate declined, but I’m hopeful that on day it will be added in some form because of this reason, it ought to be possible to express the same intent regardless if it is from C or PHP.

With user land operator overloading we can implement object based primitives with methods instead of the current function based approach. And it could be possible to extend it.

Other nice things you could do is to implement safe and unsafe string handling to avoid injections.

With operator overloading the community can evolve the language without the need to evolve PHP itself.


> defaulting to 0 doesn't count

Why this arbitrary restriction? A forced cast of a string to integer is always guaranteed to produce an integer.


And a forced cast is therefore a bad way to generally parse a user-provided string to int.


So why do you insist on using it that way?


I don't. I asked for an int parsing function, got (int)$val as a suggestion, so I had to explain why it doesn't fit the bill.


And how are we supposed to distinguish that from a legit 0?


is_numeric() has been available since forever, and is intended for exactly the thing you appear to want to do.

https://www.php.net/manual/en/function.is-numeric.php


At this point you're writing the parser that ships in most language's standard libraries.

And, if you naïvely use the suggested function for the purpose you've suggested it for, e.g., like,

  if(!is_numeric($input)) { error(); }
  else { return (int)$input; }
…you'll parse a lot of strings that still aren't valid integers. (E.g., "2e-2" is "numeric" and would thus parse.)


I think that in that case it should return false instead of 0 so (int)$val === false means that the variable is not a number.

Right now I guess that the alternative is using is_numeric and then casting to int if possible.


But the forced cast to integer is always guaranteed to result in an integer. So why would it make more sense to explicitly force cast a variable's type to an integer and get a boolean as the functions return value?

Edit:

> (int)$val === false

Would always be false because comparing two types, an integer and boolean would always be false.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: