Displaying single item in Laravel - php

I am having a hard time to get over this. Try to display a a single item by ID from database. I set the controller and route, but couldn't make it. Getting error or getting no data by the changes that I make on my show.blade
This is my whole controller:
public function welcome()
{
$estates = array();//here
$data['estates'] = $estates;
return view('welcome', $data);
}
public function search(Request $request)
{
$q = $request->q;
$estates = \DB::table('allestates')
->where("building_name", "LIKE", "%" . $q . "%")
->orWhere("address", "LIKE", "%" . $q . "%")
->orWhere("company_name", "LIKE", "%" . $q . "%")
->orWhere("region", "LIKE", "%" . $q . "%")
->orderBy('price')->paginate(10);
return view("search", compact('estates', 'q'));
}
public function show(allestates $allestates)
{
$estates = allestates::where('id', $allestates->id)->first();
//dd($estates);
if($estates){
return view('pages.show', ['estates' => $estates]);
}else{
return 'no records found';
}
}
Show function must be the problem, but what is the problem I couldn't figure it out.
This is the route:
Route::get("/", "PagesController#welcome");
Route::any("/search", "PagesController#search")->name('search.route');
Route::get('pages/{id}', 'PagesController#show');
And this is the show.blade.
<tbody>
<tr class="even">
<td>{{$estates->building_name}}</td>
</tr>
</tbody>
An this is the main.blade:
#foreach($estates as $estate)
<tr class="even">
<td>{{str_limit($estate->company_name, $limit = 20)}}</td>
<td>{{str_limit($estate->building_name, $limit = 20)}}</td>
<td>{{str_limit($estate->address, $limit = 22)}}</td>
<td>{{str_limit($estate->price, $limit = 20)}}</td>
<td class="price-hidden">{{$estate->old_price}}</td>
<td>{{str_limit($estate->extend, $limit = 20)}}</td>
<td>{{str_limit($estate->rooms, $limit = 20)}}</td>
<td>{{str_limit($estate->entry, $limit = 20)}}</td>
</tr>
#endforeach
ID returning null. but there is ID!

it's because laravel didn't find any record matching your query.
try using findOrFail in querying single record. this would return an error if no record is found.
$estates = allestates::findOrFail($id);
another way is to check wether the query is successful:
public function show($id)
{
$estates = allestates::where('id', $id)->first();
if($estates){
return view('pages.show', ['estates' => $estates]);
}else{
return 'no records found';
}
}
EXPLANATION
the $id paramater inside public function show($id) uses the {id} parameter in your route Route::get('pages/{id}', 'PagesController#show');
laravel will search the database based on the id you place in yoursite.com/pages/{id}

Related

Can you output a button via controller in Laravel?

