Laravel Pagination merge - php

I'm using laravel 4 for my project .
I have paginated select results from 4 tables and I wanted to pass them to view in one variable .
$vehicles = DB::table('vehicle')->orderBy('postTime','DESC')->paginate(8);
$estates = DB::table('estate')->orderBy('postTime','DESC')->paginate(8);
$tradings = DB::table('trading')->orderBy('postTime','DESC')->paginate(8);
$jobs = DB::table('job')->orderBy('postTime','DESC')->paginate(8);
but I could not merge them using array_merge() . I also tried ->to_array() after paginate, it didn't work.
can some one help me here ?
EDIT
as #Turgut Sarıçam suggested , I used getItems() for my results and here is my code :
public static function index(){
$minVehicle = DB::table('vehicle')->min('price');
$maxVehicle = DB::table('vehicle')->max('price');
$minEstate = DB::table('estate')->min('price');
$maxEstate = DB::table('estate')->max('price');
$minTrading = DB::table('trading')->min('price');
$maxTrading = DB::table('trading')->max('price');
if($minVehicle == 'توافقی')
$minVehicle = 0;
if($maxVehicle == 'توافقی')
$maxVehicle = 0;
if($minEstate == 'توافقی')
$minEstate = 0;
if($maxEstate == 'توافقی')
$maxEstate = 0;
if($minTrading == 'توافقی')
$minTrading = 0;
if($maxTrading == 'توافقی')
$maxTrading = 0;
$vehicles = DB::table('vehicle')->orderBy('postTime','DESC')->paginate(8);
$estates = DB::table('estate')->orderBy('postTime','DESC')->paginate(8);
$tradings = DB::table('trading')->orderBy('postTime','DESC')->paginate(8);
$jobs = DB::table('job')->orderBy('postTime','DESC')->paginate(8);
$allResults = array_merge($vehicles,$jobs);
//echo "<meta charset='UTF8'><pre>";
//return die(print_r($allResults));
return View::make('search')->with(
array(
'minVehicle' => $minVehicle,
'maxVehicle' => $maxVehicle,
'minEstate' => $minEstate,
'maxEstate' => $maxEstate,
'minTrading' => $minTrading,
'maxTrading' => $maxTrading,
'ads' => $allResults
)
);
}
Dumping $allResults (where I commented) had some results.
I cant show the exact result , but here is example of it :
Array
(
[0] => stdClass Object
(
[id] => 243
[tableName] => vehicle
)
[1] => stdClass Object
(
[id] => 239
[tableName] => vehicle
)
[2] => stdClass Object
(
[id] => 235
[tableName] => vehicle
)
[3] => stdClass Object
(
[id] => 231
[tableName] => vehicle
)
[4] => stdClass Object
(
[id] => 227
[tableName] => vehicle
)
[5] => stdClass Object
(
[id] => 223
[tableName] => vehicle
)
[6] => stdClass Object
(
[id] => 219
[tableName] => vehicle
)
[7] => stdClass Object
(
[id] => 215
[tableName] => vehicle
)
[8] => stdClass Object
(
[id] => 4
[tableName] => job
)
[9] => stdClass Object
(
[id] => 3
[tableName] => job
)
)
although the result seems to be fair , no view was returned . just a blank white page

You should get the items first. Try like this:
$allResults = array_merge($vehicles->items(), $estates->items(), $tradings->items(), $jobs->items());
Edit: I guess you can get items with getItems() function in Laravel 4. Above is for Laravel 5, my bad.

You are dealing with collections that are returned from the query. Don't think array merge is correct way to go Try using collection merge.
Collection merge is supported as well in laravel 4.
Try using this
$merged_collection = $vehicles->merge($estates)->merge($tradings)->merge($jobs);

Related

PHP - Nesting an array from API obj response

