I made a search method (GET) with some filters, the only problem that i have is when i run the search result i get the results with pagination with the adresse like :
search?q=&type_licence_id=&activite_licence_id=&structure_id=8
when i click on page 2 for exemple i have :
search?page=2
So it's display me anymore the results from the search query.
Maybe i done something wrong on my controller ? Hope someone could help me , thanks a lot in advance
here my controller :
public function search(Request $request)
{
$structure = Structure::select('num_structure', 'nom_structure' , 'id')
->get()
->mapWithKeys(function($i) {
return [$i->id => $i->num_structure.' - '.$i->nom_structure];
});
$activite = ActiviteLicencie::pluck('lb_activite' , 'id');
$type_licence = Type_licence::pluck('lb_type' , 'id');
$query = Licencies::query();
$filters = [
'type_licence_id' => 'type_licence_id',
'activite_licence_id' => 'activite_licencie_id',
'structure_id' => 'structure_id',
];
foreach ($filters as $key => $column) {
$query->when($request->{$key}, function ($query, $value) use ($column) {
$query->where($column, $value);
});
}
$licencies = $query->paginate(10);
return view('licencie/recherche', compact('licencies' , 'structure' , 'activite' , 'type_licence'));
}
I use the following in my blade template:
{{ $licencies->appends(Request::all())->links() }}
It appends all your request parameters to the pagination.
Check 'Appending To Pagination Links' on https://laravel.com/docs/5.4/pagination#displaying-pagination-results for information
You could customize the Pagination URL by
$licencies = $query->paginate(10);
$licencies->setPath($request->fullUrlWithQuery());
Docs:
https://laravel.com/docs/5.4/pagination#displaying-pagination-results
https://laravel.com/api/5.4/Illuminate/Pagination/LengthAwarePaginator.html#method_setPath
Related
I am working on a Laravel project. I am using Scout based on Algolia. Now, I cannot apply whereHas to the search.
I have a model called Place which has many to many relationships with Category with the following code.
class Place extends Model
{
use Searchable, Localizable;
protected $with = [
'images',
'phones',
'emails',
'categories'
];
protected $casts = [
'is_featured' => 'boolean'
];
public function categories()
{
return $this->belongsToMany(Category::class, 'place_category');
}
public function searchableAs()
{
return "places_index";
}
public function toSearchableArray()
{
$record = $this->toArray();
$record['_geoloc'] = [
'lat' => $record['latitude'],
'lng' => $record['longitude'],
];
unset($record['created_at'], $record['updated_at'], $record['latitude'], $record['longitude']);
return $record;
}
}
As you can see it will be indexed on Algolia.
I am searching based on geolocation and keyword using the following code.
Place::search($keyword, function ($algolia, $query, $options) use ($latitude, $longitude) {
$location = [
'aroundLatLng' => $latitude . ',' . $longitude,
'aroundRadius' => config('scout.algolia.search_radius'),
];
$options = array_merge($options, $location);
return $algolia->search($query, $options);
});
The code is working fine until I also tried to filter by category. I changed my code to something like this.
$query = Place::search($keyword, function ($algolia, $query, $options) use ($latitude, $longitude) {
$location = [
'aroundLatLng' => $latitude . ',' . $longitude,
'aroundRadius' => config('scout.algolia.search_radius'),
];
$options = array_merge($options, $location);
return $algolia->search($query, $options);
});
if ($category) {
$query = $query->whereHas('categories', function ($query) use ($category) {
$query->where('categories.id', $category);
});
}
As you can see now, I am now filtering by categories too using whereHas. When I run the code, I got the following error.
BadMethodCallException
Method Laravel\Scout\Builder::whereHas does not exist.
Literally, I cannot use whereHas with Algolia search. How can I fix it? Also, I am thinking of indexing the categories and filter the records on the Algolia side.But I am going to be filtering by id. How can I customise the query for it?
public function index(Request $request)
{
$search_book = $request->id;
$proc=DB::select(DB::raw("SELECT * FROM BOOKS WHERE BOOKID = '$Search_book'")
if ($search_book!="") {
return response()->json($proc);
return view('status.status',[
'proc' => $proc
]);
}
How to return 2 data
To determine if a request is an ajax request, you can use the ajax() method on a Request object injected into the controll action:
public function index(Request $request)
{
$results = DB::table('books')
->where('bookid', $request->id)
->get();
if ($request->ajax()) {
return response()->json($results);
}
return view('status.status', [
'proc' => $results
]);
}
I went ahead and fixed the SQL injection vulnerability in your query for you by swapping the query for a proper one. It could still be improved by using a Book model instead of a plain database query, but it is fine this way as well.
The query from your comment can be simplified by replacing the left join. Simply take the sub query as base and right join it with processspj:
DB::table('processtrans as pt')
->leftJoin('processmaster as pm', 'pm.pcm_id', '=', 'pt.pct_pcm_id')
->rightJoin('processspj as ps', 'ps.pc_id', '=', 'pt.pct_pc_id')
->where('pt.pct_pc_id', $request->id)
->select([
'ps.*',
'pm.pcm_bname',
'pt.created_at',
'pt.updated_at',
'pt.pct_id',
'pt.pct_leadtime',
'pt.pct_pcm_id',
'pt.pct_pc_id',
'pt.pct_planfinishdate',
'pt.pct_startdate',
'pt.pct_status',
])
->get();
$(document).ready(function(){
$("#dl_books").change(function()
{
var getValue=$(this).val();
$.ajax({
type: 'GET',
url: '{{route('status')}}',
data: {id:getValue},
success:function(data)
{
//Json for value textbox
$("#txtbookname").text(data[0].pcm_bname);
}
});
});
});
Just save the rendered view in a variable and do a json response:
public function index(Request $request) {
$results = DB::table('books')
->where('bookid', $request->id)
->get();
if ($results) {
$view = view('status.status', [
'proc' => $results
])->render();
return response()->json(['view'=> $view, 'proc' => '$results']);
}
}
enter code hereMy question about the combination filters in laravel by using eloquent.
I am trying to filter with a combination of the following:
username
Category
Sub_category
started_at
created_at
status
I use where conditions but it not working as required.
public function filter(Request $request, User $user)
{
$user = $user->newQuery();
// Search for a user based on their name.
if ($request->has('username')) {
$user->where('name', $request->input('username'));
}
// Search for a user based on their Category.
if ($request->has('Category')) {
$user->where('Category', $request->input('Category'));
}
// Search for a user based on their Sub_category.
if ($request->has('Sub_category')) {
$user->where('Sub_category', $request->input('Sub_category'));
}
// Search for a user based on their started_at.
if ($request->has('started_at')) {
$user->where('started_at', $request->input('started_at'));
}
// Search for a user based on their status.
if ($request->has('status')) {
$user->where('status', $request->input('status'));
}
// Continue for all of the filters.
// Get the results and return them.
return $user->get();
}
You should save your where conditions to the $user variable.
$user = $user->where($dbField, $request->input($requestParam));
For improved readability, I'd suggest using a loop with all of your filtering cases.
public function filter(Request $request)
{
$users = User::query();
$filters = [
'username' => 'name',
'Category' => 'Category',
'Sub_category' => 'Sub_category',
'started_at' => 'started_at',
'status' => 'status'
];
foreach ($filters as $requestParam => $dbField){
if ($request->has($requestParam)) {
$users = $users->where($dbField, $request->input($requestParam));
}
}
return $users->get();
}
Bear in mind $request->has does not check whether the parameter value is empty, use $request->filled if you wish so.
This is My examle refer this
public function filter(Request $request)
{
$q = User::query();
$email = $request->input('email');
$username= $request->input('username');
$q->when($email,function ($query) use ($email){
$query->where('email',$email);
});
$q->when($username,function ($query) use ($username){
$query->where('username',$username);
});
$results = $q->get();
//code
}
I have a search function with multiple parameters who seems to not work everytimes on each params for exemple i tested the search query with one param "etat_paiement = 0 ",
normaly i should have no results but i still have one but in the database this record have etat_paiement = 1
where i made a mistake ? thanks a lot in advance
here the code :
$query = EngagementOrder::query();
$filters = [
'structure_engagement_id' => 'structure_id',
'saison_id' => 'saison_id',
'etat_paiement' => 'etat_paiement',
'bl_comptabilite' => 'bl_comptabilite',
];
foreach ($filters as $key => $column) {
$query->when($request->{$key}, function ($query, $value) use ($column) {
$query->where($column, $value);
});
}
$engagements = $query->paginate(10);
in my debug bar i have the query like :
select * from engagement_order limit 10 offset 0
but i run the search with the url like :
https://mydomaine/engagements?etat_paiement=0
UPDATE : here my select box :
{!! Form::select('etat_paiement', array('1' => 'Facture Réglée' , '0' => 'Facture Non Rélgée') , null , ['class' => 'form-control select2 ', 'placeholder' => 'Selectionnez un type de réglement']) !!}
The problem is with the laravel's when method. When you are passing "0" as the first argument to the when function, the below is invoked with the value as "0", which is resolving to be false in this condition: if ($value)
public function when($value, $callback, $default = null)
{
if ($value) {
return $callback($this, $value) ?: $this;
} elseif ($default) {
return $default($this, $value) ?: $this;
}
return $this;
}
Instead of using when, you can generate the query like this:
foreach ($filters as $key => $column) {
if ($request->has($key)) {
$query->where($column, $request->{$key});
}
}
If you want to use when, change your code to
foreach ($filters as $key => $column) {
$query->when($request->has($key), function ($query, $value) use ($column,$key, $request) {
$query->where($column, $request->$key);
});
}
You may try exists instead of $request->{$key} for example:
$request->exists($key)
In your case $request->{$key} is evaluating to false because etat_paiement=0 has a falsy value. On the other hand, the exists will check if the query parameter/$key is present regardless of the value.
I'm using Laravel Excel from maatwebsite but i have a problem with export data to xls file. I have this query but i don't need to show all columns in the xls file but i need to select all this columns to do operations before download the file. In my select i have 8 columns but in my headers i just have 7 to show but this doesn't work because the 8ª column appears too.
MY FUNCTION:
public function toExcel($id) { $b = Budget::find($id);
$budget = Budget_Item::join('budgets', 'budget__items.id_budget', '=', 'budgets.id')
->join('items_sizes', 'budget__items.id_itemSize', '=', 'items_sizes.id')
->join('items', 'items_sizes.id_item', '=', 'items.id')
->join('material_types', 'items_sizes.id_materialType', '=', 'material_types.id')
->select('items.reference AS Referência', 'items.name AS Descrição', 'items_sizes.size AS Tamanho', 'material_types.material_type AS Material', 'budget__items.amount AS Quantidade', 'items_sizes.unit_price AS Val.Unitário', 'budget__items.price AS Val.Total', 'budget__items.purchasePrice')
->where('id_budget', '=', $id)
->get();
$budgetUpdate = [];
$budgetUpdate[] = ['Referência', 'Descrição', 'Tamanho', 'Material', 'Quantidade', 'Val.Unitário', 'Val.Total'];
foreach ($budget as $key)
{
if ($key->purchasePrice > 0)
{
$key->unit_price = $key->purchasePrice;
}
$budgetUpdated[] = $key->toArray();
}
Excel::create('Proposta_'.$b->reference, function($excel) use($budgetUpdated)
{
// Set the title
$excel->setTitle('Proposta');
$excel->sheet('Sheetname', function($sheet) use($budgetUpdated)
{
$sheet->fromArray($budgetUpdated, null, 'A1', false, true);
});
})->download('xls');}
How can i solve that?
Thank's
Tested on Laravel excel 3.1 docs
on controller
public function exportAsCsv()
{
return Excel::download(new MyExport, 'invoices.xlsx');
}
on MyExport, look at the map function
class MyExport implements FromCollection, WithHeadings, WithMapping{
public function collection(){
return MyTable:all();
}
// here you select the row that you want in the file
public function map($row): array{
$fields = [
$row->myfield2,
$row->myfield1,
];
return fields;
}
}
also check this
For what its worth I ran into a similar issue and didnt find much in terms of a fix so heres my solution.
1. I query the DB in the callback and get all the data I need.
2. I then go over the collection and create a new array on each iteration and assign a value & header. Works great for picking out columns from a model
Excel::create('User List Export', function($excel) {
$excel->sheet('Users', function($sheet) {
$email = yourModelGoesHere::all();
foreach ($email as $key => $value) {
$payload[] = array('email' => $value['email'], 'name' => $value['name']);
}
$sheet->fromArray($payload);
});
})->download('xls');
You can try this way.
$user_id = Auth::user()->id
Excel::create('User', function($excel) use ($user_id){
$excel->sheet('Sheet', function($sheet) use($user_id){
$user = User::where('user_id', $user_id)->select('name', 'email', 'role', 'address')->get();
});
})->export('xls');
return redirect('your route');