Modify Variables in Laravel Package from outside - php

I have a Laravel Package where I filter Users that are fetched from the database with a User Eloquent Model. So I have something like
if ($request->get('search')) {
User::where('email', 'like', '%' . $search . '%')
->orWhere('first_name', 'like', '%' . $search . '%')
->orWhere('name', 'like', '%' . $search . '%')
...
Now I want to add ore preprocess some filters on the Users before this is done from the project itself. What first came to my mind is to fire an event like
event(new UserFilterStart($users));
where I modify Users before i run the filters. So the code would look like this:
$users = User::all();
event(new UserFilterStart($users));
if ($request->get('search')) {
$users->where('email', 'like', '%' . $search . '%')
->orWhere('first_name', 'like', '%' . $search . '%')
->orWhere('name', 'like', '%' . $search . '%')
I did not manage to hand over the variable by reference, so i can manipulate it. Which is probably a good thing, because then this might have been my final solution.
I get that it is not the way Events should be used and I am looking for alternatives. How can I achieve to inject/modify the code from the package? Considering that I own this package.

Ok, it turned out that it just works fine with the Event. I just made a mistake somewhere else. Are there any real shortcomings if I use Events like that?

Related

Laravel 8 Two Table Where Search

My Code;
$posts=Term::where('user_id',$user_id)->where('status',1)->where('type','product')->with('preview','attributes','category','price','options','stock','affiliate')->withCount('reviews');
if(!empty($request->term)){
$data= $posts->where('title','LIKE','%'.$request->term.'%');
}
This my code searches for title from term table. But I want to search from another table without breaking the structure. So Example;
if(!empty($request->term)){
$data= $termTABLE->where('title','LIKE','%'.$request->term.'%');
$data= $stockTABLE->where('code','LIKE','%'.$request->term.'%');
}
Since I don't know about Laravel, I couldn't explain it fully. I hope I get help. Thanks.
Good Luck
The below example is not like yours' but you can sort it out according to your need.
For example, if user has a company you can search in the company table like
$user->where('name', 'LIKE', '%' . $searchPhrase . '%') //Searching in user table
//Searching in user table
->orWhere('email', 'LIKE', '%' . $searchPhrase . '%')
//Checking if company exist
->orWhereHas('company', function ($query) use ($searchPhrase) {
//Searching in company table
$query->where('name', 'LIKE', '%' . $searchPhrase . '%');
});

Prevent or skip rendering of symbols and entities Laravel / PHP

I have this function in my controller:
if ($request->get('query')) {
$query = $request->get('query');
$data = DB::table('users')
->where('is_archive', '=', 0)
->where(function($string) use ($query) {
$string->where('first_name', 'LIKE', '%' . $query . '%')
->orWhere('last_name', 'LIKE', '%' . $query . '%')
->orWhere('church_id', 'LIKE', '%' . $query . '%');
})
->get();
}
What it does is a real-time search result that is listing same exact results as you type a letter. Same as the search bar of google that every time when you type a letter. it will show results that is the same as the currently typed text. I wish to put security features that will prevent the rendering of <, >, ', " etc. but it will accept space (spacebar) character. What I have done so far is:
$sanitizedQuery = strtolower(trim(preg_replace('/\s+/', '', $query)));
but I seem to fail to achieve my desired outcome. Any suggestion is highly appreciated.

Laravel Eloquent loads slow

there is a lot of similar topics but couldn't find a solution for me. This query loads very slow.
public function getAllBids()
{
return Bid::with('user', 'group')
->join('auct_lots', function ($join) {
$join->on('bids.lot_id', '=', 'auct_lots.lot_id')
->where('auct_lots.company', 'LIKE', '%' . request('brand') . '%')
->where('auct_lots.model_name', 'LIKE', '%' . request('models') . '%')
->where('auct_lots.grade_en', 'LIKE', '%' . request('carGrade') . '%')
->where('auct_lots.auction_name', 'LIKE', '%' . request('auctions') . '%')
->where('auct_lots.model_type_en', 'LIKE', '%' . request('chassis') . '%')
->where('auct_lots.bid', 'LIKE', '%' . request('lots') . '%')
->where('auct_lots.lot_date', 'LIKE', '%' . request('date') . '%');
})
->orderBy('auct_lots.' . request('order_column'), request('order_type'))
->paginate(30);
}
I think the problem is that auct_lots has more than 40,000 records... But I'm not sure how to refactor this code to work faster.
When you are having large amount of data, it is better to use server side caching. This will improve performance very much faster.
Step 1: Create a Trait and write logic for store values in caching.
Ex:
trait Student{
public function storeStudentDataInCache(){
$students = Cache::rememberForever('studentList', function () {
return Student::
with(['class', 'exams'])
->where('is_published', 1)->orderBy('display_sequence', 'ASC')->get();
});
return $students;
}
}
Now in your controller call this method, this will return collection of data. So you do not need run sql queries all the time to get data. This method will run query only after one time. After that data will be stored in caching so it will get data's collection from caching text file.
Note: Whenever you update your data,please do not forget to delete this cache.
And you can also apply where condition for laravel collection or you can use filter method of collection to implement more filter logic.

How to use count and orderBy on eloquent multiple relationship fields?

What I'm trying to do is setup a server side configuration for a table data. So I have a model CounterLog that has 3 relationships set [belongsTo] category, location, user. I want a query to filter all CounterLog data including relationships, with offset, limit and orderBy methods set and in the same time retrieve all the filtered rows ignoring offset and limit. Here is what I managed until now and maybe understand better what I want:
$search_query = function($q) use ($search) {
$q->where('name', 'like', '%' . $search . '%');
};
$query = CounterLog::where('created_at', 'like', '%' . $search . '%')
->orWhereHas('category', $search_query)
->orWhereHas('location', $search_query)
->orWhereHas('user', $search_query);
$logs = $query->offset($offset)->limit($limit)->get();
$logs_total = $query->offset(0)->count();
In the last line I'm using $query->offset(0) because for some reason if offset is set to a number $logs_total becomes 0. I'm not sure this is the proper way to do it.. but even like this I have no idea how to use orderBy for ex. category.name.
I know I can always use raw queries in eloquent but I want to know if there is a way to use ORM and relationships. I would really appreciate if you could help me with this..cuz the struggle is real.
Thanks a lot :)
Apparently I haven't got a solution with ORM so I did it with "raw" queries:
$query = $this->db->table('counter_logs')
->leftJoin('categories', 'counter_logs.category_id', '=', 'categories.id')
->leftJoin('locations', 'counter_logs.location_id', '=', 'locations.id')
->leftJoin('users', 'counter_logs.user_id', '=', 'users.id');
->where('counter_logs.created_at', 'like', '%' . $search . '%')
->orWhere('categories.name', 'like', '%' . $search . '%')
->orWhere('locations.name', 'like', '%' . $search . '%')
->orWhere('users.name', 'like', '%' . $search . '%');
->select('counter_logs.id as id', 'categories.name as category', 'locations.name as location', 'users.name as user', 'counter_logs.created_at as date');
$json['total'] = $query->count();
$logs = $query->offset($offset)->limit($limit)->orderBy($sort, $order)->get();
Try to swap statements:
$logs_total = $query->count();
$logs = $query->offset($offset)->limit($limit)->get();
Or clone base query, like this:
$total_count_query = clone $query;
$logs = $query->offset($offset)->limit($limit)->get();
$logs_total = $total_count_query->count();

Laravel Query Builder Select with empty Input

I'm building up a filterable list with Laravel 5.0 and I'm crashing on following Problem.
I get the filter parameters from a HTML form and pass them to the Query Builder, but if a form input stays empty all rows of the table filtered by the other filters should be returned.
Example code:
$collection = Model::withTrashed()
->where('attr1', 'LIKE', \Request::input('attr1', '%'))
->where('attr2', 'LIKE', \Request::input('attr2', '%'))
->where('attr3', 'LIKE', \Request::input('attr3', '%'))
->get();
This seems to be most correct code for me, but it doesn't work as expected. Do you know a good solution for my Problem? I don't want to integrate a messy switch/case statement for proofing for existence and building the collection up manually. :(
Thanks for your help.
It seems that your problem is that you are always passing the filters to the query and you should only pass them if they are not empty.
Maybe somethig like this would work for you:
$results = Model::withTrashed();
if (\Request::input('attr1')) {
$results->where('attr1', 'LIKE', \Request::input('attr1', '%'));
}
if (\Request::input('attr2')) {
$results->where('attr2', 'LIKE', \Request::input('attr2', '%'))
}
if (\Request::input('attr3')) {
$results->where('attr3', 'LIKE', \Request::input('attr3', '%'))
}
$collection = $results->get();
You need to tweak your query a bit like this:
$collection = Model::withTrashed()
->where('attr1', 'LIKE', '%' . \Request::input('attr1') . '%')
->where('attr2', 'LIKE', '%' . \Request::input('attr2') . '%')
->where('attr3', 'LIKE', '%' . \Request::input('attr3') . '%')
->get();
This will make sure that the LIKE clause is still correct when an empty input parameter is sent.

Categories