I have a large object API response, I'm trying to load the data into a nested array so I can work with it later. Here is a sample of the object I get back from the API.
SObject Object
(
[type] => AggregateResult
[fields] => stdClass Object
(
[expr0] => 12
[Name] => Performance Reviews
[Status] => Closed - Approved
[expr1] => 30
)
)
SObject Object
(
[type] => AggregateResult
[fields] => stdClass Object
(
[expr0] => 12
[Name] => Performance Reviews
[Status] => Closed - Attempted
[expr1] => 11
)
)
SObject Object
(
[type] => AggregateResult
[fields] => stdClass Object
(
[expr0] => 12
[Name] => Performance Reviews
[Status] => Closed - Contact Declined
[expr1] => 13
)
As I said, the goal is to have a nested array that would look similar to this:
Array
(
[January] => Array
(
[0] => Array
(
[0] => January
[1] => Closed - Approved
[2] => 28
)
[1] => Array
(
[0] => January
[1] => Closed - Approved
[2] => 28
)
)
)
Here is my Code:
$query =
"SELECT CALENDAR_MONTH(closedDate), recordType.name,status,count(id)
FROM case
WHERE owner.name ='" . $SFName . "' AND recordType.name IN('DT Case','Performance Reviews') AND closedDate = LAST_N_MONTHS:6
GROUP BY CALENDAR_MONTH(closedDate),recordType.Name,status ORDER BY CALENDAR_MONTH(closedDate)";
$counter = 0;
$mprArray = array(); //instantiate our Array
$response = $mySforceConnection->query($query);
$queryResult = new QueryResult($response);
foreach ($queryResult->records as $case) {
//turn our query Result into an Obj
$sObject = new SObject($case);
$recordType = $sObject->Name;
$status = $sObject->Status;
$month = $sObject->expr0;
$count = $sObject->expr1;
//this is a filter to weed out a portion of the cases.
if ($recordType == "Performance Reviews") {
foreach($sObject as $record) {
//change the month's number to a month's name
$dateObj = DateTime::createFromFormat('!m', $month);
$monthName = $dateObj->format('F');
// Create the nested array, it should end up looking like $mprArray[January].
// This is a dynamic name since we're creating an array for each status that exists in performance Reviews
$mprArray[$monthName] = array($monthName,$status,$count);
// Trying to append our nested array onto the $mprArray so we can work with it later.
array_push($mprArray,$mprArray[$monthName]);
}
}
//increase counter
$counter = $counter++;
}
} catch (Exception $e) {
print_r($mySforceConnection->getLastRequest());
echo $e->faultstring;
}
Instead of a nested array, only the first item in the array is named 'January', the remainder are named based on a counter, until we get to the next month of 'february', here's what it looks like.
Array
(
[January] => Array
(
[0] => January
[1] => Closed - Contact Declined
[2] => 15
)
[0] => Array
(
[0] => January
[1] => Closed - Approved
[2] => 28
)
)
because array_push only inserts the data to the next index;
I feel you should use $mprArray[$monthName][] = array($monthName,$status,$count); only; and no need for the array_push after that

Extracting a property from an array of an array of objects

I've got an object, containing an array of objects, containing an array of values:
stdClass Object (
[devices] => Array (
[0] => stdClass Object (
[location] => 1
[delegate] =>
[type] => 1
[id] => 1234
[IP] => 1.2.3.4
[name] => host1
[owner] => user6
[security] => 15
)
[1] => stdClass Object (
[location] => 2
[delegate] =>
[type] => 1
[id] => 4321
[IP] => 4.3.2.1
[name] => host2
[owner] => user9
[security] => 15
)
)
)
I want to extract just the id and name into an array in the form of:
$devices['id'] = $name;
I considered using the array_map() function, but couldn't work out how to use it... Any ideas?
This will generate you a new array like I think you want
I know you says that delegate is an object but the print does not show it that way
$new = array();
foreach($obj->devices as $device) {
$new[][$device->id] = $device->name;
}
Would something like this not work? Untested but it cycles through the object structure to extract what I think you need.
$devices = myfunction($my_object);
function myfunction($ob){
$devices = array();
if(isset($ob->devices)){
foreach($ob->devices as $d){
if(isset($d->delegate->name && isset($d->delegate->id))){
$devices[$d->delegate->id] = $d->delegate->name;
}
}
}
return($devices);
}
Im usually using this function to generate all child and parent array stdclass / object, but still make key same :
function GenNewArr($arr=array()){
$newarr = array();
foreach($arr as $a=>$b){
$newarr[$a] = is_object($b) || is_array($b) ? GenNewArr($b) : $b ;
}
return $newarr;
}

