Classes and Functions

I have 2 classes, Results_Parser, and Engine_Data.
The Results_Parser class will take some data and parse it out into usable data formats.  One of the data formats is form_data.  The Engine_Data class has a need to access the information in Results_Parser->form_data.  This is done using a function inside of Engine_Data, called get_engine_hits.  How can I get the class Engine_Data to look at something in Results_Parser->form_data?

Caveats:  Cannot instantiate Results_Parser in Engine_Data, it's not relevant.
Do not want to have to instantiate Engine_Data inside Results_Parser, the code will get unnecessarily convoluted that way.  It is the simple matter of being able to pass data from one class to the other.

Additional info:  Results_Parser->form_data may or may not exist.  What I need it the function insdie of Engine_Data to do is to check if Results_Parser->form_data exists.  If it does, then to use it.  If not, then to use other data NOT generated within Results_Parser.
mcogan1966Asked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

shmertCommented:
You should pass an Engine_Data object BY REFERENCE to a method in Results_Parser.  This method will set the form_data in the Engine_Data object.
mcogan1966Author Commented:
I don't understand how to do that.
If Results_Parser is instantiated, it is done BEFORE Engine_Data.
Otherwise, Results_Parser will not be instantiated at all.
class Results_Parser {
.
.
   function do_something() {
.
    }
}

class Engine_Data {
    function something done() {
// if Results_Parser::do_something() exists, give me the output
    }
}

Does this make any sense?
shmertCommented:
It looks like you're using static method calls, instead of actually instantiating the objects in question.  Here's how I  picture the code working:

class Results_Parser {
.
.
   function parse_results(&$engine_data) {
        $data = array(1,2,3,4,5); // this is the parsed data
        $engine_data->setEngineHits($data[1]);
    }
}

class Engine_Data {
}

$parser = new Results_Parser();
$data = new Engine_Data();
$parser->parse_results($data);
print_r($data);
Exploring SQL Server 2016: Fundamentals

Learn the fundamentals of Microsoft SQL Server, a relational database management system that stores and retrieves data when requested by other software applications.

shmertCommented:
If this doesn't help, can you give me a more concrete example of what these classes are doing?
mcogan1966Author Commented:
I got a different idea from talking to someone else.  How about I have Results_Parser extend Engine_Data?

class Results_Parser extends Engine_Data {
        function do_something() {
        return $out;
        }
}

class Engine_Data {
         function something_done() {
// How do I tell here if Results_Parser->do_something() gave me anything in $out?
         }
}

This should help things along, but I'm not quite sure where to go from here.  I still need to know what the syntax is to get Engine_Data to know what Results_Parser->do_something() returned.
         
mcogan1966Author Commented:
Actually, with this layout, it is probably that the only class that will be instantiated will be Results_Parser.  Since it extends Engine_Data, won't it also instantiate when Results_Parser is?

If so, then I can reference functions in either by the same handle, right?
mcogan1966Author Commented:
$parser = new Results_Parser();
$data = new Engine_Data();
$parser->parse_results($data);
print_r($data);

...is incorrect.

Results_Parser is NOT parsing any data from Engine_Data.
They are 2 seperate classes, each with their own functionality.
However, it has been determined that Engine_Data needs some input from one small part of Results_Parser.  Hence the function "do_something()".  It was determined that Engine_Data is the core class, and that it is relevant to everything else going on.  By extending Results_Parser from Engine_Data, it is hoping that we can call just Engine_Data if we like, or call Results_Parser and get Engine_Data with it when we need.
shmertCommented:
Try to explain what these 2 classes _do_.  I think explaining it in some more detail would help.

What does results_parser parse?
What does an egine_data instance represent?
What attributes do both classes have?
What methods?
shmertCommented:
In my code

$parser = new Results_Parser();
$data = new Engine_Data();
$parser->parse_results($data);
print_r($data);


The parser isn't parsing data in the engine, it is setting an attribute in engine_data with the result of the data that it parses (from somewhere else)

I think subclassing is a bad idea, since you seem concerned about maintaining a good semantic OOP hierarchy and separation.
mcogan1966Author Commented:
No, it doesn't.
You are passing $data, which is instance of Engine_Data() into $parser, which is an instance of Results_Parser().  That is NOT what I am trying to do.

And no, extending / subclassing is NOT a bad idea, it is exactly what this code needs to be doing.  Just because you don't want to write you code that way doesn't make this wrong.  You are assuming too much about the code, and not focusing on the specifics of the question.

My ONLY concern, and I will repeat it one more time for you, is to find a way to get Engine_Data->something_done() to know what is returned from Results_Parser->do_something().  Nothing else in either of these 2 classes has anything to do with each other.  Since the Engine_Data object is crucial to all the code, extending Results_Parser off of it for when it is needed is the correct solution.  Not all cases will require Results_Parser to be instantiated, but all cases will require Engine_Data.  Since Engine_Data needs to know IF Results_Parser->do_something() has occured, then having some code like

if(function_exists('Results_Parser->do_something()') {...}

will tell me that we did in fact instantiate Results_Parser.  If so, then I want the output from Results_Parser->do_something().  Nothing more.
mcogan1966Author Commented:
It should be noted for the record that each class does have a instance function that does get called when the class is instantiated.  So, there is a Results_Parser function in the Results_Parser class.  Same with Engine_Data.
shmertCommented:
That's an unusual approach to subclassing, given that you stated several times that these classes have nothing to do with each other.  Usually a subclass is like a more specific type of its parent class.

e.g.
class Person {
    function firstName() {}
    function lastName() {}
}

class Student extends Person {
    function gradeLevel() {}
}

class Teacher extends Person {
    function degree()
}

I think if you could explain a little better what the classes you are architecting do (besides the fact that they have nothing to do with each other) then the simple act of describing them might make apparent a solution that wasn't apparent before.  However, I am beginning to doubt that you will do so.  Without more information I cannot help you, sorry.
mcogan1966Author Commented:
Then think of it in this relationship, Engine_Data 'may have' Results_Parser.  I guess in this case, it would be a 'has a' relationship, sort of.  Perhaps, instead of subclassing, I should consider instantiating Engine_Data inside Results_Parser?  In that case Results_Parser would have Engine_Data, or we can get Engine_Data on it's own elsewhere.
shmertCommented:
Sounds good!

Something like this?

class Engine_Data {
    var $parser
    function engine_data() {
        // constructor stuff here...
    }

    function &getParser() {
        // lazy initialization of the results_parser object,
        // it is not created until needed, after which the
        // same object is reused.
        if (!$this->parser) { $this->parser =& new Results_Parser(); }
        return $this->parser;
    }
    function setParser(&$parser) {
        // explicitly set the parser object which is to be used
        $this->parser =& $parser;
    }
}

You can use the "lazy initialization" pattern above, instead of "if(function_exists('Results_Parser->do_something()') {...}"
Always try to get in the habit of passing objects using the reference assignment (&)

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
mcogan1966Author Commented:
Basically, that's what I did.
I took Engine_Data, and DID instantiate Results_Parser inside it.
I just set up Results_Parser to hold off doing some things based on some more input.  I can now call a method inside Results_Parser by reference within the instance of Engine_Data.
mcogan1966Author Commented:
And of course, that all got changed the minute I had it worked out.
So, now I am having Result extend Engine, and making an instance of the Engine constructor within Result.  Why?  Because that's the way the lead tech wanted it done.
Oh well.  At least the code all works now.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
PHP

From novice to tech pro — start learning today.