I work in a php project with multiple independent developers and recently we had case where a function getmicrotime() was twice defined.
all worked fine, because they were defined in different files that were not both included in a single call ... until some refactory.
in the standardcase php would just output a fatal error, but here the output was blocked. (because a thirdparty website called a website ...) so we did not get the output, just the information that nothing worked anymore.
To the point:
Is there any method, external script, etc to check if functions with the same name are defined twice in the project?
i thought about reg. expr search, but ofcourse class methods can have the same name like a::meth1 and b:meth1 .... so its not that easy.
i am talking about a project with ~100.000 lines of ugly code ... so manual checking is not possible
Thanks in advance.
Consider static code analysis. I would suggest Sonar + PHP plugin: http://docs.codehaus.org/display/SONAR/PHP+Plugin
Here is the life example how it works:
http://nemo.sonarqube.org/dashboard/index/net.php.pear.phpcodesniffer
You can always write a simple script (i.e. perl or python) which will find all duplicates. The algorithm would be simple...
Related
I am in the process of migrating a site from my personal dev server onto Windstream's business hosting server. I've already run into the issue of having developed using PHP 5.4 only to find out that my static functions won't work on WS's 5.1.4 installation. I've since fixed those issues and am not facing one that I can't seem to find any help for on the internet.
All of the static functions I was using have been rewritten as functions outside the class scope. Instead of having
class Product{
...
public static function myFunction(){}
...
}
I now have
function myFunction(){}
class Product{...}
in my included Product.php file.
However, when I try to call myFunction() from my code, nothing happens. I know the nothingness comes from WS's error handling, but the point is, the function isn't working. To verify this, I have taken the following steps:
Inserted the line echo "entered included"; immediately following the <?php in Product.php. This prints "entered included" on the index page, indicating that my include is working. I have done the same thing before the final ?> with the same results, so I don't think it's getting hung up inside the included file.
I have changed myFunction() in the included file to be simply
function myFunction(){echo "myFunction works";}
A call to myFunction() still makes nothing happen.
I have moved myFunction() to the including file (myFunction() now lives in index.php instead of Product.php; index includes Product.php). This time, myFunction() executes without issue.
To my 'hack it til it does what it should' sensibilities, this tells me that the server is having a problem with functions that are declared in files that are included; honestly, though, I have absolutely no clue what's going on, and any help would be appreciated. Their website is currently down, and they were expecting it to only be offline for a day, so I'll try pretty much anything short of sacrificing a fatted calf.
I know I should be posting more specific code, but since this is a customer's actual website, I'm trying to put as little of the actual code out here as is possible. I'm happy to append specific sections of code to this entry as they are requested for clarification.
Thanks in advance for your consideration.
#Rottingham: First, thanks for the 3v4l link. Second, my assumption about static methods in 5.4 vs 5.1.4 came from this line of php.net's page on static members and methods:
"As of PHP 5.3.0, it's possible to reference the class using a variable. The variable's value can not be a keyword (e.g. self, parent and static)."
src - http://www.php.net/manual/en/language.oop5.static.php
Since my version and the server version were on different sides of the 5.3 mark mentioned, I incorrectly assumed that this was my problem.
Third, when I get in from my day job, I'll update my code to show errors and update this post if a solution has not yet been found.
Ultimately, my problem isn't with using static methods (since I don't have them anymore) but with using any function that is declared in an included .php file.
I have a PHP daemon script running on the command line that can be connected to via telnet etc and be fed commands.
What it does with the command is based on what modules are loaded, which is currently done at the start. (psuedocode below for brevity)
$modules = LoadModules();
StartConnection();
while(true){
ListenForCommands();
}
function LoadModules(){
$modules = Array();
$dir = scandir("modules");
foreach($dir as $folder){
include("modules/".$folder."/".$folder.".php");
$modules[$folder] = new $folder;
}
}
function ListenForCommands(){
if(($command = GetData())!==false){
if(isset($modules[$command])){
$modules[$command]->run();
}
}
}
So, an example module called "bustimes" would be a class called bustimes, living in /modules/bustimes/bustimes.php
This works fine. However, I'd like to make it so modules can be updated on the fly, so as part of ListenForCommands it looks at the filemtime of the module, works out if it's changed, and if so, effectively reloads the class.
This is where the problem comes in, obviously if I include the class file again, it'll error as the class already exists.
All of the ideas I have of how to get around this problem so far are pretty sick and I'd like to avoid doing.
I have a few potential solutions so far, but I'm happy with none of them.
when a module updates, make it in a new namespace and point the reference there
I don't like this option, nor am I sure it can be done (as if I'm right, namespaces have to be defined at the top of the file? That's definitely workaroundable with a file_get_contents(), but I'd prefer to avoid it)
Parsing the PHP file then using runkit-method-redefine to redefine all of the methods.
Anything that involves that kind of parsing is a bad plan.
Instead of including the file, make a copy of the file with everything the same but str_replacing the class name to something with a rand() on the end or similar to make it unique.
Does anyone have any better ideas about how to either a) get around this problem or b) restructure the module system so this problem doesn't occur?
Any advice/ideas/constructive criticism would be extremely welcome!
You should probably load the files on demand in a forked process.
You receive a request
=> fork the main process, include the module and run it.
This will also allow you to run several commands at once, instead of having to wait for each one to run before launching the next.
Fork in php :
http://php.net/manual/en/function.pcntl-fork.php
Tricks with namespaces will fail if module uses external classes (with relative paths in namespace).
Trick with parsing is very dangerous - what if module should keep state? What if not only methods changed, but, for example, name of implemented interface? How it will affect other objects if they have link to instance of reloaded class?
I think #Kethryweryn is something you can try.
I've found this script for converting wiki syntax to HTML in php and i've tried to integrate it into Codeigniter. it seems really easy to use. However, it's not working, and instead producing around 8 of these errors:
Message: Use of undefined constant LS_NONE - assumed 'LS_NONE'
I think this is because Codeigniter helpers are not a class but rather functions, and this bit of code is a class, or does this issue lie with something else? I've also tried to use it as a model without success.
It also seems horribly outdated (2007). Could somebody suggest a really simple alternative or maybe give an idea of how to convert this to a simple function if that is possible? It's a very short piece of code. I'm not sure how these constants work in relationship to a function versus a class.
I've given the Text_Wiki from Pear ago, but the use and complexity well exceeds both my requirements and knowledge :)
//Any help would be greatly appreciated
Loaded using:
$row = $query->row();
$content=$row->course_content;
$this->load->helper('wiki');
$content=explode("\n", $content);
$output = WikiTextToHTML::convertWikiTextToHTML($content);
$html=array_merge($output);
$data['contents'][]= $html;
$this->load->view('default/a',$data);
It looks like the script is actually a class. put it in the libraries folder and load it with $this->load->library(). That will allow it to properly initialize and define the constants that it uses.
something like:
$this->load->library('wikitexttohtml');
$this->wikitexttohtml->convertWikiTextToHTML($wiki_text);
Here's the situation:
I have a catch-all on my domain email (so *#domain.com) redirecting to a piping script located at /home/domain/scripts/piper.php. This piper script is not within the Kohana ORM, but all of my other files are. I want to try to use Kohana inside this piper.php file.
I have tried (unsuccessfully) all of the following:
Including Kohana
I couldn't figure out what needed to be included, and more importantly how to override the url variable that Kohana uses to determine the right controller. Also, this is a catch-all piper, so it isn't using HTTP (to my knowledge), so much as executing a command.
Piping
I tried piping to the following:
/home/domain/public_html/index.php --uri="piper"
But cPanel makes this impossible, as you can only specify the destination script, and not the proper flags and such (unless I am missing something).
PHP exec()
I tried using the following line:
exec("php /home/domain/public_html/index.php --uri=\"/piper\"")
I was hoping that the stdin data would be maintained across the exec() command, but I could never get it to recognize the uri command, though I can run this on my localhost and it works just fine.
I was using http://www.coderelic.com/2011/10/creating-cron-jobs-in-kohana-3-x-is-a-piece-of-cake/ as a reference, but can't get anything to work.
I'm happy with either one of these solutions such that I can see an incoming email, parse it, then send emails based on the parameters.
Let me know if you need more information! I'm le stumped.
/home/domain/public_html/index.php --uri="piper" would be a valid way to do it. If your host sucks and doesn't let you specify that, put it into a bash script instead and reference that.
If you are on any recent version of kohana (3.2 or 3.3), a better way to do this would be to use Minion to run the command line task. This is what Minion was designed for.
All you need to do is to:
modify your piper.php script to be a valid PHP class;
place it in /application/classes/ folder;
Kohana will automatically load your class file (like include) during initialization.
Then you can use your piper class as usual class by $piper = new Piper; ....
UPD
You have to serve your emails trough Kohana.
Create controller, for example pipe (route it with /pipe URL):
public function action_pipe() {
$pipe = new Pipe; // This creates new Pipe object (your emails serving class)
$pipe->serve(); // Sserve emails within `serve()` method of Pipe class
}
Although admittedly, I'm not sure if these other answers are correct because I can't figure out how to reproduce the results.
What ended up working for my situation was to create a Controller_Piper class that is called in the /home/domain/scripts/piper.php. What I did was to copy the code from /home/domain/public_html/index.php and changed the following:
echo Request::factory("/piper")
->execute()
->send_headers(TRUE)
->body();
This loads the piper controller and executes everything very nicely. Not sure if it's the cleanest, but it does work.
In order to localize strings used within my javascript, I want scan all my js files for such strings.
I am using a t() function to request string translations as follows:
t("Hello world");
or with dynamic portions:
t("Hello #user", {"#user": "d_inevitable"});
I want to detect all calls to the t() function and thus gather the strings contained in the first argument in a php "build" script, but skipping the following:
function foo(t) {
t("This is not the real t, do not localize this!");
}
function bar() {
var t = function(){}; //not the real t either...
}
function zoo() {
function t() {
//This also isn't the real t() function.
}
}
t("Translate this string, because this is the real t() in its global scope");
So the simple rule here is that the t function being invokes must be in global scope in order for the first argument to qualify as a translation string.
As a rule, dynamic runtime data as first argument is not allowed. The first argument to t() must always be a "constant" literal string.
I think php codesniffer will help me do it, however all the documentation I could find on it is about enforcing code standard (or detecting violations of it). I need lower level access to its js lexer.
My question is:
Would the php codesniffer's js lexer be able to help me solve my problem?
If so how do I access that lexer?
Are there any other php libs that could help me find the calls to t()?
Please do not suggest stand-alone regular expressions as they cannot possibly solve my problem in full.
Thank you in advance.
What you are describing is basically a coding standard. Certainly, ensuring strings are localised correctly is part of many project standards. So I think PHPCS is the right tool for you, but you will need to write a custom sniff for it because nothing exists to do exactly what you are after.
The best thing to do is probably clone the PHPCS Git repo from Github and then create a new directory under CodeSniffer/Standards to contain your custom sniff. Let's say you call it MyStandard. Make sure you create a Sniffs directory under it and then a subdirectory to house your new sniff. Take a look at the other standards in there to see how they work. You'll also find it easier to copy an existing ruleset.xml file from another standard and just change the cotent to suit you. if you don't want to include any other sniffs from anywhere (you just want to run this one check over your code) then you can just specify a name and description and leave the rest blank.
There is a basic tutorial that covers that.
Inside your sniff, you'll obviously want it to check JS files only, so make sure you specify that in the supportedTokenizers member var (also in the docs). This will ensure PHP and CSS files are always ignored.
When you get down to the actual checking, you'll have full low-level access to the parsed and tokenised content of your file. There are a lot of helper functions to check things like if the code inside other scopes, or to help you move backwards and forwards through the stack looking for bits of code you need.
TIP: run PHPCS using the -v option to see the token output on your file. It should help you see the structure more easily.
If you want to really do things properly, you can even create a nice unit test for your sniff to make sure it keeps running over time.
After all this, you'd check your code like this:
phpcs --standard=MyStandard /path/to/code
And you can use a lot of integrations that exist for PHPCS inside code editors.
You might decide to add a new more sniffs to the standard to check other things, which you can then do easily using your ruleset.xml file or by writing more custom sniff classes.
I hope that helps a bit. If you do decide to write your own sniff and need help, just let me know.