How to transform the results of a stored procedure in to a list of object then convert to json in CI?

I am using CodeIgniter 2.2.6 + DataMapper, I have a question regarding how to transform the results of a stored procedure into DataMapper Models, then convert them to json.
I have a model called Event:
class Event extends DataMapper {
var $table = 'EVENT'; // map to EVENT table
}
with the following code, I can easily get the top 10 Event:
$event = new Event();
$event->get( 10, 0 );
$event->all_to_json(); //this convert the result to json following the table structure
Now I have a stored procedure getSpecialEvent(), the result of this SP has exactly same structure as Table EVENT,
With the followng code, I do get the content but they are in Array format:
$sql = "call getSpecialEvent()";
$event = new Event();
$event = $this->db->query ($sql);
print_r ($event->result_array());
this will returned some thing like this:
Array
(
[0] => Array
(
[event_id] => 11
[title] => Test1
...
)
[1] => Array
(
[event_id] => 2
[title] => Test1
...
)
)
if I use this
foreach ( $event as $obj ) {
print_r($obj);
}
I get empty array:
Array
(
)
Array
(
)
then I tried
print_r ($event->result());
it returns
Array
(
[0] => stdClass Object
(
[event_id] => 11
[title] => Test1
...
)
[1] => stdClass Object
(
[event_id] => 2
[title] => Test2
...
)
}
I used some code found on internet to cast stdClass Object to Event, it looks like ok, but when I call to_json() method, it doesn't work.
function objectToObject($instance, $className) {
return unserialize(sprintf(
'O:%d:"%s"%s',
strlen($className),
$className,
strstr(strstr(serialize($instance), '"'), ':')
));
}
foreach ( $event->result() as $obj ) {
$newObj = $this->objectToObject($obj, "Event");
print_r ($newObj);
print_r ($newObj->to_json());
}
I printed he casted object, here it is:
Event Object
(
[table] => EVENT
[error] =>
[stored] =>
[model] =>
[primary_key] => id
[valid] =>
[cascade_delete] => 1
[fields] => Array
(
)
[all] => Array
(
)
[parent] => Array
(
)
[validation] => Array
(
)
[has_many] => Array
(
)
[has_one] => Array
(
)
[production_cache] =>
[free_result_threshold] => 100
[default_order_by] =>
[_validated:protected] =>
[_force_validation:protected] =>
[_instantiations:protected] =>
[_field_tracking:protected] =>
[_query_related:protected] => Array
(
)
[_include_join_fields:protected] =>
[_force_save_as_new:protected] =>
[_where_group_started:protected] =>
[_group_count:protected] => 0
[event_id] => 11
[title] => test11
...
)
but $newObj->to_json() returns empty
Array
(
)
Array
(
)
if I do a small test
$event = new Event ();
$event->event_id = 13;
$event->title = "xxxxx";
echo json_encode($event->to_json());
I do get:
{"event_id":13,"title":"xxxxx"....}
I don't know why the casted object doesn't work with to_json?
It seems to be a limitation, the casted DataMapper object (Event here) is not taken as a real DataMapper object, then I create a method in Event to export the needed info to aother pure object model and use json_encode(), this works.

Retrieving correct record from multidimentional array