I have a live search via my controller method and it outputs the results but I want to have a button for editing present too
what I have tried:
function action(Request $request)
{
if ($request->ajax()) {
$output = '';
$query = $request->get('query');
if ($query != '') {
$data = DB::table('customers')
->where('id', 'like', '%' . $query . '%')
->orWhere('email', 'like', '%' . $query . '%')
->orWhere('name', 'like', '%' . $query . '%')
->orderBy('id', 'desc')
->get();
} else {
$data = DB::table('customers')
->orderBy('is', 'desc')
->get();
}
$total_row = $data->count();
if ($total_row > 0) {
foreach ($data as $row) {
$output .= '
<tr>
<td>' . $row->id . '</td>
<td>' . $row->email . '</td>
<td>Edit</td>
</tr>
';
}
} else {
$output = '
<tr>
<td align="center" colspan="5">No Data Found</td>
</tr>
';
}
$data = array(
'table_data' => $output,
'total_data' => $total_row
);
echo json_encode($data);
}
}
Edit: Added the full method.
Note. this live search should not refresh the page, rather replace values
I highly recommend you do a lot of refactoring and read some more of the Laravel docs.
I've done some refactoring, I haven't tested, and there is a lot more work you'll need to do (I can't do it for you, I don't have enough information).
We'll start with the controller.
public function action(Request $request)
{
if (!$request->ajax()) {
return;
}
$customers = DB::table('customers')
->orderBy('id', 'desc');
if ($request->has('query')) {
$query = '%' . $request->get('query') . '%';
$customer = $customer->where('id', 'LIKE', $query)
->orWhere('email', 'LIKE', $query)
->orWhere('name', 'LIKE', $query);
}
$customers = $customers->get();
return view('path.to.view', compact(
'customers'
));
}
Let's walk through the changes.
I utilised the "early returns" code practice. This means that we don't wrap the entire method in an if statement, but rather exit out early out of the method.
It is far easier to read this way.
Renamed $data to $customers. This is a simple change but makes your code easier to read. (Can you see the theme here)?
Moved the duplication of the query builder out of the if statement. It's a "builder", so we can build part of the query that is the same. This code practice is called "DRY" or Don't Repeat Yourself.
Then we check if the $request has a specific key. This is just keeping our code very Laravel-centric.
Now we add to the $customers query builder with the query from $request.
Don't forget to call get() to 'get' all the records from the database. If the request didn't contain query, this part will still be run as normal.
Return a Laravel view, and pass in our $customers Collection. In Laravel, paths are separated by dots / . / full stops / periods.
At this point, you'll need to change how your AJAX query works and returns data.
I can't do this for you. Please attempt to do it yourself, and if you can't then open a new question.
Okay, so it's time to create our view (rather than returns that abhorrent string)!
<table>
#forelse ($customers as $customer)
<tr>
<td>{{ $customer->id }}</td>
<td>{{ $customer->email }}</td>
<td>
Edit
</td>
</tr>
#empty
<tr>
<td align="center" colspan="5">No Data Found</td>
</tr>
#endforelse
</table>
Laravel Blade templates provide a very useful directive called forelse which lets you iterate over an iterable, and if the iterable contains no elements, then it runs a separate section of code.
As you can see, this is a much better approach than counting records and doing this yourself.
One final thing, I highly recommend using named routes and replacing:
url("cust-edit/".$customer->id)
with
route("customer.edit", ["customer" => $customer])
// or
route("customer.edit", compact('customer'))
I'll give you a hint for the route.
It won't include type hinting of models, because it doesn't look like you use models.
Route::name('customer')->prefix('customer.')->group(function () {
Route::get('/cust-edit/{customer}', function ($customer) {
$customer = DB::table('customer')->where('id', $customer)->first();
// code...
})->name('edit');
});

Laravel - sum searched posts price

