php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #78683 [ Feature ] Add function to safely print nested objects / arrays in Exceptions
Submitted: 2019-10-18 08:08 UTC Modified: 2019-10-19 10:37 UTC
From: 6562680 at gmail dot com Assigned:
Status: Not a bug Package: *General Issues
PHP Version: 7.3.10 OS: Win10
Private report: No CVE-ID: None
 [2019-10-18 08:08 UTC] 6562680 at gmail dot com
Description:
------------
See the example

Usually it looks like exception with error message like "Something wents wrong", instead of "your data is incorrect: {data}"

For example - in JS console you can print "anything". Every object has some string representation. Its not realization, its only debug/output stuff.

Every person who i had asked answers like "you can extend exception to solve" - my answer is "i can solve the problem, i want FAST AND COMFORTABLE solve the issue". I can solve it adding argument with extending, adding Exceptions folder, there will be at least 20 lines of code, then everywhere i should "use" that damn exception, remembmer about this dependency, and remember that i should be inside the module. Of course i can create own function in own library or file, so i need write composer json, and everybody should remember to composer install, know how dependencies works and in fully example - know dependency injection at least.

Am using something like that, there is buggy, dev realization of course
```
// printval
public function printval($data) // : mixed
{
  if (is_null($data)) return 'null';
  if (false === $data) return 'false';
  if (true === $data) return 'true';
  if (is_float($var) && is_nan($var)) return 'NaN';
  if (is_scalar($var) && (! (is_bool($var) || is_nan($var) || ('' === $var)))) return $data;

  if (is_array($data)) {
    array_walk($data, function (&$item) {
      $item = $this->printval($item); // ! recursion
    });
    
    // some serialization or cutted one
    return $cut_serialized;
  }

  if (is_resource($h) || 'resource (closed)' === gettype($h)) {
    return '{ Resource #' . intval($data) . ' }';
  }
  
  if (is_string($var) || is_numeric($var) || (is_object($var) && method_exists($var, '__toString'))) {
    return strval($data);
  }

  if (is_object($data)) {
    // reduce class length building it like scissors regarding @maxlen attribute or const
    // Hello/World/Test/Foo/Bar -> Hello/.../Bar -> Hello/World/.../Bar -> Hello/World/.../Foo/Bar
   
    return $cut;
  }
  
  return strval($data);
}
```

Test script:
---------------
class Someclass
{
  protected $data;

  public function hasSomething($by) : bool
  {
    if (is_string($by)) return isset($this->data[ $by ]);
    elseif (is_object($by)) return $this->SOME_CHECK_METHOD_RETURNS_BOOL($by);
  }

  public function hasSomethingOrFail($by)
  {
    if (! $this->hasSomething($by)) {
      throw new \RuntimeException('Bad: ' . EXPECTED_FUNC($by));
    }
  }
}

Expected result:
----------------
function printval() {} // logval(), lognow() or something
function hash() // creates hash for variable depending on its type automatically, allows me to build array with hash() keys to unique or merge records without tonns of foreachs.


Actual result:
--------------
There's no function like that.
You write it as you want, you extending exceptions, you should carry damn dependencies even if your project should contain 1 file with simple logic.

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2019-10-18 11:38 UTC] requinix@php.net
-Status: Open +Status: Not a bug
 [2019-10-18 11:38 UTC] requinix@php.net
print_r
var_dump
var_export
gettype
get_class
json_encode
serialize

This is a bug tracker. It is not suitable for Twitter rants.
 [2019-10-18 17:28 UTC] 6562680 at gmail dot com
I mark this "bug" as feature/change request, are you saw it?

Have you tried to print exception with var_export? Did you see these "\n" in every debug panel that try to replace line breaks? Why did you ask me to do that? Please, review that comment if you regard community experience
 [2019-10-18 17:33 UTC] 6562680 at gmail dot com
print_r - has linebreaks that will be replaced to '\n' string representation, has recursions and 2000 symbols of possible length

var_dump - same
var_export - same, use it for sync both file and config

gettype - you see 'object'. nice one. all becomes explained when you see 'object'

get_class - yes, write that damn 7-lines if/else in each exception

json_encode - could be used, because does not contain line breaks, but works as complete example creating expectation that value could be copied. No, exception should give you short info instead of copied object

serialize - unreadable useless thing, could be improved in caches, but not for output.

just stop deny all request you see.
 [2019-10-18 17:38 UTC] requinix@php.net
I'll try this another way:

What is an example of the input you will give this function, and what output do you want to get?
 [2019-10-18 18:13 UTC] 6562680 at gmail dot com
(Any type) -> short one-line (string)
 [2019-10-18 18:15 UTC] 6562680 at gmail dot com
any type including closed resources, nans, true/false, object of any class and so on. it can be stringable or not. if stringable - we prefer toString
 [2019-10-18 18:50 UTC] requinix@php.net
