Laravel Eloquent splitting query into array - php

Bit of a bad title, not quite sure how to research/describe what I'm trying to do.
I have a table called specifications with the fields
id, device_id, name, detail
Two rows for two different devices would for example be
1, 1, weight, 300kg
2, 2, weight, 250kg
Now the way I need to display it is in a single table compare both devices, essentially like this:
#foreach($specifications as $specification)
<tr>
<td>{{ $specification->name }}</td>
<td>{{ $specification->detailOne }}</td>
<td>{{ $specification->detailTwo }}</td>
</tr>
#endforeach
I'm having issues getting the right query or split the query in order to be able to go through the array like above. Anyone mind putting me on the right mindset? Do I query both specs and somehow resort it into an array I can use as above, or is there something else I should be looking at?

This should work for you
#foreach($specifications->groupBy('name') as $name => $specificationGrouped)
<tr>
<td>{{ $name }}</td>
#foreach($specificationGrouped as $specification)
<td>{{ $specification['detail'] }} ({{ $specification['device_id'] }})</td>
#endforeach
</tr>
#endforeach

Related

Laravel & PHP: Cannot reach array items without a trick, why is that?

Introduction to the problem
I have written a class to import a specific CSV file. This class handles everything except moving and reading the imported file. This is done in the controller by using de File facade in Laravel.
The description below only describes one of the arrays, but I use more arrays, and also in the class itself I get the same problem. The problem is that the app crashes with some obscure error everytime I try to access an item in the array by using a string as key value. I tested this in a seperate, non-laravel, php-file and there I don't get an error. It's only in my Laravel app. Strange thing is that I tested the arrays the following way:
a) using array_key_exists - No keys are found (I used both ' and ")
b) using array_keys - This time I get all the keys from the array
c) for example: $report['student_number'] - Doesn't work, I get an error here
d) for example: $report[array_keys($report)[0]] - This works
e) In vanilla PHP I do the same and there I do not get any errors.
The real code
In the controller I handle the upload the following way:
$uploaded_file = $request->file('uploadfile');
$uploaded_file->move(storage_path().'/files', $uploaded_file->getClientOriginalName());
$import_file = storage_path().'/files/'.$uploaded_file->getClientOriginalName();
if(File::exists($import_file) && File::isReadable($import_file)) {
$raw_file_data = File::get($import_file);
$import = ImportStudents::getInstance();
$import_result = $import->import($raw_file_data);
}
In the Import class I have a private property:
private $report = [];
I fill the array with data the following way:
$this->report[$student_number][] = [
'field' => $field,
'db_field' => 'student_number',
'new_value' => $value,
'old_value' => $student_number,
'action' => 'updated'
];
In the class I finaly return this array to the controller:
return $this->report;
In the controller I pass this array to the view:
return view('home.import_report')->with('report', $import_result);
In the blade file I use the following code:
#foreach($report as $report_row)
<td>{{ $report_row['field'] }}</td>
<td>{{ $report_row['db_field'] }}</td>
<td>{{ $report_row['new_value'] }}</td>
<td>{{ $report_row['old_value'] }}</td>
<td>{{ $report_row['action'] }}</td>
#endforeach
The error
The "C:\Windows\Temp\php57CD.tmp" file does not exist or is not
readable.
Remarks
Above is only one part in my code where I get the error. As I mentioned before, I also get the same error in the code of the class.
Specifications
Laravel: 6.x
PHP: 7.3.10
Question
What am I overlooking here? What is the problem?
The solution for the above mentioned problem with showing the report, how could I forget, that I needed an extra foreach loop.
Old code
#foreach($report as $report_row)
<td>{{ $report_row['field'] }}</td>
<td>{{ $report_row['db_field'] }}</td>
<td>{{ $report_row['new_value'] }}</td>
<td>{{ $report_row['old_value'] }}</td>
<td>{{ $report_row['action'] }}</td>
#endforeach
The answer was so obvious already in my own code :-(, this code:
$this->report[$student_number][] = [
'field' => $field,
'db_field' => 'student_number',
'new_value' => $value,
'old_value' => $student_number,
'action' => 'updated'
];
New code (solution)
#forelse($report as $student_number => $report_row)
<tr><td colspan="6" style="color: white; background-color: darkblue; padding: 0;"><h5>{{ $student_number }} - {{ $report_row[0]['name'] }}</h5></td></tr>
#foreach($report_row as $actions)
<tr>
<td></td>
<td>{{ $actions['field'] }}</td>
<td>{{ $actions['db_field'] }}</td>
<td>{{ $actions['new_value'] }}</td>
<td>{{ $actions['old_value'] }}</td>
<td>{{ $actions['action'] }}</td>
</tr>
#endforeach
#empty
<tr><td colspan="6">No changes</td></tr>
#endforelse
But this problem still exists with arrays
a) using array_key_exists - No keys are found (I used both ' and ")
b) using array_keys - This time I get all the keys from the array
c) for example: $report['student_number'] - Doesn't work, I get an error here
d) for example: $report[array_keys($report)[0]] - This works
e) In vanilla PHP I do the same and there I do not get any errors.
What's not working
$student->first_name = $imported_row['Roepnaam'];
But the key 'Roepnaam' does exist in the array.
With array_keys($imported_row) I can see that the key exists.
What is working
$student->first_name = $imported_row[array_keys($imported_row)[1]];
This what puzzles me!

Format number to K/M/B within blade template

