Functions not being seen in class [SOLVED]

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

kayers
Forum Newbie
Posts: 14
Joined: Tue Apr 25, 2006 9:38 am

Functions not being seen in class [SOLVED]

Post by kayers »

Hey,

I'm having to modify a php application, and I'm having some trouble. I've added functions to a class and call them in another file, but it's like they're not even getting called. I don't understand why... I'm opening and writing a file in both functions I'm calling, as well as in a function I haven't otherwise touched, and only the last one actually works, even though the code is exactly the same (couldn't just echo it because this is an email parser). I don't understand why these functions don't seem to be getting called because I'm calling them in that file, just like all the others.

Is there anyway the functions for this class could be prototyped elsewhere?

Thanks!

[Edit]
Apparently, when an email is created in Cerberus' Agent GUI, it doesn't pass through the parser, but the functions are called directly from create.php. That's why nothing I was adding to parser.php was getting called... :oops:
Last edited by kayers on Thu Apr 27, 2006 2:20 pm, edited 1 time in total.
User avatar
pickle
Briney Mod
Posts: 6445
Joined: Mon Jan 19, 2004 6:11 pm
Location: 53.01N x 112.48W
Contact:

Post by pickle »

Class definitions can't span multiple <?PHP ... ?> blocks, let alone multiple files. If you want to add functions to a class, your best bet is to extend it with the new file:

Original class file

Code: Select all

<?PHP
class Widget
{
    function Widget(){}

    function scream()
    {
        echo "AAAAAAAAHHHH";
    }
}
?>

New extension file

Code: Select all

<?PHP
class NewWidget extends Widget
{
    function Widget{}

    function VerbalDiarrhea()
    {
       $chars = "abcdefghijklmnopqrstuvwxyz";
       for($i=0;$i<100;++$i)
       {
          echo $chars{rand(0,26)};
       }
    }
}
?>
Calling file

Code: Select all

<?PHP

$myWidget = newWidget();

$myWidget->scream();
$myWidget->VerbalDiarrhea();

?>
Real programmers don't comment their code. If it was hard to write, it should be hard to understand.
kayers
Forum Newbie
Posts: 14
Joined: Tue Apr 25, 2006 9:38 am

Post by kayers »

Ooo... Interesting suggestion. Hadn't thought of that! I was just plopping in new functions in the class. I'll give it a try; thanks!
kayers
Forum Newbie
Posts: 14
Joined: Tue Apr 25, 2006 9:38 am

Post by kayers »