How can I sum price only for posts that I searched? I have a search page and search is for date, so I search posts by a date. And when I type date that I want I need to sum all posts prices that my search function find for that date. Here is my code.
This is my search in web.php:
Route::get('/search', 'PagesController#search');
Route::post('/search',function(){
$q = Input::get ( 'q' );
$post = auth()->user()->posts()->where('ime','LIKE', '%'.$q.'%')->get();
if(count($post) > 0)
return view('search')->withDetails($post)->withQuery ( $q );
else return view ('search')->withMessage('Nema rezultata Vaše pretrage. Probajte ponovo!');
});
And this is my search function in PagesController:
public function search(){
$user_id = auth()->user()->id;
$user = User::find($user_id);
return view('search')->with('posts', $user->posts);
}
And this is my search.blade.php with table footer where is should sum my posts price:
<tfoot>
<tr>
<th>UKUPAN IZNOS: {{ Auth::user()->posts()->sum('cijena') }}€</th>
</tr>
</tfoot>
but when I type this it sums me price for all posts, and I just need for the searched ones. Any suggestions?
... but when I type this it sums me price for all posts, and I just need for the searched ones
This is because you have this line in your view:
<th> ... {{ Auth::user()->posts()->sum('cijena') }} ... </th>
This is executing a different query directly to get the total sum of the cijena. So, regardless of if you constraint your results or not this will keep output the same vale. This different query has any impact on the rest of the queried values.
What you could do is to calculate that value in the main query and return it to the view:
Route::post('/search', function () {
$q = Input::get('q');
$posts = auth()->user()->posts()->where('ime', 'LIKE', '%' . $q . '%')->get();
if (count($posts) > 0)
{
$sum = $posts->sum('cijena'); // <---
return view('search')->withDetails($posts)->withTotal($sum);
} // ^^^^^^^^^^^^^^^^^
else
{
return view('search')->withMessage('Your error message goes here!');
}
});
So now you'll have access to an extra variable $total in your blade file:
<th> ... {{ $total) }} ... </th>
Also, there is no need to define two routes for the same operation, you could reduce all that in one simple method. Additional, you shouldn't execute queries from your front-end. Do as follows:
# web.php
Route::get('/search', 'PagesController#search');
Then in your controller:
# PageController.php
use Illuminate\Http\Request;
// ...
public function search(Request $request)
{
$posts = auth()
->user()
->posts()
->when($request->has('q'), function ($q) { // first check if there is a query
return $q->where('ime', 'LIKE', '%' . request('q') . '%'); // if so, apply filter
})
->get();
if (count($posts) > 0) // checking if there is enough posts..
{
$sum = $posts->sum('cijena'); // if so get the sum of 'cijena'
return view('search')->withDetails($posts)->withTotal($sum);
} // ^^^^^^^^^^^^^^^^
else
{
return view('search')->withMessage('Your error message goes here!');
}
}
Update
This line is the one that throws the error:
<p class="searchp">Rezultati vaše pretrage <b> {{$q}} </b>: </p>
This is because I didn't include a $q variable. Just append it to your response in case you need it:
// ...
return view('search')->withDetails($posts)->withTotal($sum)->with('q', request('q'));
// ...

Laravel - How to export Excel data with Eloqeunt relationship from view?

