"Fatal error: Cannot redeclare" when reusing xml parsing code - php

I have a single xml parsing function that I'm trying to call multiple times as I only need to strip a little data out and continue on.
Here is the function:
//Parse Product ID from Product Sides
function getProductSpecs($xml,$type) {
// Setup arrary
global $productspecs;
global $count;
$count = 0;
global $type_check;
$type_check = $type;
// Parse the XML
// Create the parser
if (! ($xmlparser = xml_parser_create()) )
{
die ("Cannot create name list parser");
}
// Start tag function
function first($parser, $name, $attribs) {
global $trigger;
if ($name == "PRODUCTSIDEID") {
$trigger = 1;
} elseif ($name == "PRODUCTID") {
$trigger = 1;
}
}
// data handler function
function xml($parser, $data) {
global $trigger;
global $productspecs;
global $count;
global $type_check;
if ($trigger == 1){
if ($type_check == "sideid") {
$productspecs[$count]=$data;
$count = $count + 1;
} elseif ($type_check == "productid") {
$productspecs[$count]=$data;
$count = $count + 1;
}
$trigger = 0;
}
}
// Call the handler functions
xml_set_element_handler($xmlparser, "first", "");
// Call the data handler
xml_set_character_data_handler($xmlparser, "xml");
// Parse the XML data
xml_parse($xmlparser,$xml);
// Clear parser
xml_parser_free($xmlparser);
//Return the array
return $productspecs;
}
My problem arises when this is called:
xml_set_element_handler($xmlparser, "first", "");
I get the redeclare error on:
function first($parser, $name, $attribs) {
The function only appears the one time and I'm assuming the problem occurs on the call but is there a way around this so I don't have to duplicate so much code. I'm going to have to iterate through this multiple times.
Thanks.

Defining functions inside of functions can lead to this. Each time you run getProductSpecs() it's going to try to declare first() and xml() again, and in PHP, all user functions are declared in a global scope. The best solution is to move your first() function and your xml() function outside of the main getProductSpecs() function.
Another option is to use function_exists() around your function declarations, like this:
if (! function_exists('first')) {
// Start tag function
function first($parser, $name, $attribs) {
global $trigger;
if ($name == "PRODUCTSIDEID") {
$trigger = 1;
} elseif ($name == "PRODUCTID") {
$trigger = 1;
}
}
}

Related

PHP - Check if a function contains

I want to check if a function contains a variable called $marker.
This is what I'm trying to do:
if(function('head') contains '$marker') {
return true;
}
Is there any way to do this?
Ummm... it's not built into PHP, and, frankly, changing the files would be better, but for science reasons, I wrote a check for it. It fetches the filenames's contents every function call, so I'd recommend, if you use it more than once, to store the file's contents in another variable, but, nevertheless, this is will give you a functional view on how to do it:
<?php
function test() { $marker;}
function negativeTest() {
$noMarker;
}
function checkFunction($function, $variable, $filename) {
$file = file_get_contents($filename);
preg_match_all("/function\s+([a-z0-9_-]+)\s*\(.*?\)\s*\{((\n|.)*?)\}/im",$file,$matches);
for ($i = 0; $i < count($matches[1]); $i++) {
if ($matches[1][$i] == $function && strpos($matches[2][$i], $variable) != false) {
return true;
}
}
return false;
}
echo checkFunction("test","\$marker","index.php");
?>

How to access a member variable of different function in a codeigniter controller

//first function
function insertdigit(){
$userdigit=5;
$flag = $this->usermodel->userdigitmodel($userdigit);
$value = array(
'result' => $flag
);
echo json_encode($value);
if ($flag == true) {
return $userdigit;
} else {
}
}
//second function
function usedigit(){
$data['userdigit']=$this->insertdigit();
}
but i get {"result":true} goes back to the function? how to access a member variable in a different member function
Try to remove echo json_encode($value); in your code.
If you need to access a parameter in several functions on your controller, you have to create it outside your function so it will be available for all your controller functions.
So, in your case it should be something like this:
class Test extends Controller
{
private $userdigit; //here you can set a default value if necessary: private $userdigit = 5
function insertdigit(){
$this->userdigit=5;
$flag = $this->usermodel->userdigitmodel($this->userdigit);
$value = array(
'result' => $flag
);
echo json_encode($value);
if ($flag == true) {
return $this->userdigit;
} else {
}
}
//second function
function usedigit(){
$data['userdigit']=$this->userdigit;
}
}
This way your userdigit variable is available for all your functions. With $this you are telling PHP that you are trying to access something inside the class.
This link contain more and useful information: http://www.php.net/manual/en/language.oop5.properties.php
Is that what you really need?
A possible solution:
function insertdigit()
{
$userDigit = 5;
$flag = $this->usermodel->userdigitmodel($userDigit);
$value = array
(
'result' => $flag
);
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest')
{
echo json_encode($value);
}
if ($flag == true)
{
return $userdigit;
}
else
{
}
}
//second function
function usedigit()
{
$data['userdigit'] = $this->insertdigit();
}
The above code, in insertdigit detects if there is an Ajax request and if so, it will echo out the json_encoded data. If you call it in an normal request, i.e. via usedigit it won't echo the json_encoded data (unless you are calling usedigit via an Ajax request).
Your question doesn't really explain what you are doing, so it's hard to explain a better solution, however, if you are trying to access a "variable" in more than one place, you should really separate your code so you have a single entry point for that variable.
Is your variable dynamic, or is it static?

Easiest way to detect/remove unused `use` statements from PHP codebase

I've searched all over for something like this but I believe the word "use" is perhaps too common for any helpful results:
What is the easiest way to remove all un-used use statements from class files in a PHP codebase?
Edit: For the sake of simplicity, we can ignore detecting use statements that are used for annotations.
Check FriendsOfPHP's PHP-CS-Fixer https://github.com/FriendsOfPHP/PHP-CS-Fixer
EDIT
I have completely rewritten it, so now it is much more powerful:
Traits and anonymous/lambda functions are ignored
Now taking care of catch blocks, class extensions and interfaces
Indentation and comments don't matter
Multiple declarations for namespace aliases work too
Static and object class calls are recognized as "usage" ($u->getUsages())
Full and half qualified usages are not treated
The test file, class.php:
<?php
use My\Full\Classname as Another, My\Full\NSname, Some\Other\Space;
/* some insane commentary */ use My\Full\NSname1; use ArrayObject;
$obj = new namespaced\Another;
$obj = new Another;
$a = new ArrayObject(array(1));
Space::call();
$a = function($a, $b, $c = 'test') use ($obj) {
/* use */
};
class MyHelloWorld extends Base {
use traits, hello, world;
}
And here the script:
<?php
class UseStatementSanitzier
{
protected $content;
public function __construct($file)
{
$this->content = token_get_all(file_get_contents($file));
// we don't need and want them while parsing
$this->removeTokens(T_COMMENT);
$this->removeTokens(T_WHITESPACE);
}
public function getUnused()
{
$uses = $this->getUseStatements();
$usages = $this->getUsages();
$unused = array();
foreach($uses as $use) {
if (!in_array($use, $usages)) {
$unused[] = $use;
}
}
return $unused;
}
public function getUsages()
{
$usages = array();
foreach($this->content as $key => $token) {
if (!is_string($token)) {
$t = $this->content;
// for static calls
if ($token[0] == T_DOUBLE_COLON) {
// only if it is NOT full or half qualified namespace
if ($t[$key-2][0] != T_NAMESPACE) {
$usages[] = $t[$key-1][1];
}
}
// for object instanciations
if ($token[0] == T_NEW) {
if ($t[$key+2][0] != T_NAMESPACE) {
$usages[] = $t[$key+1][1];
}
}
// for class extensions
if ($token[0] == T_EXTENDS || $token[0] == T_IMPLEMENTS) {
if ($t[$key+2][0] != T_NAMESPACE) {
$usages[] = $t[$key+1][1];
}
}
// for catch blocks
if ($token[0] == T_CATCH) {
if ($t[$key+3][0] != T_NAMESPACE) {
$usages[] = $t[$key+2][1];
}
}
}
}
return array_values(array_unique($usages));
}
public function getUseStatements()
{
$tokenUses = array();
$level = 0;
foreach($this->content as $key => $token) {
// for traits, only first level uses should be captured
if (is_string($token)) {
if ($token == '{') {
$level++;
}
if ($token == '}') {
$level--;
}
}
// capture all use statements besides trait-uses in class
if (!is_string($token) && $token[0] == T_USE && $level == 0) {
$tokenUses[] = $key;
}
}
$useStatements = array();
// get rid of uses in lambda functions
foreach($tokenUses as $key => $tokenKey) {
$i = $tokenKey;
$char = '';
$useStatements[$key] = '';
while($char != ';') {
++$i;
$char = is_string($this->content[$i]) ? $this->content[$i] : $this->content[$i][1];
if (!is_string($this->content[$i]) && $this->content[$i][0] == T_AS) {
$useStatements[$key] .= ' AS ';
} else {
$useStatements[$key] .= $char;
}
if ($char == '(') {
unset($useStatements[$key]);
break;
}
}
}
$allUses = array();
// get all use statements
foreach($useStatements as $fullStmt) {
$fullStmt = rtrim($fullStmt, ';');
$fullStmt = preg_replace('/^.+ AS /', '', $fullStmt);
$fullStmt = explode(',', $fullStmt);
foreach($fullStmt as $singleStmt) {
// $singleStmt only for full qualified use
$fqUses[] = $singleStmt;
$singleStmt = explode('\\', $singleStmt);
$allUses[] = array_pop($singleStmt);
}
}
return $allUses;
}
public function removeTokens($tokenId)
{
foreach($this->content as $key => $token) {
if (isset($token[0]) && $token[0] == $tokenId) {
unset($this->content[$key]);
}
}
// reindex
$this->content = array_values($this->content);
}
}
$unused = new UseStatementSanitzier('class.php');
print_r($unused->getUnused());
/*
Returns:
Array
(
[0] => NSname
[1] => NSname1
)
*/
It would probably depend on the way your code is set up. If your code uses namespaces like so:
namespace Foo
{
<one or more classes in namespace Foo>
}
then you're probably fine if you just check each file individually. That still means you would have to parse the PHP code to find the use statements, and then to determine which statements are used.
The easy way is to use a tool that's already been built. I recently started using PhpStorm IDE (30 day free trail, or the early access program) and that can inform you when you have unused use statements in a file (and you can even specify whether that should come up as warnings or errors). It would still require you to open each file though. But you could also check files you are editing, then eventually your code will be cleaner.

trouble with recursion in php

I cannot figure out why this function is not working. Evertime I try to make the recursive call all I get is an IE page with a cannot display error message. I left // by the lines that is causing me the trouble. I also tried the call without the $this-> and got an error function not recognized
private function insert($key, $current) {
$newnode=new Node($key);
$parent=$this->root;
if($this->root==null) {
$this->root=$newnode;
return;
} else {
if($newnode->data > $parent->data) {
$parent=$parent->rightChild;
$this->insert($key, $parent);//if I comment this line it
//work, but that make the function useless
} else {
echo "smaller ";
}
}
}
The error is obviously an infinite recursive loop.
This is most probably due to the fact that you never use the $current argument.
You're always comparing the $newnode->data against $this->root->data which if greater once, will always be greater.
Update
Here's how I'd change it
private function insert($key, $current = null)
{
$newnode = new Node($key);
$parent = null === $current ? $this->root : $current;
if (null === $parent) {
$this->root = $newnode;
return;
}
if ($newnode->data > $parent->data) {
// same as before from here

PHP Function Parameter is always null in Wordpress

I am not an expert Wordpress PHP developer but I am not understanding this situation. I am passing a variable through a static function into the $GLOBALS variable that contains an array. That variable when in the static function is always NULL, but before it goes into it, it is a valid type and prints fine.
functions.php
$badge_Id = get_comment_meta($comment->comment_ID,"badge_id", true);
if(strlen($badge_Id) > 0) {
Cisco_Rewards::add_badge_id($badge_id);
echo $badge_id; // PRINTS PERFECTLY
}
rewards.php
class Cisco_Rewards {
static function add_badge_id($badge_id) {
if(count($GLOBALS['badge_ids']) == 0) {
$GLOBALS['badge_ids'] = array();
}
echo $badge_id; // WONT PRINT, IS NULL
array_push($GLOBALS['badge_ids'], $badge_Id);
print_r($GLOBALS['badge_ids']); // ALWAYS HAS NULL VALUES
}
Instead of
if(count($GLOBALS['badge_ids']) == 0) {
$GLOBALS['badge_ids'] = array();
}
echo $badge_id;
try
var_dump($badge_id); // to check what it contains at the very beginning of the function
if(!is_array($GLOBALS['badge_ids'])) {
$GLOBALS['badge_ids'] = array();
}

Categories