How would it produce a "short one-line string" for something like $_SERVER? What does it produce for classes without a __toString? What about binary strings? Control characters like newlines and tabs? And how *is* recursion supposed to be handled?

Could it be that maybe your logging method of sticking something into the exception message isn't good enough? And that maybe you need a more complex solution, like PSR-3?
 [2019-10-19 00:18 UTC] 6562680 at gmail dot com
Its not a serialization. To serialize we still should pass additional argument.
Its not for logging where you should get full explained output.
The function is used only at info level, between the developers, in maybe notifications / exception.
I dont cry that is REQUIRED AS AIR. Will be great to have this one to print "variable info" in short as we can, to help developer to explain while debugging without analyze logs. No more!

It just like "console.log()" keeping in the mind that we havent interactive dropdown lists, and have only one string

How would it produce a "short one-line string" for something like $_SERVER?
{ Array(27) }

What does it produce for classes without a __toString?
{ Object #27 My\Awesome\Namespace }

What about binary strings?
Not sure: represent as is, but maybe "\0PropertyName\0 representation

Control characters like newlines and tabs? "Still '\t' and '\n'. If it is a string with these chars - ok, you pass it you get it. Var_dump() creates it to format output.

And how *is* recursion supposed to be handled?
In this function - noway and not requested. You just display object id and classname, it will be used like this:

throw new \UnexpectedValueException('Incorrect object passed: FUNC($var) => FUNC(...$allowed_list) (split with space if unpack)


Could it be that maybe your logging method of sticking something into the exception message isn't good enough? And that maybe you need a more complex solution, like PSR-3?

Again i know about logging. know about extending exceptions and can send my exceptions to bugtracker. I just want to skip requirement to deep debugging and log analyzing on easy validation stuff like "value not in list".

When i debugging - i still remember what values i expect, i just need to short hint what value was passed (and resulted with exception). I dont need exactly deep representation and ability to copy and convert back. Just view short hint about like if you use Symfony\VarDumper but without dropdowns - only type/id/length
 [2019-10-19 00:22 UTC] 6562680 at gmail dot com
String could be { String(27) "My\0BadString\27With\t\nTabs...." }

// split vars with 1 space
logval(...$arguments)

// cut every output to maxlen then wrap with '{ <Type> [#<id>] <Cutstr> }
printval(int $maxlen, ...$arguments);
 [2019-10-19 00:37 UTC] 6562680 at gmail dot com
oh my bad i wrote topic name "safely print"
i mean safely for interpreter

you know, when you calling "is_nan" (that returns bool) you could get fatal error like "you variable is not a float", i mean "safely for that stuff"

(strval) object -> fatal "non-stringable"

i mean without this fatals everywhere that could be solved only with if/else
 [2019-10-19 02:24 UTC] requinix@php.net
Here's the thing. Adding a new function to the core because someone doesn't like the 8 (I forgot debug_zval_dump) or more functions that serve a similar purpose isn't enough of a reason to do so. The whole point of allowing people to write their own classes and functions is specifically because PHP won't have everything already, and sharing that custom code between projects is why PEAR and Composer exist.

So here's my offer. Go on the internals mailing list and see what they think - I'm not saying this needs an RFC, just to talk about it - and if they agree with you that another function is warranted then so be it.
 [2019-10-19 07:28 UTC] 6562680 at gmail dot com
understand all about php.
array_map(func, array)
but array_filter(array, func)

i can put here 12 bugs that makes me angry from

but instead of make it better, we talking talking talking. creating rfc, explaining and deny features by any reason

i tried 6 times (there is 1 time) - nothing changed.

i understand the logic of community speech php is dead
its not dead, its freezed.
 [2019-10-19 07:35 UTC] 6562680 at gmail dot com
just... little bit confused about my life was PHP all 12 years i spent for that shit. 12 damn years. i imaged the reason for each comma i put in my code, know how to write fastest the faster.

but the dev team recommends me asking "all the community" of people who writing 1/2 years to be agree, and spent 2 years to build my own authority (what? likes? followers? what is need to get some votes from people today)?

no problem. just continue to speak. i'd better to do my job without ideas, suggestions, complaining and so on. its useless.
 [2019-10-19 10:37 UTC] nikic@php.net
-Block user comment: No +Block user comment: Yes
 [2019-10-19 10:37 UTC] nikic@php.net
Moderation note: Comment by "jdjdirjdktidie at shutup dot com" removed and further comments on this bug disabled.

Adding this kind of functionality requires an RFC (https://wiki.php.net/rfc/howto). In this particular case, at least a reference implementation in PHP, examples of the produced output, as well as intended usage scenarios should be outlined in the proposal.

For the record, I do think that some functionality like this could be useful (another application would be phpt tests), but it needs a more careful outline before a useful discussion can be started on it. The description in this feature request is somewhat ... rambling.
 
PHP Copyright © 2001-2021 The PHP Group
All rights reserved.
Last updated: Wed Apr 21 21:01:24 2021 UTC