I'm currently using "maatwebsite/excel": "3.1.10", recently switched from 2.x version, and I'm having a problem with displaying excel data from view that is using Eloquent relationship. Here's all my code below.
UsersEarningHistory.php:
<?php
namespace App\Exports;
use App\EarningHistory;
use Illuminate\Contracts\View\View;
use Maatwebsite\Excel\Concerns\FromView;
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Events\AfterSheet;
use Maatwebsite\Excel\Concerns\WithMapping;
class UsersEarningHistory implements FromView, ShouldAutoSize, WithEvents, WithMapping
{
protected $history;
public function __construct($history = null)
{
$this->history = $history;
}
public function view(): View
{
return view('admin.commission.excel_table', [
'history' => $this->history ?: EarningHistory::all()
]);
}
public function registerEvents(): array
{
return [
AfterSheet::class => function(AfterSheet $event) {
$cellRange = 'A1:W1'; // All headers
$event->sheet->getDelegate()->getStyle($cellRange)->getFont()->setSize(14)->setBold($cellRange);
},
];
}
}
UserController where my method for exporting data is:
public function index(Request $request)
{
//
$active = $this->active;
$active[1] = 'commission';
view()->share('active', $active);
$breadcrumbs = [
['link' => '/admin', 'text' => 'Administration'],
['text' => 'Commission']
];
view()->share('breadcrumbs', $breadcrumbs);
$styles[] = '//cdn.jsdelivr.net/bootstrap.daterangepicker/2/daterangepicker.css';
view()->share('styles', $styles);
$scripts[] = '//cdn.jsdelivr.net/momentjs/latest/moment.min.js';
$scripts[] = '//cdn.jsdelivr.net/bootstrap.daterangepicker/2/daterangepicker.js';
$scripts[] = '/js/admin/commission.js';
view()->share('scripts', $scripts);
$history = new EarningHistory();
if ($request->filled('q')) {
$history = $history->whereHas('user', function ($query) use ($request) {
$query->where('username', 'like', '%' . $request->q . '%');
});
}
if ($request->filled('qn')) {
$history = $history->whereHas('user', function ($query) use ($request) {
$query->where('first_name', 'like', '%' . $request->qn . '%');
$query->orWhere('last_name', 'like', '%' . $request->qn . '%');
if (strpos( $request->qn, ' ') !== false) { // is both
$both = explode(" ",$request->qn);
if(isset($both[0]))
$query->orWhere('first_name', 'like', '%' . $both[0] . '%');
if(isset($both[1]))
$query->orWhere('last_name', 'like', '%' . $both[1] . '%');
}
});
}
if($request->filled('has_correct_ratio')) {
$history = $history->where('has_correct_ratio', $request->filled_correct_ratio);
}
if (!$request->filled('null')) {
$history = $history->where(function ($query) {
$query->where('personal_balance', '!=', 0)
->orWhere('group_balance', '!=', 0);
});
}
if ($request->filled('date')) {
$history = $history->whereBetween('created_at', [Carbon::parse('01.' . $request->date)->firstOfMonth(),
Carbon::parse('01.' . $request->date)->addMonth()->firstOfMonth()]);
}
if ($request->filled('export')) {
$date = $request->filled('date') ? 'Earning history for ' . Carbon::parse('01.' . $request->date)->format('F') :
'Earning history for all time';
return Excel::download( new UsersEarningHistory($history), $date.'history.xls');
}
$data['history'] = $history->paginate(15);
$data['request'] = $request;
return view('admin.commission.index', $data);
}
Export table blade:
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Name</th>
<th>Month</th>
<th>Amount</th>
<th>World Bonus</th>
<th>Total amount</th>
<th>Personal points</th>
<th>Group points</th>
{{--<td></td>--}}
</tr>
</thead>
<tbody>
#foreach($history as $obj)
<tr>
<td>
{{ $obj->user->first_name . ' ' . $obj->user->last_name }}
</td>
<td>{{$obj->created_at->format('F')}}</td>
<td>€{{ number_format($obj->personal_balance + $obj->group_balance, 2)}}</td>
<td>€{{ number_format($obj->world_bonus, 2)}}</td>
<td>€{{ number_format($obj->personal_balance + $obj->group_balance + $obj->world_bonus, 2)}}</td>
<td>
{{ intval($obj->personal_points) }}
</td>
<td>
{{ intval($obj->group_points) }}
</td>
<td>
{{ App\User::$_RANK[$obj->rank]['title'] }}
</td>
{{--<td align="center">--}}
{{--<a href="/admin/payouts/{{$obj->id}}" class="btn btn-primary btn-xs">--}}
{{--<i class="icon-eye"></i>--}}
{{--</a>--}}
{{--<!--TODO Prikaži akciju na osnovu trenutnog statusa-->--}}
{{--#if($obj->status=='pending')--}}
{{--<a href="javascript:;" class="ajax-action btn btn-sm btn-success" data-action="/ajax/payout-change-status" --}}
{{--data-obj-id="{{$obj->id}}" data-status="approved">#lang('form.approve')</a>--}}
{{--<a href="/admin/payouts/reject/{{$obj->id}}" class="btn btn-sm btn-danger" >#lang('form.reject')</a>--}}
{{--#endif--}}
{{--</td>--}}
</tr>
#endforeach
</tbody>
</table>
As you can see, I'm trying to get user name from his earning history, but when I try to export data, my excel file is empty, but it's not giving me any errors.
Note: EarningHistory is related with User model:
//EarningHistory model
public function user()
{
return $this->belongsTo('App\User', 'user_id', 'id')->withTrashed();
}
//User model
public function earning_history()
{
return $this->hasMany('App\EarningHistory');
}
Found a solution. My $history variable in UserController was returning Query builder, because I forgot to add ->get(); method :
return Excel::download( new UsersEarningHistory($history->get()), $date.'history.xls');
Now everything works as it should.

Pagination coming from AJAX request not working properly -- Laravel 5.6

I'm using Laravel 5.6 -- Jquery Ajax
Here's the point
I'm having a search input placed in my navbar there's an eventlistener('keyup') on it.
Everytime keyup is fired, an AJAX GET request is send to
url : '{{action('PostController#searchAdmin')}}'
From web.php : Route::get('/search/admin', 'PostController#searchAdmin');
I made the return of that action a partial with data
return view('back.partials.searchResult', ['posts' => $posts, 'trashed' => $trashed]);
And I replace the content of the main tag with that partial
Everything is working properly except when the result count is greater than 10 (the breakpoint of pagination).
Pagination control links are all pointing to "search/admin?page=x" and when I click on it, this error is showing
Undefined variable: posts
I used $posts->links() to show the controls
I found a solution so I post it
In web.php
Route::get('/search', function(Request $request) {
$search = $request->search;
$trashed = Post::trash()->count();
$posts = Post::notTrash()
->where('title', 'like', '%' . $search . "%")
->orWhere('post_type' , 'like', '%' . $search . '%')
->paginate(10);
$posts->withPath('?search=' . $search);
return view('back.partials.searchResult', ['posts' => $posts, 'trashed' => $trashed, 'search' => $search]);
});
This code was for test purpose and will be soon exported in a new controller called SearchController
In my PostController
public function index(Request $request)
{
// GET parameters
$paginate = $request->input('paginate') ?? 10;
$search = $request->input('search') ?? null;
if($search !== null) {
$posts = $this->checkCategories($paginate, $search);
} else {
$posts = Post::notTrash()->orderBy('id', 'ASC')->paginate($paginate);
}
$trashed = Post::trash()->count();
$posts->withPath('?search=' . $search);
return view('back.index', ['posts' => $posts, 'trashed' => $trashed, 'search' => $search]);
}
Working with
private function checkCategories($paginate, $search)
{
$categories = Category::all();
foreach ($categories as $category) {
if(strpos(strtolower($category->name), $search) === false) {
// #TODO: Change for stripos
$posts = Post::notTrash()
->where('title', 'like', '%' . $search . '%')
->orWhere('post_type', 'like', '%' . $search . '%')
->paginate($paginate);
} else {
return Category::find($category->id)->posts()->paginate($paginate);
}
}
return $posts;
}
The index method now accept Request to handle get parameters when they are some.
In my views
#if($search !== null)
{{ $posts->appends($search)->links() }}
#else
{{ $posts->links() }}
#endif
Now replace
{{ $posts->links() }}
The solution was $var->**withPath()** and handling GET parameters

Laravel if request not empty add orWhere

public function index(Request $request) {
if ($request->has('deleted')) {
$assistants = Assistant::onlyTrashed()->where(1);
if ($request->has('firstName'))
$assistants = $assistants->orWhere('firstname', 'LIKE', $request->firstName.'%');
if ($request->has('lastName'))
$assistants = $assistants->orWhere('lastname', 'LIKE', $request->lastName.'%');
if ($request->has('email'))
$assistants = $assistants->orWhere('email', 'LIKE', $request->email.'%');
} else {
$assistants = Assistant::all()->where(1);
if ($request->has('firstName'))
$assistants = $assistants->orWhere('firstname', 'LIKE', $request->firstName.'%');
if ($request->has('lastName'))
$assistants = $assistants->orWhere('lastname', 'LIKE', $request->lastName.'%');
if ($request->has('email'))
$assistants = $assistants->orWhere('email', 'LIKE', $request->email.'%');
}
return $this->showAll($assistants);
}
I am trying to check if firstName, lastName or email is not empty, add to query with LIKE command.
But it returns an error :
Type error: Too few arguments to function
Illuminate\Support\Collection::where(), 1 passed
in Laravel 5.6.
You have multiple problems.
where(1) is not a valid Query Builder call. You also don't seem to need this.
You don't need to repeat all of these request->has() calls, put them below the if ... else ...
Assistants::all() will actually run a query and return all rows in a collection. Use Assistants::query() to return a Query Builder instance.

Categories