Given that you have an array that contains varying amounts of objects, how can you access the properties of the last object? I tried to use end($array); but it gives the error: Object of class Post could not be converted to string
The class is:
class Post {
private $datafile;
public $index;
public $subIndex;
public $poster;
public $title;
public $message;
public $date;
// constructor and some unrelated methods here
public function getCommentData($givenIndex) {
$comments = null;
$data = file($this->datafile);
foreach($data as $row) {
list($index, $subIndex, $poster, $message, $date) = explode('|', $row);
$this->index = $subIndex; // SubIndex ties a Comment to a Post (same ID)
if($this->index == $givenIndex) {
$comment = new Post();
$comment->poster = $poster;
$comment->message = $message;
$comment->date = date(DATEFORMAT, strtotime($date));
$comments[] = $comment;
}
}
return $comments;
}
}
Now, I would like to access only the last Comment item's properties, but I'm not sure how it should be done? In a regular array, end() is quick and easy to use, but how about with objects as it doesn't seem to work?
Here is an example var_dump:
array (size=2)
0 =>
object(Post)[4]
private 'datafile' => null
public 'index' => null
public 'subIndex' => null
public 'poster' => string 'Postaaja' (length=8)
public 'title' => null
public 'message' => string 'Kommentti' (length=9)
public 'date' => string '5 Mar 2013 | 23:12' (length=18)
1 =>
object(Post)[5]
private 'datafile' => null
public 'index' => null
public 'subIndex' => null
public 'poster' => string 'Toinenkin' (length=9)
public 'title' => null
public 'message' => string 'Lisäkommentti' (length=14)
public 'date' => string '5 Mar 2013 | 23:13' (length=18)
Thanks!
EDIT:
Here's the way I tried to use it:
$comments = new Post(FILECOMMENTS);
$currentComments = $comments->getCommentData($i); // $i is the index of current newspost item
$newsComments = new Format();
$newsComments->formatShortComment($currentComments, $i);
And the method in the Format class:
// This comment is displayed as a short text in the main News view
public function formatShortComment($data, $index) {?>
<div class="newsComments">
<p class="newsPreviewComment">
<?php
$lastItem = end($data);
if(!empty($lastItem->message)) {
echo '<i>"',$lastItem->message,'"</i> ';
echo '-',$lastItem->poster;
}
?></p>
» Show All/Add comments
(<?php echo $commentCount; ?>)
</div><?php
}
You could try:
$tempArray = array_values($data);
$lastItem = $tempArray[count($tempArray)-1];
I hope I didn't miss something important, but if you're just trying to get the last element of a PHP array:
$lastItem = $data[count($data) - 1];
Related
I have an array of associative array, I will like to update the values in this array, hence I created a function that looks like this.
//The Array of Associative arrays
array (size=2)
0 =>
array (size=3)
'slang' => string 'Tight' (length=5)
'description' => string 'Means well done' (length=15)
'example-sentence' => string 'Prosper it Tight on that job' (length=28)
1 =>
array (size=3)
'slang' => string 'Sleet' (length=5)
'description' => string 'Means to send on long errand' (length=28)
'example-sentence' => string 'I am going to sleep sia' (length=23)
//The function
public function update($slang, $new)
{
array_map(function($data, $key) use($slang, $new)
{
if($data['slang'] == $slang)
{
$data[$key] = array_replace($data, $new);
}
}, UrbanWord::$data);
}
I tired running this but the original array will not update. I need help on how to go about fixing this please.
Thanks
You may use array_reduce instead of array_map as following:
public function update($array, $slang, $new)
{
return array_reduce($array, function ($result, $item) use ($slang, $new) {
if ($item['slang'] == $slang) {
$item = array_replace($item, $new);
}
$result[] = $item;
return $result;
}, array());
}
Usage:
UrbanWord::$data = $this->update(
UrbanWord::$data,
'Tight',
array('description' => 'another description')
);
var_dump($myUpdatedArray);
If you want to update it directly passing the UrbanWord::$data by reference you may try something like:
class UrbanWord
{
public static $data = array(
array(
'slang' => 'Test',
'Desc' => 'Frist Desc'
),
array(
'slang' => 'Test1',
'Desc' => 'Second Desc'
)
);
}
class MyClass
{
public function update(&$array, $slang, $new)
{
$array = array_reduce($array, function ($result, $item) use ($slang, $new) {
if ($item['slang'] == $slang) {
$item = array_replace($item, $new);
}
$result[] = $item;
return $result;
}, array());
}
}
$myClass = new MyClass();
$myClass->update(UrbanWord::$data, 'Test', array('Desc' => 'test'));
echo '<pre>';
var_dump(UrbanWord::$data);
echo '</pre>';
I know this question is more data structures but since I am doing it in Symfony there might be a simpler way. I have a recursive function treeBuilder() I want to call on some data to create a hierarchy. Say a database of people and I want to create a tree structure if they live with their parents. I know I am passing an array of object to the function but it needs to be an array. I am pretty sure I need to rewrite this function so that it handles the the array of object but am stumped. I am not sure how to access the elements of the array to check the parentid. I know the code below is not correct but that is where I am at now.
Controller:
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository('CompanyMyBundle:Org')->findAll();
var_dump($entities);
$tree=$this->treeBuilder($entities);
return array(
'entities' => $tree,
);
}
private function treeBuilder($ar, $pid=null)
{
$op=array();
foreach( $ar as $item ) {
// I know I have an array of objects
if( $item['ParentId'] == $pid ) {
$op[$item['Id']] = array(
'Street' => $item['Street'],
'ParentId' => $item['ParentId']
);
$children = self::treeBuilder( $ar, $item['Id'] );
if( $children ) {
$op[$item['Id']]['children'] = $children;
}
}
}
return $op;
}
var_dump($entities) from indexAction():
/export/www/working/symfony/src/Company/MyBundle/Controller/DepController.php:34:
array (size=60)
0 =>
object(Company\MyBundle\Entity\Org)[1556]
private 'Name' => string 'Me' (length=46)
private 'Street' => string '123 Sesame' (length=255)
private 'City' => string 'Myhometown' (length=255)
private 'ParentId' => int 0
private 'Id' => int 1
1 =>
object(Company\MyBundle\Entity\Org)[1557]
private 'Name' => string 'Me2' (length=46)
private 'Street' => string '123 Sesame' (length=255)
private 'City' => string 'Myhometown' (length=255)
private 'ParentId' => int 1
private 'Id' => int 2
If you need to get entities as arrays instead of objects, you would need to use Doctrine's hydrator:
$em = $this->getDoctrine()->getManager();
$orgRepo = $em->getRepository('CompanyMyBundle:Org');
$entities = $orgRepo->createQueryBuilder('org')
->getQuery()
->getResult(\Doctrine\ORM\AbstractQuery::HYDRATE_ARRAY);
Note:
I would suggest to leave entities as objects and use getters:
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository('CompanyMyBundle:Org')->findAll();
$tree = $this->treeBuilder($entities);
return array(
'entities' => $tree,
);
}
private function treeBuilder($entities, $pid = null)
{
$op = array();
/** Org $entity */ //Type hinting, if you use autocompletion
foreach ($entities as $entity) {
if ($entity->getParentId() == $pid) {
$op[$entity->getId()] = [
'Street' => $entity->getStreet(),
'ParentId' => $entity->getParentId()
];
$children = self::treeBuilder($entities, $entity->getId());
if (!empty($children)) {
$op[$entity->geId()]['children'] = $children;
}
}
}
return $op;
}
I have a POST request array that looks like this
$request = array (size=2)
'licence' => string 'uDyQwFwqV7aQG2z' (length=15)
'user' =>
array (size=7)
'first_name' => string 'Danut' (length=5)
'last_name' => string 'Florian' (length=7)
'username' => string 'daniesy9' (length=8)
'password' => string '123456' (length=6)
'rpassword' => string '123456' (length=6)
'email' => string 'daniesy+1#me.com' (length=16)
'phone' => string '9903131' (length=7)
This in fact is an array which represents values sent by a form. I know the name of the elements, for example the username input has the name of user[username] and i have to find the related value from the array, by name. Something like:
$key = "user[username]";
$request[key];
Any idea how to do this?
I know that the correct way to do it is $request["user"]["username"] but it's quite complicated because i have to use the fields names from the form which are user[username], user[firstname], etc and it might have up to 4 levels of depth.
Answered in comments but similar Question to
Convert a String to Variable
eval('$username = $request["user"]["username"];');
Edit
Eval not a valid suggestion as request data.
So I would suggest the second method on this post
<?php
$request = array(
'user' => array(
'username' => 'joe_blogs'
)
);
function extract_data($string) {
global $request;
$found_matches = preg_match_all('/\[\"([a-z]+)\"\]/', $string, $matches);
if (!$found_matches) {
return null;
}
$current_data = $request;
foreach ($matches[1] as $name) {
if (key_exists($name, $current_data)) {
$current_data = $current_data[$name];
} else {
return null;
}
}
return $current_data;
}
$username = extract_data('request["user"]["username"]');
?>
function findInDepth($keys, $array){
$key = array_shift($keys);
if(!isset($array[$key])){
return FALSE;
}
if(is_array($array[$key])){
return findInDepth($keys, $array[$key]);
}
return $array[$key];
}
$key = "user[username]";
$keys = preg_split("/(\[|\])/", $key);
echo findInDepth($keys, $request);
This function solves my problem. It first splits the string (aka the input name) into an array of keys and then recessively searches in depth the array by keys until it finds a value which is not an array and returns FALSE otherwise.
You could separate keys with dots. Primitive example:
<?php
class ArrayDot
{
protected $array = [];
public function __construct(array $array) {$this->array = $array;}
public function get($path)
{
$array = $this->array;
foreach(explode('.', $path) as $key) {
$array = $array[$key];
}
return $array;
}
}
$array = [
'user' => [
'username' => 'tootski',
]
];
$a = new ArrayDot($array);
echo $a->get('user.username'); # tootski
Working with DateTime in projects again have a problem with duplicating if use array_unique to array which have a elemts of object,(but probles only with DateTime), see code:
class simpleClass
{
public $dt;
function __construct($dt)
{
$this->dt = $dt;
}
}
$dateObj = new simpleClass(new DateTime);
$std = new stdClass;
$arr = [$dateObj, $dateObj, $std, $std, $std, $std];
var_dump(array_unique($arr, SORT_REGULAR));
Expected 1 element with dateObj
But actually there 2
Function array_unique() will compare strings, so objects will be casted to strings. Solution to that would be to use __toString() magic method to return full date identifier:
class simpleClass
{
public $dt;
function __construct(DateTime $dt) {
$this->dt = $dt;
}
public function __toString() {
return $this->dt->format('r');
}
}
$dateObj1 = new simpleClass(new DateTime);
$dateObj2 = new simpleClass(new DateTime);
$dateObj3 = new simpleClass(new DateTime('today'));
$arr = [$dateObj1, $dateObj2, $dateObj3];
print_r(array_unique($arr));
Demo.
I still can't understand. Setting the array with:
$arr = [$dateObj, $dateObj, $std, $std];
returns:
array (size=2)
0 =>
object(simpleClass)[1]
public 'dt' =>
object(DateTime)[2]
public 'date' => string '2013-11-14 14:37:08' (length=19)
public 'timezone_type' => int 3
public 'timezone' => string 'Europe/Rome' (length=11)
2 =>
object(stdClass)[3]
This way, array_unique seems to work...
How do I convert from my PHP array (mysql_fetch_array) to a declared PHP Class then encode that to json format string. My array:
while ($rows = mysql_fetch_array($result, MYSQL_ASSOC)){
$patient[] = array( 'id' => $rows['id'],
'name' => $rows['name'],
'sex' => $rows['sex'],
'civil_status' => $rows['civil_status'],
'age' => $rows['age'],
'type_of_admission' => $rows['type_of_admission'],
'admission_diagnosis' => $rows['admission_diagnosis'],
'date_admitted' => $rows['date_admitted']);
}
My declare PHP Class
class Person
{
public $id;
public $name;
public $sex;
public $civil_status;
public $age;
public $type_of_admission;
public $admission_diagnosis;
public $date_admitted;
}
I think you are looking for mysql_fetch_object:
while ($row = mysql_fetch_object($result, 'Person')){
$json_rows[] = json_encode($row);
}
Also, you should be using mysqli, which has the same basic concept.
just retype to (object)
$object = (object) $array_name;
for json_encode.