Switch class results dynamically - php

I'm trying to write a code where I could run a function based on it's previous variables. I don't know how to explain any better but a sample will do. I'm trying to do something like this:
<?php
$agric = new Agriculture;
$newplant = $agric-> setClass('plant');
$newanimal = $agric->setClass('animal');
$agric->getAll(); // returns null
$newplant->setProperties($plant1_data); //uses plant
$newanimal->setProperties($animal1_data); // uses animal
$newplant->setProperties($plant2_data); //uses plant
$newanimal->setProperties($animal2_data); // uses animal
$newplant->getAll(); // returns all plants array
$newanimal->getAll(); // returns all animals array
$agric->getAll(); // returns both plants array and animals
?>
So, In one form, the new variables calls the setClass in order to work and everytime it is is called they use their setClass method to know which type of argument they should use to run their code. I know I could do this differently but I seem to love this approach. Any help will do. Thanks in advance

Thanks #everyone.. I finally got the answer to that. So the reason why I'm giving it to #Dragos is because phone factory seems to be the best approach to it. So, all I did was to create two classes. One is Agriculture which has a method to get the properties of what was called using "getAll()" and the Other is HandleAgric which also has "getAll()". The HandleAgric has its own setClass which is static and every time it is called, it instantiates a new Agriculture with its default parameter. So, Both Classes will have setClass() and getAll() as method. Something like this
<?php
class HandleAgric{
private static $Agriculture;
public function __construct(){
self::setClass();
}
function __call($method,$args){
$self = new self;
if(method_exists($self::$Agriculture, $method)){
$call = call_user_func(array($self::$Agriculture, $method));
return $call;
}
return trigger_error("Error Found!!! Aborting");
}
public static function setClass($class=null){
self::$Agriculture = new Agriculture;
$call = self::$Agriculture->setClass($class);
return $call;
}
}
//Example of usage
$Agric = new HandleAgric();
$Plant = $Agric::setClass("plant");
$Animal = $Agric::setClass("animal");
$Plant->setProperties($arrayList);
$Animal->setProperties($arrayList);
# $Plant->getAll() //return plants properties in array;
# $Animal->getAll() //return Animal properties in array;
# $Agric->getAll() //return Agric (both plant and animal) properties in array;
?>
I believe this to be much better.

For your example to work, the method setClass from Agriculture must work like a factory: it instantiates a class based on the parameter and returns the object.
Agriculture class must also keep all the objects instantiated inside setClass method in its own internal array, so when getAll method is called, it iterates through each object and executes their own getAll methods.

Related

What is the difference in this way of method calling

As I got it, in the first example an object is created, and in the second one I don't see an object created. I am trying to understand, what is the difference between the two ways of method calling :
<?php
class Animal{
public $voice;
public function speak($sound){
echo $this->voice = $sound;
}
}
// Example 1
$tiger = new Animal();
$tiger->speak('Roar');
// Example 2
(new Animal)->speak("Cloak Cloak");
Whenever you use "new", you're creating an instance of an object (it can be temporary). The difference in your code is that in the first example, you're storing the instance in "$tiger", so it'll persist, but in the second example you're only instantiating a temporary object to call a method.
In the first example, you are assigning the variable $tiger as a new Object, by which you can then call the functions and variables associated with that object, by referencing $tiger.
i.e. as Tiger now equals an Object of Class Animal, it can speak.
However in the second example, you are still creating a new Object of class Animal, and as such it can speak - but you have not assigned it to a variable. So you cannot reference that same Object any longer.
So in the first example, if we wanted to name our $tiger, we could have the Class look something like this.
class Animal{
public $voice;
public $name = "I have no name.";
public function speak($sound){
echo $this->voice = $sound;
}
public function sayYourName(){
echo $this->name;
}
}
Now if we say,
$tiger = new Animal();
$tiger->speak('Roar');
$tiger->name = "Rory";
$tiger->sayYourName(); // This will echo "Rory"
However, if you try your second example instead :
(new Animal)->sayYourName(); // This will echo "I have no name."
So if you say :
(new Animal)->name = "Rory";
(new Animal)->sayYourName(); // This will still echo "I have no name".
This is because we haven't assigned a reference to the new animal, so while we can access methods of the function, and even predefined variables, we can't then reference them again later on.
To do that, we should stick to the first method (i.e. referencing)
$tiger = new Animal();
$tiger->name = "Rory";
$tiger->sayYourName();
In conclusion, use referencing to refer to an Object later on. i.e to get the animals attention, you have to call it by its name.

