PHP: Search objects in an array - php

Let's say I have an array of objects.
<?php
$people = array();
$people[] = new person('Walter Cook');
$people[] = new person('Amy Green');
$people[] = new person('Irene Smith');
How can I search an object in this array for a certain instance variable? For example, let's say I wanted to search for a person object with the name of "Walter Cook".
Thanks in advance!

It depends of the person class construction, but if it has a field name that keeps given names, you can get this object with a loop like this:
for($i = 0; $i < count($people); $i++) {
if($people[$i]->name == $search_name) {
$person = $people[$i];
break;
}
}

Here is:
$requiredPerson = null;
for($i=0;$i<sizeof($people);$i++)
{
if($people[$i]->name == "Walter Cook")
{
$requiredPerson = $people[$i];
break;
}
}
if($requiredPerson == null)
{
//no person found with required property
}else{
//person found :)
}
?>

Assuming that name is a public property of the person class:
<?php
// build the array of objects
$people = array();
$people[] = new person('Walter Cook');
$people[] = new person('Amy Green');
$people[] = new person('Irene Smith');
// search name
$searchName = 'Walter Cook';
// ascertain the presence of the name in the array of objects
$isMatch = false;
foreach ($people as $person) {
if ($person->name === $searchName) {
$isMatch = true;
break;
}
}
// alternatively, if you want to return all matches into
// a new array of $results you can use array_filter
$result = array_filter($people, function($person) use ($searchName) {
return $person->name === $searchName;
});
hope this helps :)

well you could try this inside your class
//the search function
function search_array($array, $attr_name, $attr_value) {
foreach ($array as $element) {
if ($element -> $attr_name == $attr_value) {
return TRUE;
}
}
return FALSE;
}
//this function will test the output of the search_array function
function test_Search_array() {
$person1 = new stdClass();
$person1 -> name = 'John';
$person1 -> age = 21;
$person2 = new stdClass();
$person2 -> name = 'Smith';
$person2 -> age = 22;
$test = array($person1, $person2);
//upper/lower case should be the same
$result = $this -> search_array($test, 'name', 'John');
echo json_encode($result);
}

Related

Convert an object to an array and remove its default values

