Looping through method within an object Laravel 4 - php

I am trying to loop through a method I created for dates in my object. However, it's only looping the first results and I am not sure how I can make it loop through every result and apply accordingly.
Date Method
public function getDate($date) {
$date = preg_replace('/,/', '', $date);
$newDate = strtotime($date);
$dateFormat = date('l: F d, Y',$newDate);
return $dateFormat;
}
Controller calling the Model
public function showDashboard() {
$pages = Pages::orderBy('created_at', 'DESC')->get();
// foreach($pages as $page) {
// $date = $this->getDate($page->created_at);
// }
//var_dump($date); die;
return View::make('dashboard.index', ['pageTitle' => 'Dashboard','pages' => $pages]);
}
dumping $date only returns one result which looks like the last date in the database table. If I put the dump inside the loop I only get the first result.
I tried applying the method directly to the Blade template $this->getDate($page->created_at); but returns an error stating it is not a defined method. The blade template is just a simple foreach loop that would show each record. What I want accomplished is foreach one of those created_at records I want the getDate method applied to it.

You've not set $date as an array - its writing over itself each time..
public function showDashboard() {
$pages = Pages::orderBy('created_at', 'DESC')->get();
$date = array();
foreach($pages as $page) {
$date[] = $this->getDate($page->created_at);
}
var_dump($date); die;
return View::make('dashboard.index', ['pageTitle' => 'Dashboard','pages' => $pages]);
}

Related

Laravel modify Collection data

I wonder if Laravel have any helper to modify a collection.
What I need to do is to make a query with paginate() then check if the logged in users ID match the sender or receiver and based on that add a new value to the output:
$userId = Auth::guard('api')->user()->user_id;
$allMessages = Conversation::join('users as sender', 'conversations.sender_id', '=', 'sender.user_id')
->join('users as reciver', 'conversations.recipient_id', '=', 'reciver.user_id')
->where('sender_id',$userId)->orWhere('recipient_id',$userId)
->orderBy('last_updated', 'desc')
->select('subject','sender_id','recipient_id', 'sender_unread', 'recipient_unread', 'last_updated', 'reciver.username as receivername', 'sender.username as sendername')
->paginate(20);
Now I want to do something like:
if ($allMessages->sender_id == $userId) {
// add new value to output
newField = $allMessages->sendername
} else {
// add new value to output
newField = $allMessages->receivername
}
Then send the data with the new value added
return response()->json(['messages' => $allMessages], 200);
Is this possible?
You're better off using the Collection class's built-in functions for this. For example, the map function would be perfect.
https://laravel.com/docs/5.3/collections#method-map
$allMessages = $allMessages->map(function ($message, $key) use($userId) {
if ($message->sender_id == $userId) {
$message->display_name = $message->receivername;
} else {
$message->display_name = $message->sendername;
}
return $message;
});
Solved by adding:
foreach ($allMessages as $message) {
if ($message->sender_id == $userId) {
$message->display_name = $message->receivername;
} else {
$message->display_name = $message->sendername;
}
}
You can surely use the laravel's LengthAwarePaginator.
Along with total count of collection you also need to pass the slice of collection's data that needs to be displayed on each page.
$total_count = $allMessages->count();
$per_page = 2;
$current_page = request()->get('page') ?? 1;
$options = [
'path' => request()->url(),
'query' => request()->query(),
];
Suppose you want 2 results per page then calculate the offset first
$offset = ($current_page - 1) * $per_page;
Now slice the collection to get per page data
$per_page_data = $collection->slice($offset, $per_page);
$paginated_data = new LengthAwarePaginator($per_page_data, $total_count, $per_page, $current_page, $options);
$paginated_data will have only limited number of items declared by $per_page variable.
If you want next two slice of data then pass api_request?page="2" as your url.
As I don't know which Laravel version you're using, taking Laravel 5.2 let me give you a smarter way to deal with this (if I get your problem correctly).
You can use Laravel's LengthAwarePaginatior(API Docs).
Don't use paginate method when you are bulding your query, instead of that use simple get method to get simple collection.
$userId = Auth::guard('api')->user()->user_id;
$allMessages = Conversation::join('users as sender', 'conversations.sender_id', '=', 'sender.user_id')
->join('users as reciver', 'conversations.recipient_id', '=', 'reciver.user_id')
->where('sender_id',$userId)->orWhere('recipient_id',$userId)
->orderBy('last_updated', 'desc')
->select('subject','sender_id','recipient_id','sender_unread','recipient_unread','last_updated','reciver.username as receivername','sender.username as sendername')
->get();
Now you can populate extra items into that collection based on your certain conditions like this.
if ($allMessages->sender_id == $userId ) {
// add new value to collection
} else {
// add new value to collection
}
Now use LengthAwarePaginator, to convert that populated collection into a paginated collection.
$total_count = $allMessages->count();
$limit = 20;
$current_page = request()->get('page');
$options = [
'path' => request()->url(),
'query' => request()->query(),
];
$paginated_collection = new LengthAwarePaginator($allMessages, $total_count, $limit, $current_page, $options);
The variable $paginated_collection now can be used to be sent in response. Hope this helps you to deal with your problem.