How can I make an array of type "class" in PHP?

I have the following class with several properties and a method in PHP (This is simplified code).
class Member{
public $Name;
public $Family;
public function Fetch_Name(){
for($i=0;$i<10;$i++){
$this[$i]->$Name = I find the name using RegExp and return the value to be stored here;
$this[$i]->Family = I find the family using RegExp and return the value to be stored here;
}
}//function
}//class
In the function Fetch_Name(), I want to find all the names and families that is in a text file using RegExp and store them as properties of object in the form of an array. But I don't know how should I define an array of the Member. Is it logical or I should define StdClass or 2-dimension array instead of class?
I found slightly similar discussion here, but a 2 dimensional array is used instead of storing data in the object using class properties.
I think my problem is in defining the following lines of code.
$Member = new Member();
$Member->Fetch_name();
The member that I have defined is not an array. If I do define it array, still it does not work. I did this
$Member[]= new Member();
But it gives error
Fatal error: Call to a member function Fetch_name() on a non-object in
if I give $Member[0]= new Member() then I don't know how to make $Member1 or Member[2] or so forth in the Fetch_Name function. I hope my question is not complex and illogical.
Many thanks in advance
A Member object represents one member. You're trying to overload it to represent or handle many members, which doesn't really make sense. In the end you'll want to end up with an array that holds many Member instances, not the other way around:
$members = array();
for (...) {
$members[] = new Member($name, $family);
}
Most likely you don't really need your Member class to do anything really; the extraction logic should reside outside of the Member class, perhaps in an Extractor class or something similar. From the outside, your code should likely look like this:
$parser = new TextFileParser('my_file.txt');
$members = $parser->extractMembers();
I think you should have two classes :
The first one, Fetcher (or call it as you like), with your function.
The second one, Member, with the properties Name and Family.
It is not the job of a Member to fetch in your text, that's why I would make another class.
In your function, do your job, and in the loop, do this :
for($i = 0; $i < 10; ++$i){
$member = new Member();
$member->setName($name);
$member->setFamily($family);
// The following is an example, do what you want with the generated Member
$this->members[$i] = $member;
}
The problem here is that you are not using the object of type Member as array correctly. The correct format of your code would be:
class Member{
public $Name;
public $Family;
public function Fetch_Name(){
for($i=0;$i<10;$i++){
$this->Name[$i] = 'I find the name using RegExp and return the value to be stored here';
$this->Family[$i] = 'I find the family using RegExp and return the value to be stored here';
}
}
}
First, $this->Name not $this->$Name because Name is already declared as a member variable and $this->Name[$i] is the correct syntax because $this reference to the current object, it cannot be converted to array, as itself. The array must be contained in the member variable.
L.E: I might add that You are not writing your code according to PHP naming standards. This does not affect your functionality, but it is good practice to write your code in the standard way. After all, there is a purpose of having a standard.
Here you have a guide on how to do that.
And I would write your code like this:
class Member{
public $name;
public $family;
public function fetchName(){
for($i=0;$i<10;$i++){
$this->name[$i] = 'I find the name using RegExp and return the value to be stored here';
$this->family[$i] = 'I find the family using RegExp and return the value to be stored here';
}
}
}
L.E2: Seeing what you comented above, I will modify my answer like this:
So you are saying that you have an object of which values must be stored into an array, after the call. Well, after is the key word here:
Initialize your object var:
$member = new Memeber();
$memebr->fechNames();
Initialize and array in foreach
$Member = new Member();
foreach ($Member->Name as $member_name){
$array['names'][] = $member_name;
}
foreach ($Member->Family as $member_family) {
$array['family'][] = $member_family;
}
var_dump($array);
Is this more of what you wanted?
Hope it helps!
Keep on coding!
Ares.

PHP combine $this variable