I am using laravel 5.7.19.
Within my TableController.php controller I query data from my db and hand it over to the view:
public function index()
{
$c = DB::table('tick_data')
->select('*')
->join('basis', 'basis.Id', '=', 'tick_data.b_id')
->whereRaw('tick_data.id IN( SELECT MAX(tick_data.id) FROM tick_data GROUP BY tick_data.exchange_timestamp)')
->get();
return view('datatable')->with('coins', $c);
}
Within my table.blade.php file I am putting the data out:
#foreach ($coins as $key=>$c)
<tr>
<td>{{ ++$key }}</td>
<td>{{ $c->pair }}</td>
<td>{{ number_format($c->last_price, 8) }}</td>
<td>{{ number_format($c->price_change_percentage, 8) }}</td>
<td>{{ number_format($c->price_change, 8) }}</td>
<td>{{ number_format($c->high_price, 8) }}</td>
<td>{{ number_format($c->low_price, 8) }}</td>
<td>{{ $c->base_volume }}</td>
<td>{{ $c->name }}</td>
</tr>
#endforeach
As you can see I am mainly using the number_format() function for formatting my values.
However, base_volume comes in the form of 467703.0000000000 or 10831.13202978000 and I would like to change it to the shortform with K,M,B.
Is there any function in blade that can do this? What is a good way to preformat the numbers?
Appreciate your replies!
I don't know any blade functions that can do this. However, you can use the PHP Humanizer package for this. For example, from their documentation:
use Coduo\PHPHumanizer\NumberHumanizer;
NumberHumanizer::metricSuffix(-1); // "-1"
NumberHumanizer::metricSuffix(0); // "0"
NumberHumanizer::metricSuffix(1); // "1"
NumberHumanizer::metricSuffix(101); // "101"
NumberHumanizer::metricSuffix(1000); // "1k"
NumberHumanizer::metricSuffix(1240); // "1.2k"
NumberHumanizer::metricSuffix(1240000); // "1.24M"
NumberHumanizer::metricSuffix(3500000); // "3.5M"
The good thing about the package is, it also supports multiple locales.
Edit: There are also other alternative solutions as discussed here. This could be a better option for you if you just need to shorten numbers.

Laravel Blade - orderBy

I have this foreach loop in my blade template.
#foreach ($employee->projects->groupBy('stage') as $stage => $project)
<tbody>
<td>{{ $stage }}</td>
<td class="text-center">{{ count($project) }}</td>
</tbody>
#endforeach
Where it finds all the projects that the employee is involved in and groups them by what stage they are in (Waiting, In Progress, Launched). And then it lists the stages and the count of how many are in each stage. This works perfectly but they are not in the right order. I would like them in Waiting, In Progress, Launched. Currently it's in Launched, Waiting, In Progress.
How can I order them in my custom order?
SQL should be
SELECT ... FROM projects GROUP BY stage
ORDER BY stage = 'Waiting' DESC, stage = 'In Progress', ...
probably you need use similar to this
->order_by(DB::expr("stage = 'Waiting' DESC"))->order_by(...)
Ok figured this out. Here's what I did...
$projects = $employee->projects()
->groupBy('stage')
->select('stage', DB::raw('count(*) as total'))
->orderByRaw('case
when stage = "Waiting" then 1
when stage = "In Progress" then 2
when stage = "Launched" then 3
end')
->get();
Then in my blade template, I did...
#foreach ($projects as $project)
<tbody>
<td>{{ $project->stage }}</td>
<td class="text-center">{{ $project->total }}</td>
</tbody>
#endforeach
Hope this helps someone else.

Enumerating elements of a table

I have a table and I want to enumerate each element.
Something like this
#foreach($elements as $element)
<tr>
<td>{{ (isset($a))?$a++:($a = 1) }}</td>
<td>...
</tr>
#endforeach
I expect the table to begin with 1 and then count on, however, the first two columns are always 1. I have already solved this problem by giving the template an $a = 0; on the controller but I want to know why my first solution doesn't work and if there is a workaround
Laravel Blade has a very handy variable for loops, called the $loop variable. This lets you gather information about the current element of the list, including the index and iteration count.
So you can do just this:
#foreach($elements as $element)
<tr>
<td>{{ $loop->iteration }}</td>
<td>...
</tr>
#endforeach

How to: foreach without affecting every row?

Is there a way to do a foreach on for example your products and sort this by their category_id and show the category name above the products. (I'm using laravel 4 as framework)
Example what the output should look like:
Chairs
wooden chair number 1
pretty chair number 1
pretty chair number 2
Doors
tall door number 1
white door number 1
Key question: How can i make a foreach without having the categoryname above each row ?
Hopefully i made my question/problem clear and can someone help me out!
This is what i got so far:
Though, when i do my foreach in the blade i will get the error: " Undefined index "
The foreach i used in my controller:
foreach($results as $result) {
$category[$result->category_id][] = $result;
}
My foreach in the blade:
#foreach ($category as $key => $product)
<tr>
<td>{{ $product[$key]['created_at'] }}</td>
<td>{{ $product[$key]['order_id'] }}</td>
<td>{{ $product[$key]['name'] }}</td>
</tr>
#endforeach
you are attempting to use category_id to fetch $product from $products, which is array with 0-X indexes. for sake of simplicity i will ignore html formatting and syntax since i never used framework mentioned...
#foreach ($category as $key => $products)
echo 'Category #', $key
#foreach ($products as $product)
<tr>
<td>{{ $product['created_at'] }}</td>
<td>{{ $product['order_id'] }}</td>
<td>{{ $product['name'] }}</td>
</tr>
#endforeach
#endforeach
not completely sure i understand the question. but if im trying to organize an array.. i might use a conditional statement inside the foreach loop. I'm not sure your question is very clear.. see if this helps at all
foreach($results as $result) {
// just an example.. i narrow down what I push into my category array
if($result->type == 'whatever'){
$category[$result->category_id][] = $result;
}
}

Categories