I am trying to sort an array of values using a class method. The values are as follows
$agegroups = array("08","910","1112","1314","1516","1718","1999");
However, they can be any combination of numbers. The values above correspond to age groups used on my site and are are defined in a database table, so I can't hard code them. I have an object that contains an array of age group defintions like this
private $agegroups = array();
function __construct() {
// retrieve data from the database
while($data = $sth->fetch()) {
$ag = new StdClass();
$ag->low = $data['low']; //stores the low end of the age group
$ag->high = $data['high'] //stores the high end of the age group
$this->agegroups[$data['key']] = $ag;
}
}
$data['key'] corresponds to the $agegroups array defined above. In the same class, I defined a sort method
function sort($a,$b) {
$aAG = $this->agegroups[$a];
$bAG = $this->agegroups[$b];
return $aAG->low > $bAG->low ? 1 : -1;
}
My understanding is that usort can only use a static method. However my object needs to retrieve the values from a database, so I can't make it static.
I tried using an anonymous function with usort that could use an instance of the class defined outside the function but I get an error about an undefined object.
$agObj = new agegroups();
$agegroups = usort($agegroups, function($a, $b){
global $agObj;
return $agObj->sort($a,$b);
});
The error I get is Fatal error: Call to a member function sort() on a non-object
I release I can create a new instance of the object inside the anonymous function but I don't want to have to query the database each time. Is there a way to use my class to sort these values?
Wherever a function is required, you can use array(object, functionName) to call the method on that object.
usort($agegroups, array($agObj, 'sort'));
BTW, you shouldn't assign the result of usort back to agegroups. The sorting functions modify the array in place; they return a boolean, not the reordered array.
Related
class Test {
public function results() {
$return['first'] = 'one';
$return['second'] = 'two';
return $return;
}
}
$test = new Test;
print_r($test->results()); // Returns entire array
I just want to return a single specified element from the array, such as the value of key "second". How do I do this without sifting through the entire array after it's returned?
I just want to return a single specified element from the array, such as the value of key "second"
Pass in an argument to identify which element to return, and return that (or false if it doesn't exist - for example);
public function results($key = null)
{
$return['first'] = 'one';
$return['second'] = 'two';
// check the key exists
if (!array_key_exists($key, $return)) {
return false;
}
return $return[$key];
}
Then:
print_r($test->results('second')); // two
How do I do this without sifting through the entire array after it's returned?
It's important to note that you do not need to "sift through the entire array" to retrieve a value by its key. You know the key, so you can access it directly.
class Test {
private $arr; //private property of object
__construct(){
//create arr in constructor
$this->arr=[];//create new array
$this->arr['first'] = 'one';
$this->arr['second'] = 'two';
}
/**
/* get array
**/
public function getResults(){
return $this->arr;
}
/**
/* get single array element
**/
public function getResult($key) {
return isset($this->arr[$key])?$this->arr[$key]:null;//return element on $key or null if no result
}
}
$test = new Test();
print_r($test->getResult("second")); // Returns array element
//or second possibility but the same result
print_r($test->getResults()["second"]); // Returns array element
Few advices:
Create data structure in constructor ($arr in this particular case) because creating it on very results method call is not any kind of using objects or objective programming. Imagine that if array is created in results method then on every call new array is located in memory, this is not efficent, not optimal and gives no possibility to modify this array inside class Test.
Next in method results add parameter to get only this key what is needed and hide all array in private class property $arr to encapsulate it in object.
And last my private opinion for naming style:
Use camelCase when naming method names.
In PHP an array value can be dereferenced from the array by its key.
$arr = ["foo" => "bar", "baz" => "quix"];
echo $arr["foo"]; // gives us "bar"
echo $arr["baz"]; // gives us "quix"
If the method/function returns an array the same can be done with the return value, whether by assigning the return value to a variable and using the variable to dereference the value by key, or by using function array dereferencing.
class Test {
public function results() {
return ["foo" => "bar", "baz" => "quix"];
}
}
$test = new Test;
$arr = $test->results();
echo $arr["foo"]; // gives us "bar"
echo $arr["baz"]; // gives us "quix"
// Using FAD (Function Array Dereferencing)
echo $test->results()["foo"]; // gives us "bar"
echo $test->results()["baz"]; // gives us "quix"
Of course there are two important caveats to using function array dereferencing.
The function is executed each time you do it (i.e no memoziation)
If the key does not exist or the function returns something other than array, you get an error
Which means it's usually safer to rely on assigning the return value to a variable first and then doing your validation there for safety... Unless you are sure the function will always return an array with that key and you know you won't need to reuse the array.
In PHP 5.4 and above:
print_r($test->results()['second']);
In older versions which you shouldn't be running as they are out of security maintenance:
$results = $test->results();
print_r($results['second']);
Edit: The first example originally said 5.6 and above but array dereferencing was introduced in 5.4! For the avoidance of doubt, 5.6 is the lowest php version within security maintenance.
I have an array whose items are of a certain object type, let it be my_object.
The class defining the my_objects has a function that I want to use to filter the array. How can I specify that function when calling array_filter?
class my_class{
private $exclude;
public filter_function(){
return !$this->exclude;
}
}
$array=array($my_object1, $my_object2, ....);
$filtered=array_filter($array,'filter_function');//obviously does not work
my_object1 , my_object2 , ... are all instances of my_class and I want that the
$my_object1->filter_function()
$my_object2->filter_function()
,.....
be called for filtering the array.
If you want to filter the array based on return value of each individual object's filter_function method call, you could simply:
array_filter($array, function($obj) { return $obj->filter_function(); });
No need to clutter the original class with static methods as in Mark's answer.
You need to indicate the object as well as the method in your callback, using an array syntax as shown in the php docs for callbacks
class my_class{
private $exclude;
public filter_function(){
return !$this->exclude;
}
}
$array = array($my_object1, $my_object2, ....);
$classFilter = new my_class();
$filtered = array_filter($array,[$classFilter, 'filter_function']);
In this case, you need to create an instance first, then use that instantiated object as the first element in the callback, and the method name as the second element
EDIT
However, if you're trying to filter this collection of my_class objects based on whether individual objects have the exclude set, then you need to have a filter method for the collection:
class my_class{
private $exclude;
public filter_function(){
return !$this->exclude;
}
public static filter_collection($value){
return $value->filter_function();
}
}
$array = array($my_object1, $my_object2, ....);
$filtered = array_filter($array,['my_class', 'filter_collection']);
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.
I'm trying to understand this object but i can't figure out a simple fact. If count method shows public properties and the result is the number of keys in an array that was passed. In the case of an associative array when i try to access a key like a public property is not found. Maybe i misunderstood the interface.
//example
$currentDate = getdate();
//applying print_r() we can see the content
$objectDate = new ArrayObject();
//verifying the public properties- result is 11
$objectDate->count();
//but can't access keys like public properties
$objectDate->hours;
You can access array entries as properties (->) by passing the ArrayObject::ARRAY_AS_PROPS flag to the ArrayObject constructor:
//example
$currentDate = getdate();
print_r($currentDate);
// create ArrayObject from array, make entries accessible as properties (read and write).
$objectDate = new ArrayObject($currentDate, ArrayObject::ARRAY_AS_PROPS);
// verifying the public methods - result is 11
print_r($objectDate->count());
print "\n";
// accessing entries like public properties
print_r($objectDate->hours);
Such class implements ArrayAccess interface, so you can write:
$objectDate['hours']
With brackets notation, but not with arrow [->] one.
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().