Yii2 MongoDB query not working

I was using MySQL for my db before and moved to using MongoDB just recently. I have been converting my queries to MongoDB format then I encountered a problem along the way.
I wanted to get the payslip_id of a specific user where date_generated (of the payslip) is in between the start and end dates of a specific payroll period. Here's the original query (MySQL):
public function getPayslipDetails()
{
$time = date_default_timezone_set('Asia/Manila');
$time = date('Y/m/d', time());
$session = Yii::$app->session;
return $this->hasOne(Payslip::className(), ['user_id' => 'user_id'])->where('date_generated BETWEEN :start_time AND :end_time', array(':start_time' => $session['start'], ':end_time' => $session['end']));
}
public function getPayslipID()
{
return $this->payslipDetails ? $this->payslipDetails->payslip_id : '';
}
Now, here's my converted query to MongoDB:
public function getPayslipDetails()
{
$time = date_default_timezone_set('Asia/Manila');
$time = date('Y/m/d', time());
$session = Yii::$app->session;
return $this->hasOne(Payslip::className(), ['user_id' => '_id'])->where(array('date_generated' => array('$in' => array($session['start'], $session['end']))));
}
public function getPayslipID()
{
return $this->payslipDetails ? $this->payslipDetails->_id : '';
}
Notice the return statements are different. I wonder if my MongoDB query is correct or not. It doesn't return any error as well.
I would really appreciate your response.
The $in operator selects the documents where the value of a field equals any value in the specified array. It is not equivalent to MySQLBETWEEN.
Use $gte and $lte operators.
public function getPayslipDetails()
{
$time = date_default_timezone_set('Asia/Manila');
$time = date('Y/m/d', time());
$session = Yii::$app->session;
return $this->hasOne(Payslip::className(), ['user_id' => '_id'])->where(array('date_generated' => array('$gte' => $session['start']), 'date_generated' => array('$lte' => $session['end'])));
}
public function getPayslipID()
{
return $this->payslipDetails ? $this->payslipDetails->_id : '';
}
I am not sure about the syntax of php-mongodb but I think this should help.

Storing time in array

I have some code that stores values in an array. It all seems to work but I also want to store the time that each value is added to the array (as part of the array) The code stores only unique values to a maximum of four.
function getBand() {
$band_name=$_GET['band_name'];
return $band_name;
}
$pages=$_SESSION['pages'];
if(in_array($_GET['band_name'], $pages)) {
echo"Already in Array";
} else {
if (empty($_SESSION['pages']))
$_SESSION['pages'] = array();
$_SESSION['pages'][] = getBand();
$_SESSION['pages'] = array_slice($_SESSION['pages'], -4);
}
Use time () to get the time.
And store that in the desired array.
array_push ($array, time ());
Since you're talking about "the time they are added to the array" it could be that you mean microseconds which in that case use microtime ()
Note that both functions don't return a formatted timestamp, instead they return an integer.
More on time () here
More on microtime () here
Maybe something like this could do the work:
$test = "Metallica";
$test2 = "The Black Keys";
$arr['pages'][$test] = $test;
$arr['pages'][$test] = date("D M d, Y G:i");
$arr['pages'][$test2] = $test;
$arr['pages'][$test2] = date("D M d, Y G:i");
echo '<pre>'.print_r($arr, true).'</pre>';
For date format you can see - http://php.net/manual/bg/function.date.php
Cheers
class SessionManager
{
protected static $pages = null;
protected static $maxPages = 4;
public function __construct($session) {
self::$pages = $session['pages'];
}
public static function addPage($pageName) {
self::$pages[$pageName] = array(
'name' => $pageName,
'created' => date('Y-m-d h:i:s')
);
self::$pages = array_slice(self::$pages, -1 * $maxPages);
}
public static function writeSession(&$session) {
$session['pages'] = self::$pages;
}
public static function getPages() {
return self::$pages;
}
}
session_start();
$session = new SessionManager($_SESSION);
$session->addPage($_GET['band_name']);
$session->writeSession($_SESSION);
print_pre($session->getPages());

How to summarize multiple Intervals in PHP

