Right now, I have this code where $obj_arr maybe contain array and an object.
$obj_temp = array ($obj_identity, $arr_user, $obj_locale, $arr_query);
foreach ($obj_temp as $maybe_arr) {
if (is_array($maybe_arr)) :
$name = (string) key($maybe_arr);
if (is_object($maybe_arr)) :
???? // how to retrieve a class name ?
endif;
$obj_arr[$name] = $maybe_arr;
}
obj_will_be_extract($obj_arr);
function obj_will_be_extract($obj_arr) {
extract($obj_arr);
//Do the rest
}
I need to create an array consist of combination of objects and arrays. Cause I need to extract it, then how to get an object name?
Use get_class to get the class name of an object.
Since PHP 5.5 you can use MyAction::class statement, so you can get a class name without class initialization
Related
I have a file which consist of user defined functions with CamelCase names :
// some useful comments
function functionOne(){
return false;
}
// some other useful comment
function addTwoNumbers($x,$y)
{
return 5;
}
...
I would like to output these functions sorted by name like
addTwoNumbers($x,$y)
2 parameters
Comment: some other useful comment
functionOne()
0 parameters
Comment: some useful comments
So far, I get a list of function names like this:
include '../includes/functions.php';
$allFunctions = get_defined_functions();
$userFunctions = $allFunctions['user'];
sort($userFunctions);
foreach ($userFunctions as $functionName) {
echo $functionName. "<br>";
}
My main problem is that I do not know how to display the number of parameters of each function and the parameter variable names.
Further (but I could live with it) the function names are only displayed with lower case letters, so I can't read them in CamelCase.
And finally the comments are of course not shown. I was thinking of writing them in an array $comments['functionOne']="some useful comments".
So my main problem is how do you get the parameter variable names and number.
To get paramater number and names, you can use Reflection in PHP :
function getFunctionArgumentNames($functionName) {
$reflection = new ReflectionFunction($functionName);
$argumentNames= array();
foreach ($reflection ->getParameters() as $parameter) {
$argumentNames[] = $parameter->name;
}
return $argumentNames;
}
Then you'll have your parameter names, and the length of the returned array will give you how many there are.
More information can be found about it :
ReflectionClass
ReflectionObject
What is Reflection in PHP ?
Another common use of Reflection is for creating documentation. It would be extremely labour intensive to write documentation about every method of every class of a large framework or application. Instead, Reflection can automatically generate the documentation for you. It does this by inspecting each method, constructor and class to determine what goes in and what comes out.
Use ReflectionFunction class
for example:
$refFunc = new ReflectionFunction('preg_replace');
foreach( $refFunc->getParameters() as $param ){
print $param;
}
The ReflectionFunction class reports information about a function.
See more http://php.net/manual/en/class.reflectionfunction.php
I'm writing a method that copies an object. Instead of manually setting each property manually, it would be more robust to just loop over the original object's properties...
//Booo
$new->name = $old->name;
$new->color = $old->color;
...
//Oh yeah...
foreach ($old as $prop=>$val){
$new->$prop = $val;
}
unset $new->id;
It appears that CakePHP entities cannot be iterated over in this way. I tried using $old->toArray(), which basically works... but has the drawback of converting all the associations to arrays also, which is screwing this up for me down stream.
How do I loop over the $old properties without converting all the data types?
Update:
Mark brought to my attention the existence of a __clone() method. Sounds like it does exactly what I need but I'm still figuring out how to use it.
You can use $entity->visualProperties()
foreach($old->visualProperties() as $property) {
if($new->has($property))
$new->set($property, $old->get($property));
After looking at this for a while, and discovering there is no __clone() function for entities, at least in 3.8, I have worked out how to do it, with the hint from DouglasSantos :
//Find out the entity classname
$classname = get_class($entity);
//Instanciate a new object of that class
$clone = new $classname;
//Use visibleProperties to clone it
foreach($entity->visibleProperties() as $property)
if($clone->has($property))
$clone->set($property, $entity->get($property));
Of course you could combine the first 2 lines into one line, but I have split it out for clarity.
UPDATE: I have discovered if you use the has->($property) check it will skip many of the fields. So the corrected answer is :
//Find out the entity classname
$classname = get_class($entity);
//Instanciate a new object of that class
$clone = new $classname;
//Use visibleProperties to clone it
foreach($entity->visibleProperties() as $property)
$clone->$property = $entity->$property;
It is actually much easier to use the Table Object:
// Assuming your model is called "Documents"
// If you are in the Controller, you can just use `$this->Documents`
instead of fetching the Table from the Registry
use Cake\ORM\TableRegistry;
$table = TableRegistry::getTableLocator()->get('Documents');
// newEntity() creates a new Entity from an array of data
$documentCopy = $table->newEntity(
// extract() extracts the given properties as an associative array
$document->extract(
// getVisible() will get all visible properties as an array
$document->getVisible()
)
);
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.
Is it possible to access object's properties, when you don't know just how their names will be written?
My problem is that when a query returns Zend_Db_Table_Rowset_Abstract object, there are some fields with names like "name_fr", "name_en", "name_au". I want to access either of them according to the current language used in the application. To achieve this I write the code this way:
$result = $myModel->fetchAll($query)->current();
$row = $result->toArray();
echo 'Your name is '.$row['name_'.$language];
This is very annoying. Is it possible to write a code like this for example:
$result = $myModel->fetchAll($query)->current();
echo 'Your name is '.$result->name_{$language};
This should work:
$result = $myModel->fetchAll($query)->current();
echo 'Your name is '.$result->{'name_'.$language};
When you use Zend_Db_Table and fetchAll()->current(), type of returned object is Zend_Db_Table_Row, which inherits from Zend_Db_Table_Row_Abstract. Zend_Db_Table_Row_Abstract implements ArrayAccess(manual) interface, which means you can refer to object properties using array key notation.
So, syntax:
'Your name is '.$row['name_'.$language];
should work without using toArray();
Try this:
$result->{"name_$language"}
I need to initialize an array of objects in PHP.
Presently I have the following code:
$comment = array();
And when i am adding an element to the array
public function addComment($c){
array_push($this->comment,$c);
}
Here, $c is an object of class Comment.
But when I try to access an functions of that class using $comment, I get the following error:
Fatal error: Call to a member function
getCommentString() on a non-object
Can anyone tell me how to initialize an array of objects in php?
Thanks
Sharmi
$this->comment = array();
Looks like a scope problem to me.
If $comments is a member of a class, calling $comments inside a function of that class will not actually use the member, but rather use an instance of $comments belonging to the scope of the function.
If other words, if you are trying to use a class member, do $this->comments, not just $comments.
class foo
{
private $bar;
function add_to_bar($param)
{
// Adds to a $bar that exists solely inside this
// add_to_bar() function.
$bar[] = $param;
// Adds to a $bar variable that belongs to the
// class, not just the add_to_bar() function.
$this->bar[] = $param;
}
}
This code might help you:
$comments = array();
$comments[] = new ObjectName(); // adds first object to the array
$comments[] = new ObjectName(); // adds second object to the array
// To access the objects you need to use the index of the array
// So you can do this:
echo $comments[0]->getCommentString(); // first object
echo $comments[1]->getCommentString(); // second object
// or loop through them
foreach ($comments as $comment) {
echo $comment->getCommentString();
}
I think your problem is either how you are adding the objects to the array (what is $this->comment referencing to?) or you may be trying to call ->getCommentString() on the array and not on the actual objects in the array.
You can see what's in the array by passing it to print_r():
print_r($comment);
Presuming you have Comment objects in there, you should be able to reference them with $comment[0]->getCommentString().