I have this class :
class MyObject{
var $title = null;
var $description = null;
var $items = [];
var $metas = [];
var $image = null;
var $country = 'Belgium';
}
And this data :
$data = new MyObject();
$data->title = 'NEW ITEM';
$data->children = ['CHILD1','CHILD2'];
$data->image = 'image.gif';
$data->country = 'Belgium';
Before storing my data in my database, I would like to remove all the defaults values from the datas, and get this output:
$dataToStore = array(
'title'=>'NEW ITEM',
'children'=>['CHILD1','CHILD2'],
'image'=>'image.gif'
);
I made an attempts with
$blank = new MyObject();
$defaults = (array)$blank;
$dataToStore = array_diff((array)$data, (array)$blank);
But it doesn't work since I get an Array to string conversion.
How could I do ?
Thanks !
Try this:
class MyObject {
public $title = null;
public $description = null;
public $children = [];
public $metas = [];
public $image = null;
public $country = 'Belgium';
protected $default = [];
function getDefault()
{
$reflect = new ReflectionClass(__CLASS__);
$vars = $reflect->getProperties(ReflectionProperty::IS_PUBLIC);
$default = [];
foreach ($vars as $privateVar) {
$default[$privateVar->getName()] = $this->{$privateVar->getName()};
}
return $default;
}
}
$data = new MyObject();
$one = $data->getDefault();
$data->title = 'NEW ITEM';
$data->children = ['CHILD1','CHILD2'];
$data->image = 'image.gif';
$data->country = 'Belgium';
$two = $data->getDefault();
echo '<pre>';
print_r($one);
print_r($two);
$output = [];
foreach($one as $key => $value){
if($value != $two[$key]){
$output[$key] = $two[$key];
}
}
print_r($output);
We get default values and set in $one
After set new data, we get default values and set in $two
Then, we check which key is not changed
First of all. Imagine that you use this class everytime you want to create a Movie entry. (I put this example because your class is very general).
class Movie{
var $title = null;
var $description = null;
var $items = [];
var $metas = [];
var $image = null;
var $country = 'Belgium';
}
Every time you want to create a new Movie record, for database or any other thing (how well have you done before).
You can create a new object.
$movie1 = new Movie();
$movie1->title = 'NEW ITEM';
$movie1->children = ['CHILD1','CHILD2'];
$movie1->image = 'image.gif';
$movie1->country = 'Belgium';
And then, if you need another one, you just have to instantiate a new object (which by default are already initialized; that's what class constructors are for) Well, we don't have a constructor here yet, but now we'll add it later
$movie1 = new Movie();
$movie1->title = 'Another title';
$movie1->items = ['SOME','ITEMS'];
$movie1->metas = ['SOME', 'METAS'];
$movie1->image = 'image.gif';
$movie1->country = 'Belgium';
$movie1->description = "Some description";
// tehere is no need for emtpy
$movie2 = new Movie();
$movie2->title = 'Title movie 2';
$movie2->items = ['SOME','ITEMS', 'MOVIE2'];
$movie2->metas = ['SOME', 'METAS', 'MOVIE"'];
$movie2->image = 'image2.gif';
$movie2->country = 'France';
$movie1->description = "Another description";
$movie1 and $movie2 now are different objects with different data.
But let's make it even better:
<?php
class Movie{
var $title;
var $description;
var $items;
var $metas;
var $image;
var $country;
function __construct($title, $description, $items, $metas, $image, $country) {
$this->title = $title;
$this->description = $description;
$this->items = $items;
$this->metas = $metas;
$this->image = $image;
$this->country = $country;
}
function GetClassVars() {
return array_keys(get_class_vars(get_class($this)));
}
}
$movie1 = new Movie("Ttile one",
"the description",
['SOME','ITEMS'],
['SOME', 'METAS'],
"image.gif",
"Belgium");
$movie2 = new Movie("Ttile two",
"the description of two",
['SOME','ITEMS', 'MORE'],
['SOME', 'METAS', 'AND MORE'],
"image2.gif",
"France");
PrintMovie($movie1);
PrintMovie($movie2);
function PrintMovie($object){
echo "#############################";
$class_vars = $object->GetClassVars();
foreach ($class_vars as $nombre) {
$val = $object->{$nombre};
if(gettype($val) == "array"){
foreach($val as $v){
echo "<pre>";
echo "\t$nombre ->";
echo " " .$v;
echo "</pre>";
}
}
else{
echo "<pre>";
echo "$nombre -> $val";
echo "</pre>";
}
}
echo "#############################\n";
}
As you are seeing in the example. I am creating two different movies (without having to delete the data each time; the constructor takes care of that, to initialize the data each time)
You also have an array with all the names of the properties of the class. In order to iterate over them and print them on the screen. You could even modify its value, since, like the PrintMovie function (it could also be called GetMovieData, if we wanted to modify it instead of printing the value)
The result of
PrintMovie($movie1);
PrintMovie($movie2);
is:
#############################
title -> Ttile one
description -> the description
items -> SOME
items -> ITEMS
metas -> SOME
metas -> METAS
image -> image.gif
country -> Belgium
############################# #############################
title -> Ttile two
description -> the description of two
items -> SOME
items -> ITEMS
items -> MORE
metas -> SOME
metas -> METAS
metas -> AND MORE
image -> image2.gif
country -> France
#############################
As you can see we have not had to delete anything and we have all the names of the properties in an array, to access them dynamically (as long as we have the object). That's why we pass it to the PrintMovie function
We could have put the print function inside the class, but I think it is also understood that way. In any case, I have invented the example so that you understand that with object-oriented programming, each object is different, therefore you do not have to delete anything to reuse it. You simply create a new object.

output and call array from class function (rollingcurl)

Excuse my English, please.
I use Rollingcurl to crawl various pages.
Rollingcurl: https://github.com/LionsAd/rolling-curl
My class:
<?php
class Imdb
{
private $release;
public function __construct()
{
$this->release = "";
}
// SEARCH
public static function most_popular($response, $info)
{
$doc = new DOMDocument();
libxml_use_internal_errors(true); //disable libxml errors
if (!empty($response)) {
//if any html is actually returned
$doc->loadHTML($response);
libxml_clear_errors(); //remove errors for yucky html
$xpath = new DOMXPath($doc);
//get all the h2's with an id
$row = $xpath->query("//div[contains(#class, 'lister-item-image') and contains(#class, 'float-left')]/a/#href");
$nexts = $xpath->query("//a[contains(#class, 'lister-page-next') and contains(#class, 'next-page')]");
$names = $xpath->query('//img[#class="loadlate"]');
// NEXT URL - ONE TIME
$Count = 0;
$next_url = "";
foreach ($nexts as $next) {
$Count++;
if ($Count == 1) {
/*echo "Next URL: " . $next->getAttribute('href') . "<br/>";*/
$next_link = $next->getAttribute('href');
}
}
// RELEASE NAME
$rls_name = "";
foreach ($names as $name) {
$rls_name .= $name->getAttribute('alt');
}
// IMDB TT0000000 RLEASE
if ($row->length > 0) {
$link = "";
foreach ($row as $row) {
$tt_info .= #get_match('/tt\\d{7}/is', $doc->saveHtml($row), 0);
}
}
}
$array = array(
$next_link,
$rls_name,
$tt_info,
);
return ($array);
}
}
Output/Return:
$array = array(
$next_link,
$rls_name,
$tt_info,
);
return ($array);
Call:
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
function get_match($regex, $content, $pos = 1)
{
/* do your job */
preg_match($regex, $content, $matches);
/* return our result */
return $matches[intval($pos)];
}
require "RollingCurl.php";
require "imdb_class.php";
$imdb = new Imdb;
if (isset($_GET['action']) || isset($_POST['action'])) {
$action = (isset($_GET['action'])) ? $_GET['action'] : $_POST['action'];
} else {
$action = "";
}
echo " 2222<br /><br />";
if ($action == "most_popular") {
$popular = '&num_votes=1000,&production_status=released&groups=top_1000&sort=moviemeter,asc&count=40&start=1';
if (isset($_GET['date'])) {
$link = "https://www.imdb.com/search/title?title_type=feature,tv_movie&release_date=,".$_GET['date'].$popular;
} else {
$link = "https://www.imdb.com/search/title?title_type=feature,tv_movie&release_date=,2018".$popular;
}
$urls = array($link);
$rc = new RollingCurl([$imdb, 'most_popular']); //[$imdb, 'most_popular']
$rc->window_size = 20;
foreach ($urls as $url) {
$request = new RollingCurlRequest($url);
$rc->add($request);
}
$stream = $rc->execute();
}
If I output everything as "echo" in the class, everything is also displayed. However, I want to call everything individually.
If I now try to output it like this, it doesn't work.
$stream[0]
$stream[1]
$stream[3]
Does anyone have any idea how this might work?
Thank you very much in advance.
RollingCurl doesn't do anything with the return value of the callback, and doesn't return it to the caller. $rc->execute() just returns true when there's a callback function. If you want to save anything, you need to do it in the callback function itself.
You should make most_popular a non-static function, and give it a property $results that you initialize to [] in the constructor.. Then it can do:
$this->results[] = $array;
After you do
$rc->execute();
you can do:
foreach ($imdb->results as $result) {
echo "Release name: $result[1]<br>TT Info: $result[2]<br>";
}
It would be better if you put the data you extracted from the document in arrays rather than concatenated strings, e.g.
$this->$rls_names = [];
foreach ($names as $name) {
$this->$rls_names[] = $name->getAttribute('alt');
}
$this->$tt_infos = [];
foreach ($rows as $row) {
$this->$tt_infos[] = #get_match('/tt\\d{7}/is', $doc->saveHtml($row), 0);
}
$this->next_link = $next[0]->getAttribute('href'); // no need for a loop to get the first element of an array

PHP String in Array returns only first charachter

I have a php function to display a list of revslider's sliders (wp plugin), the string returns only the first letter of the sliders' names
here is my code :
function jobboard_revslider(){
if (class_exists('RevSlider')) {
$theslider = new RevSlider();
$arrSliders = $theslider->getArrSliders();
$arrA = array();
$arrT = array();
foreach($arrSliders as $slider){
$arrA[] = $slider->getAlias();
$arrT[] = $slider->getTitle();
}
if($arrA && $arrT){
$result = array_combine($arrA, $arrT);
}
else
{
$result = false;
}
return $result;
}
}
I tried all I know and other answers around here but no hope.
I would really appreciate a push !
Thanks
Check sizeof ($ array)> 0 do this for both arrays. Also just try to echo what you are getting in getalias and gettitle methods before storing it in array.
function jobboard_revslider(){
if (class_exists('RevSlider')) {
$theslider = new RevSlider();
$arrSliders = $theslider->getArrSliders();
$arrA = array();
$arrT = array();
foreach($arrSliders as $slider){
$arrA[] = substr($slider->getAlias(), 1);
$arrT[] = substr($slider->getTitle(), 1);
}
if($arrA && $arrT){
$result = array_combine($arrA, $arrT);
}
else
{
$result = false;
}
return $result;
}

Echo a value from an array based on function parameters

I need to be able to echo a value from a private property in one of my classes if a method is called within the class. It's a little tricky to explain so let me demostrate and hopefully someone can fill in the blank for me :)
<?php
class test {
private $array['teachers']['classes'][23] = "John";
public function __construct($required_array) {
$this->array['teachers']['classes'][23] = "John";
$this->array['students'][444] = "Mary";
$this->echo_array($required_array);
}
public function echo_array($array) {
// Echo the value from the private $this->array;
// remembering that the array I pass can have either
// 1 - 1000 possible array values which needs to be
// appended to the search.
}
}
// Getting the teacher:
$test = new test(array('teachers','classes',23));
// Getting the student:
$test = new test(array('students',444));
?>
Is this possible?
$tmp = $this->array;
foreach ($array as $key) {
$tmp = $tmp[$key];
}
// $tmp === 'John'
return $tmp; // never echo values but only return them
An other approach to get value;
class Foo {
private $error = false,
$stack = array(
'teachers' => array(
'classes' => array(
23 => 'John',
24 => 'Jack',
)
)
);
public function getValue() {
$query = func_get_args();
$stack = $this->stack;
$result = null;
foreach ($query as $i) {
if (!isset($stack[$i])) {
$result = null;
break;
}
$stack = $stack[$i];
$result = $stack;
}
if (null !== $result) {
return $result;
}
// Optional
// trigger_error("$teacher -> $class -> $number not found `test` class", E_USER_NOTICE);
// or
$this->error = true;
}
public function isError() {
return $this->error;
}
}
$foo = new Foo();
$val = $foo->getValue('teachers', 'classes', 24); // Jack
// $val = $foo->getValue('teachers', 'classes'); // array: John, Jack
// $val = $foo->getValue('teachers', 'classes', 25); // error
if (!$foo->isError()) {
print_r($val);
} else {
print 'Value not found!';
}

how to use three objects of an array at a time in php

I have an array called emp_rec with more than 100 employees and each employee having around 60 fields, am using the following method to use one employee at a time...
foreach($emp_rec as $obj) {
$name = $obj->get_empname();
//.....
......///
}
Now am planning to use three employees at a time in a single loop,
How can i do this...?
You could try this:
$current = Array();
while(($current[0] = array_shift($emp_rec))
&& ($current[1] = array_shift($emp_rec))
&& ($current[2] = array_shift($emp_rec))) {
// do stuff here
}
if( $current[0]) {
// there were records left over, optionally do something with them.
}
Try something like this:
for ($i = 0; $i < count($emp_rec); $i+=3) {
$emp1 = $emp_rec[$i];
$emp2 = $emp_rec[$i+1];
$emp3 = $emp_rec[$i+2];
}
Here you can iterate in one time on same multi objects. Easy to adapt.
<?php
// Example of class
class A {
public $a = 'a';
public $b = 'b';
public $c = 'c';
}
$obj1 = new A; // Instantiate 3 objects
$obj2 = new A;
$obj3 = new A;
$objs = array((array)$obj1, (array)$obj2, (array)$obj3); // Array of objects (cast in array)
foreach ($objs[0] as $key => $value) {
echo $objs[0][$key];
echo $objs[1][$key];
echo $objs[2][$key];
}
Output aaabbbccc
What about :
$GROUP_SIZE = 3;
$emp_count = count($emp_rec);
for ($i=0; $i<$emp_count; $i+=$GROUP_SIZE) {
for ($j=0; $i+$j<$emp_count && $j<$GROUP_SIZE; $j++) {
$current = $emp_rec[$i+$j];
$name = $current->get_empname();
}
}
If you need to manipulate 3 or N employees at a time, it would let you know in which "group" the current employee is.

Categories