Well, I did it, and it still doesn't work... I'm completely stumped; it's like the application's just passing over the calls, and I don't know why... I'm adding custom field instantiation via email to Cerberus Helpdesk; it's very crude right now, but I don't have much experience with php other than using Smarty and doing some work with forms. Sorry to be a bother. :(

in parser.php:

Code: Select all

$cer_parser = new CER_CF_PARSER();
$cer_ticket = new CER_CF_PARSER_TICKET();
.
.
.
array_push($custom_fields,$cer_parser->find_custom_field_in_body($o_raw_email));
.
.
.
$cer_ticket->instantiate_custom_fields($custom_fields);
in cf_email_parser.php:

Code: Select all

class CER_CF_PARSER extends CER_PARSER
{
	function find_custom_field_in_body(&$raw_email)
	{	
		$custom_field_values = array();
		$options;
		
		$sql = "SELECT g.group_id, g.group_name, ".
			"f.field_id, f.field_name, f.field_type, v.field_value ".
			"FROM `field_group` ".
			"LEFT JOIN `fields_custom` f ON (f.field_group_id = g.group_id) ".
			"LEFT JOIN `field_group_values` v ON (v.field_id = f.field_id) ".
			"ORDER BY g.group_name";
			
		$res = $this->db->query($sql);
		
		preg_match_all("/\[Group\](.*)/i",$raw_email->body,$groups, PREG_SET_ORDER);
		preg_match_all("/\[Field Name\](.*)/i",$raw_email->body,$field_names, PREG_SET_ORDER);
		preg_match_all("/\[Field Value\](.*)/i",$raw_email->body,$field_values, PREG_SET_ORDER);
		
		if($this->db->num_rows($res))
		{
			while($row = $this->db->fetch_row($res))
			{
				if($row["group_id"] != NULL)
				{
					$counter = 0;
					
					foreach($groups as $group_name)
					{
						if($group_name[1] == $row["group_name"])
						{
							foreach($field_names as $f_name)
							{
								if($f_name[1] == $row["field_name"])
								{
									foreach($field_values as $f_val)
									{
										if($row["field_type"] == "D")
										{
											$sql2 = sprintf("SELECT o.field_id, o.option_id, o.option_value ".
													"FROM fields_options o ".
													"WHERE o.field_id = %d ".
													"ORDER BY o.option_order, o.option_value ASC",
														$row["field_id"]
												);
											$res2 = $this->db->query($sql2);

											if($this->db->num_rows($res2)) 
											{
												while($row2 = $this->db->fetch_row($res2)) 
												{
													$options = array($row2["option_value"]);
												}

												foreach($options as $i)
												{
													if($i == $f_val[1])
													{
														$custom_field_values[$counter] = array($row["group_id"], $row["field_id"], $row["field_value"]);
													}
												}
											}
										}
										else
										{
											$custom_field_values[$counter] = array($row["group_id"], $row["field_id"], $f_name[1]);
										}
									}
								}
							}
						}
					}
					
					$counter++;	
				}	
			}
		}
		
		//test
		$filename = "test_find.txt";
		$fp = fopen($filename, "a");
		$string;
		
		foreach ($custom_field_values as $val)
		{
			$string .= $val;
		}
		
		$write = fputs($fp, $string);
		fclose($fp);
		
		
		return $custom_field_values;
	}
	
	
}

class CER_CF_PARSER_TICKET extends CER_PARSER_TICKET
{
	function instantiate_custom_fields($custom_fields = "")
	{
		$field_handler = new cer_CustomFieldGroupHandler();
		
		//test
		$filename = "test_instantiate.txt";
		$fp = fopen($filename, "a");
		$string = "in instantiate_custom_fields";
		$write = fputs($fp, $string);
		fclose($fp);
		
		
		if(is_array($custom_fields))
		{
			foreach($custom_fields as $cf_fields)
			{
				$instance_id = $field_handler->addGroupInstance("T", $this->ticket_id, $cf_fields[0]);
				$field_handler->setFieldInstanceValue($cf_fields[1], $instance_id, $cf_fields[2]);
			}
		}
		else
		{
			;
		}
	}
}
User avatar
pickle
Briney Mod
Posts: 6445
Joined: Mon Jan 19, 2004 6:11 pm
Location: 53.01N x 112.48W
Contact:

Post by pickle »

You've mentioned 4 classes in your cf_email_parser.php:

Code: Select all

CER_CF_PARSER extends CER_PARSER
That means you've already got a class CER_PARSER, and this new class you're declaring, CER_CF_PARSER is an extension of that class

Code: Select all

CER_CF_PARSER_TICKET extends CER_PARSER_TICKET
Again, means you've already got a class CER_PARSER_TICKET and this new class CER_CF_PARSER_TICKET is an extension of it.

Do you have a class called CER_PARSER? If not, you probably want to declare your classes like this:

Code: Select all

class CER_CF_PARSER
{
...
}
class CER_CF_PARSER_TICKET extends CER_CF_PARSER
{
...
}
Does that make sense?
Real programmers don't comment their code. If it was hard to write, it should be hard to understand.
kayers
Forum Newbie
Posts: 14
Joined: Tue Apr 25, 2006 9:38 am

Post by kayers »

Yeah, it makes sense. :) But there are classes named CER_PARSER and CER_PARSER_TICKET, but they're really long, and I didn't want to take up a lot of space. :)

Originally, I'd had those 2 functions in CER_PARSER and CER_PARSER_TICKET, respectively, and thought they'd behave just like all the other functions, but when I submitted an email through the GUI (submitting a new trouble ticket actually writes and sends an email), I wasn't seeing the behavior I was expecting when I went to view the new ticket in the GUI. So, I put in those little fopen, etc lines, just to see if the function was actually being entered. Nothing... So, just to make sure I had THAT code correct, I put it in a function I KNEW was working (create_new_ticket). And it worked...

So then I made sure my calls weren't in some kind of condition that wasn't being met. They weren't. In fact...

Code: Select all

$cer_ticket->create_new_ticket($o_raw_email->headers->subject,$dest_queue);
$cer_ticket->instantiate_custom_fields($custom_fields);
The calls are RIGHT AFTER ONE ANOTHER! 8O

I'm stumped. But thank you so much for your help, pickle! I really appreciate it, and it helps to discuss the problem. I have experience with CFML, HTML, Javascript, C++, etc, but not too much with PHP. So, I thought it would be good to post on a forum to see if there's something I'm overlooking. But even my coworker who's familiar with PHP couldn't figure it out. :?
User avatar
pickle
Briney Mod
Posts: 6445
Joined: Mon Jan 19, 2004 6:11 pm
Location: 53.01N x 112.48W
Contact:

Post by pickle »

Ok, at this point I'd start debugging right from the beginning. By that I mean echo something from the constructor method of CER_CF_PARSER_TICKET - just to see if its even being instantiated.

From there, I'd dump this line in right after you instantiate your CER_PARSER_TICKET class:

Code: Select all

echo '<pre>';
print_r(get_class_methods('CER_PARSER_TICKET'));
echo '</pre>';
As you might guess, that line will dump all the functions in your ticket class. See what that gives you.

Remind me - is the function defined in the parser class working and the function defined in the ticket class not working?
Real programmers don't comment their code. If it was hard to write, it should be hard to understand.
kayers
Forum Newbie
Posts: 14
Joined: Tue Apr 25, 2006 9:38 am

Post by kayers »

Hmm, I can't echo anything (I think; is there a way to echo it out to a console/terminal?) because this code is being used underneath the surface, parsing the email, BUT I'll try to have it printed to a file. Neither functions in the subclasses I made are getting called, but the functions in the parent classes (CER_PARSER and CER_PARSER_TICKET) are, but if I move my functions there, they're STILL not getting called.

We shall see! Thanks!

Edit:
Just tried running it from the CLI, but there are so many dependencies with this file, it won't let me. I try to print out the functions to a text file using get_class_methods with no luck, but I think I'm doing it wrong. I'm going to keep Googling, but if anyone has any suggestions, I'd really appreciate it. :)
kayers
Forum Newbie
Posts: 14
Joined: Tue Apr 25, 2006 9:38 am

Post by kayers »

Okay! Here's what I'm getting as a result of little stubs I put in the constructors of CER_PARSER, CER_PARSER_TICKET, CER_CF_PARSER, and CER_CF_PARSER_TICKET:

Code: Select all

in cer_parser_ticket constructor
in cer_parser constructor
in cer_parser_ticket constructor
in cer_parser constructor
in cer_parser constructor
in cer_parser_ticket constructor
in cer_parser constructor
in cer_parser_ticket constructor
So, it is NEVER getting into the CER_CF_blah classes' constructors... But why? I'm "newing" them in parser.php.
User avatar
pickle
Briney Mod
Posts: 6445
Joined: Mon Jan 19, 2004 6:11 pm
Location: 53.01N x 112.48W
Contact:

Post by pickle »

Hmmm,

After looking at the docs, it seems we're forgetting how constructor functions work. In your CER_CF_PARSER_TICKET class, you need to define a constructor method CER_CF_PARSER_TICKET - otherwise I guess it's not being extended. Try that.
Real programmers don't comment their code. If it was hard to write, it should be hard to understand.
User avatar
John Cartwright
Site Admin
Posts: 11470
Joined: Tue Dec 23, 2003 2:10 am
Location: Toronto
Contact:

Post by John Cartwright »

An extended class's constructor won't be called unless you tell it to.

Code: Select all

class foo extends bar 
{
   function foo() {
      parent::bar();
   }
}
Only skimmed the thread, appologies if this is off.
kayers
Forum Newbie
Posts: 14
Joined: Tue Apr 25, 2006 9:38 am

Post by kayers »

Sorry, this post is pretty long...
After looking at the docs, it seems we're forgetting how constructor functions work. In your CER_CF_PARSER_TICKET class, you need to define a constructor method CER_CF_PARSER_TICKET - otherwise I guess it's not being extended. Try that.
Yeah, I saw that after trying it the first time and looking at the docs, so I added:

Code: Select all

function CER_CF_PARSER()
	{
		$this->CER_PARSER();
		
		//test
		$filename = "test_instantiate.txt";
		$fp = fopen($filename, "a");
		$string = "in cer_cf_parser constructor\n";
		$write = fputs($fp, $string);
		fclose($fp);
o	}

.
.
.

function CER_CF_PARSER_TICKET()
	{
		$this->CER_PARSER_TICKET();
		
		//test
		$filename = "test_instantiate.txt";
		$fp = fopen($filename, "a");
		$string = "in cer_cf_parser_ticket constructor\n";
		$write = fputs($fp, $string);
		fclose($fp);
	}
Still, nothing.

I got curious; if I added the functions back to CER_PARSER and CER_PARSER_TICKET, would get_class_methods see them there? So, I added this:

Code: Select all

function CER_PARSER()
	{
		$this->db = cer_Database::getInstance();
		
		//test
		$filename = "test_instantiate.txt";
		$fp = fopen($filename, "a");
		$string = "in cer_parser constructor\n";
		$write = fputs($fp, $string);
		
		$functions = get_class_methods('CER_PARSER');

		foreach ($functions as $val)
		{
			fwrite($fp, $val);
			fwrite($fp, "\n");
		}
		
		fwrite($fp, "\n");
		fclose($fp);
	}
.
.
.
function CER_PARSER_TICKET()
	{
		$this->db = cer_Database::getInstance();
		$this->thread_handler = new cer_ThreadContentHandler();
		
		//test
		$filename = "test_instantiate.txt";
		$fp = fopen($filename, "a");
		$string = "in cer_parser_ticket constructor\n";
		$write = fputs($fp, $string);
		
		$functions = get_class_methods('CER_PARSER_TICKET');

		foreach ($functions as $val)
		{
			fwrite($fp, $val);
			fwrite($fp, "\n");
		}
		
		fwrite($fp, "\n");
		
		fclose($fp);
	}
And I got:

Code: Select all

in cer_parser constructor
cer_parser
check_if_merged
get_ticket_id
send_autoresponse
send_closeresponse
send_gatedresponse
proxy_email_to_requesters
send_email_to_watchers
send_email_to_address
process_mail_rules
mark_ticket_customer_replied
mark_ticket_bounced
find_ticketid_in_subject
find_ticketid_from_message_id
find_ticketid_in_body
[b]find_custom_field_in_body[/b]
_validate_ticket_id
is_banned_address
perform_war_check

in cer_parser_ticket constructor
cer_parser_ticket
load_ticket_data
_get_ticket_spam_probability
generate_unique_mask
mask_is_unique
set_requester
set_queue_address_id
find_ticket_id
reset_due_date
create_new_ticket
[b]instantiate_custom_fields[/b]
cache_ticket_requesters
save_requester_link
is_ticket_requester_address
is_ticket_requester_id
is_comment_or_email
save_thread_time_worked
add_ticket_thread
_save_thread_attachments
get_dest_queue_data
_find_address_catchall_queue
_find_to_addy_in_received
is_queue_address
is_admin_address
get_address_id
They're in there! But nothing's being printed by the stubs that are in those functions! So, again I got to thinking: what if I'm doing something wrong with either 1) my function calls, 2) my file writing stubs, or 3) Cerberus itself (is it caching the function defs somewhere?)? I decided to put dummy functions into the CER_PARSER and CER_PARSER_TICKET classes:

Code: Select all

function test_parser()
	{
		$filename = "test_functions.txt";
		$fp = fopen($filename, "a");
		$string = "in test_parser\n";
		$write = fputs($fp, $string);
		fclose($fp);
	}
.
.
.

function test_parser_ticket()
	{
		$filename = "test_functions.txt";
		$fp = fopen($filename, "a");
		$string = "in test_parser_ticket\n";
		$write = fputs($fp, $string);
		fclose($fp);
	}
And I get back (... means it's the same as before)

Code: Select all

in cer_parser constructor
.
.
.
[b]test_parser[/b]
.
.
.

in cer_parser_ticket constructor
.
.
.
[b]test_parser_ticket[/b]
.
.
.
But... *drumroll please*

NOTHING'S BEING PRINTED IN THE FILE THAT'S SUPPOSE TO BE WRITTEN IN THOSE FUNCTIONS!

I'm really starting to wonder if this is a Cerberus issue rather than a PHP one, but I'm not going to assume anything, especially since I'm not too familiar with PHP. What does everyone think?
kayers
Forum Newbie
Posts: 14
Joined: Tue Apr 25, 2006 9:38 am

Post by kayers »

Thanks, Jcart! I'll try that too! :)
kayers
Forum Newbie
Posts: 14
Joined: Tue Apr 25, 2006 9:38 am

Post by kayers »

Is there any PHP reason changes to parser.php would not be recognized?
User avatar
pickle
Briney Mod
Posts: 6445
Joined: Mon Jan 19, 2004 6:11 pm
Location: 53.01N x 112.48W
Contact:

Post by pickle »

On a standard install - no. I believe you can get systems that cache page results, but I wouldn't assume that's your problem. You may also be getting cached results - it may be a browser problem.
Real programmers don't comment their code. If it was hard to write, it should be hard to understand.
Post Reply