This function returned 524320 for one my classes. If I run it through getModifierNames, it tells me:
>> Reflection::getModifierNames(524320)
array (
0 => 'abstract',
)
Which is correct, but 524320 isn't a power of 2, so it must have some other flags? Actually, if we look at it's binary representation, 10100111 it looks like it has 5 flags set. So what are the other 4, and where can I find a list of all of them?
Edit: Now I'm confused... the representation is actually 10000000000000100000, according to this. Which makes sense, because that corresponds to "explicit abstract class". Oh... I bet this was an overflow issue now that I'm thinking about...must investigate a bit more.
See the ZEND_ACC_* constants in http://lxr.php.net/xref/PHP_TRUNK/Zend/zend_compile.h#144
Mind that some of these are internal and are not exported in anyway to userspace. The ones exported to userspace ones can be found in http://php.net/manual/en/class.reflectionmethod.php and other classes.
Related
just learning PHP and I have a project I'm looking at which appears to have typos but I'm not sure if they are or not.
I want to know if the output of the two bits of code below is the same.
$this->addSubmitElement($this->_buttons[self::BTN_LIST], self::BTN_LIST);
$this->addSubmitElement($this->_buttons[self::BTN_DRAFT], self::BTN_DRAFT);
and
$this->addSubmitElement($this->_buttons[self::BTN_LIST], self::BTN_LIST)
->addSubmitElement($this->_buttons[self::BTN_DRAFT], self::BTN_DRAFT);
It seems it should be but my project behaves differently depending on which version I have.
There's a common pattern used when designing 'mutating' methods (setSmth, addSmth) that update some properties of an object: use that object (i.e., $this) as return value.
Following this pattern enables chaining you've showed in your second example. Note that this is a pattern, but not a requirement; if the package changed, you're not able to use that approach anymore.
I've noticed some inconsistencies in the PHP manual; a number of core function signatures are documented to accept arguments by reference, however they accept arguments by value.
I posted a more specific question previously, and #cweiske provided a great answer (with reference to the pertinent PHP source) however these inconsistencies appear to be more rampant.
There are a number of functions that are affected by this (I'll update this list as warrants; also note, these tests were done in an error_reporting(-1) environment)
http://www.php.net/manual/en/function.current.php
This was already discussed at the linked question
http://www.php.net/manual/en/function.key.php
This was already discussed at the linked question
http://www.php.net/manual/en/function.array-replace-recursive.php
array array_replace_recursive ( array &$array , array &$array1 [, array &$... ] )
Accepts arguments $array, $array1, etc., by value. This has been corrected.
http://www.php.net/manual/en/function.array-multisort.php
bool array_multisort ( array &$arr [, mixed $arg = SORT_ASC [, mixed $arg = SORT_REGULAR [, mixed $... ]]] )
Accepts arguments $arr, etc., by value. This should throw an error, as it won't do anything if the argument isn't a variable.
Now I'm concerned, not because I'm being anal about the documentation, but because I fear that PHP devs are on the fence about the implementation details of these functions (or something equally unreliable)
I use array_replace_recursive() for instance, to take an array argument, and apply it against another array containing defaults. Some of my codebase has taken advantage of this inconsistency, to simply do:
$values = array_replace_recursive(array(
'setting_1' => array(
'sub-setting_1' => '',
'sub-setting_2' => '',
'sub-setting_3' => '',
),
'setting_2' => array(
'sub-setting_1' => 0,
'sub-setting_2' => 0,
),
'setting_3' => true,
), $values);
Thus producing a properly formatted array (to get around gratuitous isset() calls)
Should I be concerned with this? I'm thinking about submitting a documentation related bug request, but I'm first curious if anyone on SO (looking in your direction #cweiske) has insight on why this has been done.
Perhaps I'm not understanding your dilemma, but those functions don't directly modify the data in their parameters, so whether they accept via reference or value is sort of a moot point isn't it? Either way you're going to need to assign the return value if you want the function call to actually do anything for you.
In terms of insight into why you might be seeing the discrepancy. PHP 5 has had many changes made to the way references work. In fact I believe it's PHP 5.3+ that no longer permits certain usages of & to assign by reference. What you may be seeing is the transition of some of the PHP core functions to comply with the new rules about reference assignment. If memory serves me, PHP 5.3 branch was actually intended to be PHP 6, but was decidedly merged into the trunk as a branch instead of waiting for several complex features to be finished. This would account for why you've never seen confusion like this before in PHP.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I need some PHP code to convert some PHP into JS.
functionality - I'm using common PHP functions from php.js
syntax - ???
The issue is converting the syntax. I don't need full PHP syntax, mind you; no need for supporting class definitions/declarations. Here's a small checklist of what needs conversion:
"." should be "+" (string concat)
"->" should be "." (object operator)
"::" should be "." (class operator - not really required)
Please note that the resulting code is pretty much independent of the PHP environment, so no "what if it uses a PHP class?".
I'm not asking for full code, just a tip on the right direction to this kind of conversion; I was thinking about employing a state machine/engine.
If you're curious as to why I'm pushing code to the user side: I need a dynamic way to change visibility of certain elements given certain conditions. My plan is to do this without having to execute this code server side and having unnecessary ajax calls.
Edit: Look people. I know not using AJAX sounds ludicrous to you but the world doesn't work on hype and nice-sounding design conditions (=ajax). I simply can't afford each single user polling my server 5 to 10 times per second just for my server to return a "yes" or "no" answer. Keep in mind that switching is asynchronous, and I can't buffer the AJAX calls.
Edit 2: I am sure what I'm doing is the best way in my situation. There is no "possibly better" way, so quit posting non-constructive comments. I can't get into any more detail than I have so already. The conversion from PHP code to JS is simply a matter of shortening user input; we only need one expression, then convert it to whichever language is necessary (in this particular case, from PHP to JS). The conditions on how this works will not change regardless if I describe the system down to the API specs, and inundating the topic with useless (for you) prototype docs will not help at all.
Also, for those thinking this idea came after waking up form some dream; know this has been reviewed between technical development and QA, so please do not deviate into inexistent design issues.
Edit 3: Examples (original PHP code and expected output):
(original) -- (converted)
5=="test" -- 5=="test"
'$'.(func(12)*10) -- '$'+(func(12)*10)
Fields::count()==5 -- Fields.count()==5
$this->id==5 -- this.id==5
About the last example, don't worry about context/scope, it is correct. Also note that the expressions may look weird; this is because they are expression; a single line of code that must return a value, which explains the absence of an EOL (;) and the multiple use of returning a boolean value. (exotic stuff like backtick operator execution, PHP tags, echo, die, list, etc.. left out on purpose)
Okay, let me take a stab at this one...
Screw regexes. I love them, but there's a better way, and it's built in. Check out token_get_all(). It will parse PHP source as a string and return a list of the very same tokens that PHP itself uses (including the beloved T_PAAMAYIM_NEKUDOTAYIM). You can then completely reconstruct the source of the script, one token at a time, translating it into Javascript syntax along the way.
[charles#teh ~]$ php --interactive
Interactive shell
php > print_r(token_get_all('<?php class Foo { public function bar() { echo "Yikes!"; } } $f = new Foo(); $f->bar(); ?>'));
Array
(
[0] => Array
(
[0] => 368
[1] => <?php
[2] => 1
)
[1] => Array
(
[0] => 353
[1] => class
[2] => 1
)
[2] => Array
(
[0] => 371
[1] =>
[2] => 1
)
[3] => Array
(
[0] => 307
[1] => Foo
[2] => 1
)
...
While this may be a bit overkill, it also uses the same parsing rules PHP uses, and should therefore be less of a long-term pain than regular expressions. It also gives you the flexibility to detect features that can't be translated (i.e. things that php-js doesn't support) and reject the translation and/or work around the problem.
Also, you still haven't told us what you're doing and why you're doing it. There are still probably more accurate, useful answers available. Help us help you by giving us more information.
You believe polling to be unrealistic due to an expected stupidly high number of requests per second. Why are you expecting that number? What does your application do that would cause such conditions?
Why do you want to translate PHP code rather than writing specific Javascript? You're just manipulating page contents a bit, why do you need PHP code to make that decision?
Language translation is probably the least simple solution to this problem, and is therefore an amazingly awful idea. It couldn't have been arrived at as the first option. What are your other options, and why have they been ruled out?
Have you tried Harmony Framework?
Here's the quick and dirty solution I came up with, written in under 20 minutes (probably lots of bugs), but it looks like it works.
function convertPhpToJs($php){
$php=str_split($php,1); $js='';
$str=''; // state; either empty or a quote character
$strs=array('\'','`','"'); // string quotes; single double and backtick
$nums=array('0','1','2','3','4','5','6','7','8','9'); // numerals
$wsps=array(chr(9),chr(10),chr(13),chr(32)); // remove whitespace from code
foreach($php as $n=>$c){
$p=isset($php[$n-1])?$php[$n-1]:'';
$f=isset($php[$n+1])?$php[$n+1]:'';
if($str!='' && $str!=$c){ $js.=$c; continue; } // in a string
if($str=='' && in_array($c,$strs)){ $str=$c; $js.=$c; continue; } // starting a string
if($str!='' && $str==$c){ $str=''; $js.=$c; continue; } // ending a string
// else, it is inside code
if($c=='$')continue; // filter out perl-style variable names
if($c==':' && $f==':'){ $js.='.'; continue; } // replace 1st of :: to .
if($p==':' && $c==':')continue; // filter out 2nd char of ::
if($c=='-' && $f=='>'){ $js.='.'; continue; } // replace 1st of -> to .
if($p=='-' && $c=='>')continue; // filter out 2nd char of ->
if($c=='.' && (!in_array($p,$nums) || !in_array($f,$nums))){ $js.='+'; continue; } // replace string concat op . to +
if(in_array($c,$wsps))continue; // filter out whitespace
$js.=$c;
}
return $js;
}
The following:
$window->alert("$".Math::round(450/10));
Converted to:
window.alert("$"+Math.round(450/10));
Edit: Can't believe all the fuss this question caused compared to the time taken.
Feel free to criticize at will. I don't actually like it much personally.
I wrote a tool called php2js that can automatically convert PHP code to javascript. It is not perfect, but supports the most common PHP functionality including classes, inheritance, arrays, etc, etc. It also includes and knows about php.js, so code written with php's standard library functions may "just work".
Maybe you will find it useful.
Im created tool PHP-to-JavaScript for converting PHP code to JavaScript. Its support:
Namespaces,use
Class, abstract class extends and interfaces
constants and define
Exceptions and catch
list()
magic methods __get __set and __call
and more
In most other Object Oriented languages. it would be sacrilege to have each function receive a single associative array of Objects rather than enumerating each in the method signature. Why though, is it acceptable and commonly used in most popular frameworks for both of these languages to do this?
Is there some justification beyond wishing to have concise method signatures?
I do see a benefit in this -- that the API could remain unchanged as new, optional parameters are added. But Javascript and PHP already allow for optional parameters in their method signatures. If anything, it seems like Java or another OO language would benefit from this more... and yet I rarely see this pattern there.
What gives?
In my opinion, a lot of these functions are climbing in the number of arguments they accept, over 10 is not uncommon. Even if you do optional parameters, you still have to send them in order.
Consider a function like:
function myFunc(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13){
//...
}
Say you want to use arguments 3 and 11 only. Here is your code:
myFunc(null, null, null, 'hello', null, null, null, null, null, null, null, 'world');
Wouldn't you rather just:
myFunc({
a3 : 'hello',
a11 : 'world'
});
?
There are a couple of reasons for this.
The first is that not all argument lists have a natural order. If there is a use-case to only supply the 1st and 6th argument, now you have to fill in four default placeholders. Jage illustrates this well.
The second is that it's very hard to remember the order the arguments must occur in. If you take a series of numbers as your arguments, it's unlikely to know which number means what. Take imagecopyresampled($dest, $src, 0, 10, 0, 20, 100, 50, 30, 80) as an example. In this case, the configuration array acts like Python's named arguments.
The major reason is that those particular languages simply do not support having multiple calling conventions for the same function name. I.E. you can't do the following:
public function someFunc(SomeClass $some);
public function someFunc(AnotherClass $another);
public function someFunc(SomeClass $some, AnotherClass $another);
So you must find another way to create simpler ways to pass your variables around, in PHP we end up with someFunc(array('some'=>$some, 'another'=>$another)) because it is the only convenient way. In JavaScript we end up using objects, which isn't as bad: someFunc({some: something, another: anotherthing})
Ruby follows this methodology as well, and has even devised a more succinct syntax meant specifically for using hashes as initializers, as of Ruby 1.9:
# old syntax
myFunc(:user => 'john', :password => 'password');
# new syntax
myFunc(user: 'john', password: 'password');
The problem being addressed is that, within these languages, you cannot overload functions based on argument type. This results in complex classes with a single constructor that can have a huge and unwieldy argument list. Using hash-like objects to supply parameters allows for a sort of pseudo-overloading by parameter name rather than by type.
My only real problem with this practice is it becomes difficult to document your arguments:
PHPDoc for variable-length arrays of arguments
One of the most important reason why you don't see this in other OO languages is that you are probably referring to compiled languages like C++ or Java.
The compiler is responsible to determine, at compilation time not during execution, which method you want to call and this is normally done based on the signature, so basically it has to be done this way. This is also how method overload is done in these languages.
First of all such technique is very simple for the coders.
They do not need to remember order of all of the parameters of the all functions in your application. The code becomes more readable and more robust.
Any future development, improvements or refactoring will be no so hard to provide. The code becomes more maintainable.
But there is some pitfalls. For example, not every IDE will give you a simple code completing with such functions and their parameters.
In my opinion there 2 reasons why this has evolved:
Array's are very easy to create and manipulate, even with mixed types.
PHP/JS programmers have often a non academic background and are less indoctrinated from languanges like Java and C++.
This question already has answers here:
Python equivalent of PHP's compact() and extract()
(6 answers)
Closed 7 years ago.
Looking for the python equivalent of this.
http://php.net/extract
Maybe you would be better off explaining what you are trying to do. Any solution to the direct question would be rather unpythonic as there is almost certainly a better way to do what you want.
EDIT (per your comments):
And indeed, there is a better way.
What you are trying to do is known as unpacking argument lists, and can be done like this:
self.__api_call__('POST', '/api/foobar/', **mydict)
A working example:
>>> def a_plus_b(a,b):
... return a+b
...
>>> mydict = {'a':3,'b':4}
>>> a_plus_b(**mydict)
7
And it also works with kwargs, as you might expect:
>>> def a_plus_b(**kwargs):
... return kwargs['a'] + kwargs['b']
...
>>> a_plus_b(**mydict)
7
no. why do you need it?
do the following (see comment)
def __api_call__(self, method, resource, **kwargs):
print(kwargs)
def do_call(my_dict):
self.__api_call__('POST', '/api/foobar/', **your_dict) # double asterisk!
One generally uses locals() to achieve this result, but the exact functionality is up to you.
>>> print apple
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: name 'apple' is not defined
>>> print banana
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: name 'banana' is not defined
>>> variables = {"apple" : "a rigid, juicy fruit", "banana" : "a soft, fleshy fruit"}
>>> for variable,value in variables.iteritems():
... locals()[variable] = value
...
>>> print apple
a rigid, juicy fruit
>>> print banana
a soft, fleshy fruit
EDIT
Thanks to everyone who has diligently commented on the badness of this approach. I wholeheartedly agree that THIS IS A BAD APPROACH, and it deserves to be mentioned in the actual response for anyone who stumbles across this page. (Never underestimate that; I saw this technique in a code snippet somewhere. I can see why in that particular case it was harmless, but I know I can't go around encouraging bad methodology just because there are situations in which it won't break.)
IMO it is at least a nice theoretical question: how such construction can be implemented and how does it look like once it is applied?
For instance, as a function it can be implemented as
import inspect
def extract_attribute(obj, names):
if type(names) == str:
names = [names]
# Get previous frame from the inspect stack.
frame = inspect.stack()[1][0]
try:
frame_locals = frame.f_locals
attributes = inspect.getmembers(
obj, lambda attr: not inspect.ismethod(attr))
for name, attribute in attributes:
if name.startswith('__') or name.endswith('__'):
continue
if name in names:
frame_locals[name] = attribute
finally:
del frame
del frame_locals
and used as
class A(object):
foo = 'bar'
a = A()
extract_attribute(a, 'foo')
assert locals()['foo'] == 'bar'
assert foo == 'bar
Note: await pylint will complain on the last line. One can find *extract_attribute* function working with object in somewhat similar way to import functionality for modules. Applying it as additional layer of scope coupling (mixed with present import) will increase complexity of the code almost without exceptions.
PS
Obvious enough manipulating built-in is a sign of doing something python was not designed to do. But self-flattering mantras like not-practical and "non-pythonic" are not really proper arguments to me. In general it is always much more "practical" to make an experiment and to see if:
1. Construction will enrich the expressiveness of the language (e.g. making it more readable and natural-like), give new functionality, etc.
2. Construction is too ugly and dangerous to be used, too flexible and unsafe, performance trade-offs are unacceptable, etc.
Illustration and test by explicit example is a preferred alternative. Looking at code everyone is free to make his own opinion without sharing the "professional guts" or copy-pasting religious dogmas. Please don't.