In my app I can create projects and for each project I can record work reports. Each report has a start and an end timestamp. A table in the project description shows every report for this project and it also calculates the duration (with DateTime and the diff() function used between start and end timestamp). Now I want to calculate the total work time on the projects but I have no idea how I can do this. I already tried looping through all reports somehow and then use DateTime functions, but I'm getting nowhere... My last desperate attempt was this:
public static function calculateDuration($start, $end)
{
$start = date('Y-m-d H:i:s', $start);
$end = date('Y-m-d H:i:s', $end);
$s = new \DateTime($start);
$e = new \DateTime($end);
$interval = $e->diff($s);
return $interval->format('%H:%I');
}
public static function calculateTotal($idProject)
{
$reports = self::find('id_project = "' . $idProject . '"');
$totalReports = new \DateTime();
foreach ($reports as $report) {
$totalReports->add(new \DateInterval(self::calculateDuration($report->getStart(), $report->getEnd())));
}
/*echo '<pre>';
die(var_dump($totalReports));
echo '</pre>';*/
return $totalReports->format('H:I');
}
the calculateDuration functions works perfectly, but of course calculateTotal doesn't, because DateInterval does not take a string like "0:30". So that is completely useless...
I hope I provided all the needed information, just let me know if you need something else.
For clarity on my comments: You already have calculateDuration doing all the work, and it internally deals with a DateInterval object. So why not make use of it? Here, getInterval is a protected method that's used by both existing methods and returns the DateInterval object directly. Now calculateDuration becomes a simple formatting function, and calculateTotal has access to the DateInterval object.
protected static function getInterval($start, $end)
{
$s = new \DateTime('#' . $start);
$e = new \DateTime('#' . $end);
return $e->diff($s);
}
public static function calculateDuration($start, $end)
{
return self::getInterval($start, $end)->format('%H:%I');
}
public static function calculateTotal($idProject)
{
// ...
$totalReports = new \DateTime();
$totalReportsEnd = clone $totalReports;
foreach ($reports as $report) {
$totalReportsEnd->add(self::getInterval(
$report->getStart(),
$report->getEnd()
));
}
$totalInterval = $totalReportsEnd->diff($totalReports);
// do as you wish with the interval
}
Just create a valid DateInterval format instead of returning hours and minutes:
// Untested. Might need escaping.
return $interval->format('PT%HH%IM');

Converting a Mysql Result Object to Associative Array (CodeIgniter)

I'm trying to get a database query which is an object converted to an associative array, so that I can use it in the calendar class in codeigniter.
This is my model:
<?php
class Get_diary_model extends Model {
function getAllDiaries($year,$month) {
$data = $this->db->query("SELECT day AND entry FROM diary WHERE month=$month AND year=$year"); // the entries for the relevant month and year
foreach($data->result_array() as $row) { // return result as assoc array to use in calendar
echo $row['day'];
echo $row['entry'];
}
return $data;
}
}
and this is the error I get:
atal error: Cannot use object of type CI_DB_mysql_result as array in C:\wamp\www\mm\system\libraries\Calendar.php on line 219
Any ideas?
Check ou this video tutorial, it will help you -> http://net.tutsplus.com/tutorials/php/codeigniter-from-scratch-the-calendar-library/
Your model should look like this:
function getAllDiaries($year,$month)
{
$q = $this->db->query("SELECT day AND entry FROM diary WHERE month=$month AND year=$year");
if($q->num_rows() > 0):
foreach($q->result() as $row):
$data[] = $row;
endforeach;
return $data;
else:
return false;
endif;
}
and your controller:
function index($year = null, $month = null)
{
$this->load->model('Get_diary_model');
if (!$year) {
$year = date('Y');
}
if (!$month) {
$month = date('m');
}
$data['calendar'] = $this->Get_diary_model->getAllDiaries($year, $month);
}
The problem was not in your use of result_array(), more that you later return $data directly. $query = $this->db->query() then use $query->result_array() in the foreach. Then you can return $data after building it up in the foreach.
The other answer is a long-winded way of writing the following:
function getAllDiaries($year,$month)
{
$sql = "SELECT day AND entry FROM diary WHERE month=$month AND year=$year";
return $this->db->query($sql)->result();
}
But of course that will return an array of objects, not an multidimensional array.
Use below simple method,
$query = $this->db->get_where('table', array('table_id' => $id));
$queryArr = $query->result();
foreach ($queryArr[0] as $key=>$val)
{
$row[$key]=$val;
}
print_r($row); //this will give associative array
Here is the solution for CodeIgniter-3
function getAllDiaries(){
$query = $this->db->query("YOUR QUERY HERE");
return $query->result('array');
}
OR
function getAllDiaries(){
return $this->db->query("YOUR QUERY HERE")->result('array');
}
Note: result() function accept "array" or "object" as parameter. Default is "object"

Categories