How to combine two variables to obtain / create new variable?
public $show_diary = 'my';
private my_diary(){
return 1;
}
public view_diary(){
return ${"this->"}.$this->show_diary.{"_diary()"}; // 1
return $this->.{"$this->show_diary"}._diary() // 2
}
both return nothing.
Your class should be like following:
class Test
{
public $show_diary;
function __construct()
{
$this->show_diary = "my";
}
private function my_diary(){
return 707;
}
public function view_diary(){
echo $this->{$this->show_diary."_diary"}(); // 707
}
}
It almost looks from your question like you are asking about how to turn simple variables into objects and then how to have one object contain another one. I could be way off, but I hope not:
So, first off, what is the differnce between an object and a simple variable? An object is really a collection of (generally) at least one property, which is sort of like a variable within it, and very often functions which do things to the properties of the object. Basically an object is like a complex variable.
In PHP, we need to first declare the strucutre of the object, this is done via a class statement, where we basicaly put the skeleton of what the object will be into place. This is done by the class statement. However, at this point, it hasn't actually been created, it is just like a plan for it when it is created later.
The creation is done via a command like:
$someVariable= new diary();
This executes so create a new variable, and lays it out with the structure, properties and functions defined in the class statement.
From then on, you can access various properties or call functions within it.
class show_diary
{
public $owner;
public function __construct()
{
$this->owner='My';
}
}
class view_diary
{
public $owner;
public $foo;
public function __construct()
{
$this->foo='bar';
$this->owner=new show_diary();
}
}
$diary= new view_diary();
print_r($diary);
The code gives us two classes. One of the classes has an instance of the other class within it.
I have used constructors, which are a special type of function that is executed each time we create a new instance of a class - basically each time we declare a variable of that type, the __construct function is called.
When the $diary= new view_diary(); code is called, it creates an instance of the view_diary class, and in doing so, the first thing it does is assigns it's own foo property to have the value 'bar' in it. Then, it sets it's owner property to be an instance of show_diary which in turn then kicks off the __construct function within the new instance. That in turn assigns the owner property of the child item to have the value 'My'.
If you want to access single properties of the object, you can do so by the following syntax:
echo $diary->foo;
To access a property of an object inside the object, you simply add more arrows:
echo $diary->owner->owner;
Like this?
$diary = $this->show_diary . '_diary';
return $this->$diary();

Php sub-methods

I've used php enough to be quite comfortable with it, but recently I've been looking through some MVC frameworks to try and understand how they work, and I've come across a syntax and data structure which I haven't encountered before:
function view($id)
{
$this->Note->id = $id;
}
What is the ->id section of this code? Is this a sub-method based off it's parent method? If so, how do I go about writing code to create such a structure? (ie. creating the structure from scratch, not using an existing framework like the above example from cakephp).
The following code demonstrates how one could arrive at the structure you described.
<?php
class Note
{
public $id = 42;
}
class MyClass
{
public function __construct() {
// instance of 'Note' as a property of 'MyClass'
$this->Note = new Note();
}
public function test() {
printf("The \$id property in our instance of 'Note' is: %d\n",
$this->Note->id);
}
}
$mc = new MyClass();
$mc->test();
?>
Note is a property of $this and it's (current) value is an object with a property named id which gets assigned the value of $id.
If id was a method of the Note object, the line would read $this->Note->id($id);.
Another way to think about the construct is considering
$this->Note->id = $id;
similar to
$this["Note"]["id"] = $id;
Which would actually be equivalent if both objects ($this and subobject Note) were based on ArrayAccess.

Is it bad practice to construct a child class with a parent object?

I have a search class that I am using to fetch results from two different sources and combine them together. The Search class is the parent and has two children A and B which extend Search.
In the Search class, I have a method called fetch() which instantiates the two child objects to get their results. It looks something like this:
public function fetch(){
$a = new A($this);
$a_results = $a->fetch();
$b = new B($this);
$b_results = $b->fetch();
// code to combine the results here
}
The constructor of class A and B both look like this:
class A extends Search
{
public function __construct(Search $search){
parent::__construct($search->category, $search->offset, $search->keywords...);
}
It feels like I'm doing something wrong in that I'm passing a parent object to a child and then creating another parent object with the exact same data. Is there a better way to set this up?
I have it set this way because some parts of my application need to access class A and B directly, rather than through the parent Search class.
Use composition, for example have the Search class to have an array of sources, where each source is an instance of a Source class where you define what's common to a source and pass the parameters for each A and B sources.
The idea here, in case it's not clear, is for the Source class to return the data from the sources and let the Search class do the search. How practical or efficient this is depends on the actual source and way of searching
class Search {
private $sources = array();
public Search($p1,$p2,$p3,$p4) {
//Use proper parameters to define the sources
$sources[] = new Source("A",$p1,$p2,$p3,$p4);
$sources[] = new Source("B",$p1,$p2,$p3,$p4);
}
public function fetch() {
foreach ($source in $sources) {
$results[] = $source->fetch();
}
combine($results);
}
}
class Source {
//Whatever you need to define the source
public function fetch() {
//Fetch from the proper source
}
public Source($name,$p1,$p2,$p3,$p4) {
//Store the parameters to be able to operate
}
}

Categories