I'm having a mental freeze moment. If I have an array in the following format:
$myData = Array
(
[0] => stdClass Object
(
[id] => 1
[busID] => 5
[type] => SMS
[number] => 5128888888
)
[1] => stdClass Object
(
[id] => 2
[busID] => 5
[type] => APP
[number] => 5125555555
)
[2] => stdClass Object
(
[id] => 4
[busID] => 5
[type] => APP
[number] => 5129999988
[verified] => 1
[default] => 0
)
)
And I only have an var for ID of the record, how do I retrieve the rest of the detail for that set.
$myID = 2;
// get number 5125555555 and it's type
echo $myData[][$myID]['number']; // ???
The way you have your data arranged your going to have to loop through your array to identify the object corresponding to $myID.
foreach($myData as $object) if($object->id == $myID) echo $object->number;
The alternative is to arrange your $myData as an associative array with the id field as the key. Then you could access it simply with $myData[$myID]->number.
Actually it's an array that contains StdClass objects , try looping over $myData and access each attribute :
foreach ( $myData as $data )
{
print_r($data->id);
// ...
}
You can avoid loop by using following logic:
<?php
$myID = 2;
$myData = json_decode(json_encode($myData),1); // Convert Object to Array
$id_arr = array_column($myData, 'id'); // Create an array with All Ids
$idx = array_search($myID, $id_arr);
if($idx !== false)
{
echo $myData[$idx]['type'] . ' -- ' . $myData[$idx]['number'];
}
?>
Working Demo
Note: array_column is supported from PHP 5.5.
For lower versions you can use this beautiful library https://github.com/ramsey/array_column/blob/master/src/array_column.php
You can create a custom function to achieve this, you need to pass the array and id whose details you want and the function will return the array with matching id, like below
function detailsById($myData,$id){
foreach($myData as $data){
if($data->id == $id){
return $data;
}
}
}
Just call this function with your array and id..
$data=detailsById($myData,2);
echo "<pre>";print_r($data);
This will give you :
stdClass Object
(
[id] => 2
[busID] => 5
[type] => APP
[number] => 5125555555
)
And further to print 'number' and 'type' use $data array
$data['type'];
$data['number'];

CakePHP Model Query Return Data Formating

I'm looking for a way to make it so cake returns all database data in the same format/structure... Currently it returns two different types of format depending on the relationship.
If a model 'B' is associated with the current model 'A' being queried it will then place model associations for 'B' underneath it as you can see in [User] below. I want it so that all queries use that structure.
example:
$this->find('all', ....
returns:
Array
(
[0] => Array
(
[UserGroup] => Array
(
[id] => 53
[user_id] => 100003332014851
[media_id] =>
[name] => john
[description] => qwasdfad
)
[User] => Array
(
[id] => 100003332014851
[session_id] => ssm2qbrotmm13ho1ipm8ii2492
[username] =>
[password] => -1
[Planner] => Array
(
)
[Purchase] => Array
(
)
[Listing] => Array
(
)
)
)
I want this to look like:
Array
(
[0] => Array
(
[UserGroup] => Array
(
[id] => 53
[user_id] => 100003332014851
[media_id] =>
[name] => john
[description] => qwasdfad
[User] => Array
(
[id] => 100003332014851
[session_id] => ssm2qbrotmm13ho1ipm8ii2492
[username] =>
[password] => -1
[Planner] => Array
(
)
[Purchase] => Array
(
)
[Listing] => Array
(
)
)
)
)
)
In CakePHP, the find() method return data like your first format. But If you want to format like second one then you have to process it by hand (try to avoid this if possible)
$data = $this->find('all');
$assocs = Set::extract('/User', $data); // extracting all `User` array
foreach($assocs as $key => $assoc) {
unset($data[$key]['User']); // removing the associate `User` from `$data`
$data[$key]['UserGroup']['User'] = $assoc['User']; // adding associate under `UserGroup`
}
ended up doing this... it changes the output to what we need. The top level item does not have a header which is fine I just adjusted our scripts for that... maybe this will help somebody else if they need a custom idea
also no guarantee this covers all possible results but so far it works with all the queries we have.
class AppModel extends Model {
function afterFind($results, $primary) {
//if this is a primary, structure like a secondary so entire site is same format
if ($primary) {
$class = get_class($this);
//simple fix for primary
foreach ($results as $key => $result) {
$result = $this->formatData($result, $class);
$results[$key] = $result;
}
}
return $results;
}
function formatData($result, $class) {
$array = array();
if (isset($result[$class])) {
$array = $result[$class];
unset($result[$class]);
}
$array += $result;
return $array;
}
You can also use contain in this case along with find as UserGroup.User for your desired result

Categories