How to combine multiple methods without repeating queries in Controller? - php

I have a method index
protected function index(Request $request)
{
$articles = Article::published()->paginate(8);
return view('pages.blog', [
'articles' => $articles,
'orientation' => $this->getOrientation(),
$this->getCategory($request)
]);
}
And a method getCategory()
public function getCategory($request)
{
if ($request->has('category')){
$search = $request->get('category');
$articles = Article::published()
->where('orientation', 'LIKE', '%' . $search . '%')
->paginate(8);
return view('pages.blog', [
'articles' => $articles,
'orientation' => $this->getOrientation()
]);
}
}
As you can see, I try to get my getCategory function outside of my index function.
It works, only, with my debug bar, I have all the SQL queries (those of index and those of getCategory).
Is it possible to optimize my code? Can you help me ?
Thank you

If you need both results add cache for query in index and get full result from cache.
Or if you have all results maybe use collections filter for same your collection from index and provide display data what you need.
For example getCategory add param where you set your collection from index. In article add filter to get only data what you are interest in.

I'm nowhere near an editor to chekc this, but here goes. First function:
public function index(Request $request)
{
$articles = Article::published()->paginate(8);
return view('pages.blog', [
'articles' => $articles,
'orientation' => $this->getOrientation(),
//$this->getCategory($request) - this i don't think can work like this. You are calling
//a function that does not return a value, but instead loads a view, insted:
'categories' => $this->getCategory($request)//the idea here is you call a function and
//get a return as an array
]);
}
Second function:
public function getCategory($request)
{
if ($request->has('category')){
$search = $request->get('category');
$articles = Article::published()
->where('orientation', 'LIKE', '%' . $search . '%')
->paginate(8);
$result = [
'articles' => $articles,
'orientation' => $this->getOrientation()
];
}
else $result = null;
return $result;
}
This might work, once again, im a noob. But i don't see why you need 2 methods for this since there is a if ($request->has('category')){ which will yield a null. Idk, give it a try...

Related

QueryBuilder with a relationship in Symfony

I'm coding in Symfony a search bar working with a query builder for an entity named "Structure" which is related to an entity "Partenaire" (OneToMany), it's working great but the problem is that it shows all the structures and I need to display only the structures related to the Partenaire. If someone can help me to solve this issue, thank you.
PartenaireController.php:
#[Route('/{id}', name: 'app_partenaire_show', methods: ['GET', 'POST'])]
public function show(Partenaire $partenaire, EntityManagerInterface $entityManager, PartenaireRepository $partenaireRepository,Request $request, PartenairePermissionRepository $partenairePermissionRepository, StructureRepository $structureRepository): Response
{
$getEmail = $this->getUser()->getEmail();
$partenaireId = $entityManager->getRepository(Partenaire::class)->findOneBy([
'id' => $request->get('id')
]);
$search2 = $structureRepository->findOneBySomeField2(
$request->query->get('q')
);
return $this->render('partenaire/show.html.twig', [
'partenaire' => $partenaire,
'permission'=>$partenairePermissionRepository->findBy(
['partenaire' => $partenaireId],
),
'structures'=>$search2, // show all the structures
/* 'structures'=>$structureRepository->findBy( // show the structure linked to the partenaire but doesn't work with the search
['partenaire' => $partenaireId],
[],
),*/
'email'=>$getEmail,
]);
}
StructureRepository.php :
public function findOneBySomeField2(string $search2 = null): array
{
$queryBuilder = $this->createQueryBuilder('q')
->orderBy('q.id' , 'ASC');
if ($search2) {
$queryBuilder->andWhere('q.Adresse LIKE :search')
->setParameter('search', '%'.$search2.'%');
}
return $queryBuilder->getQuery()
->getResult()
;
}
as it's a One To Many relation, you should join the right table and add a where statement in your structure query like :
public function findByPartenaireWithFilter(Partenaire $partenaire, string $search2 = null): array
{
$queryBuilder = $this->createQueryBuilder('q')
->leftJoin('q.partenaire','p')
->where('p.partenaire.id = :partenaireId')
->setParameter('partenaireId', $partenaire->getId())
->orderBy('q.id' , 'ASC');
if (null !== $search2) {
$queryBuilder->andWhere('q.Adresse LIKE :search')
->setParameter('search', '%'.$search2.'%');
}
return $queryBuilder
->getQuery()
->getResult();
}
You need to limit your results to the desired Partenaire by adding a condition. You can achieve this by simply passing another argument to the repository function.
I've removed the commented code in the controller and the loading of the Partenaire entity, as it should be already loaded thanks to the magic of param converters.
#[Route('/{id}', name: 'app_partenaire_show', methods: ['GET', 'POST'])]
public function show(Partenaire $partenaire, EntityManagerInterface $entityManager, Request $request, PartenairePermissionRepository $partenairePermissionRepository, StructureRepository $structureRepository): Response
{
$getEmail = $this->getUser()->getEmail();
// The Partenaire should already be loaded
$result = $structureRepository->findByPartenaireWithFilter(
$partenaire,
$request->query->get('q')
);
return $this->render('partenaire/show.html.twig', [
'partenaire' => $partenaire,
'permission' => $partenairePermissionRepository->findBy(
['partenaire' => $partenaireId],
),
'structures' => $search2, // show all the structures
'email' => $getEmail,
]);
}
As for the repository, it's pretty straightforward: pass the loaded partenaire and add a where clause.
public function findByPartenaireWithFilter(Partenaire $partenaire, string $search2 = null): array
{
$queryBuilder = $this->createQueryBuilder('q')
->where('q.partenaire = :partenaire')
->setParameter('partenaire', $partenaire)
->orderBy('q.id' , 'ASC');
if (null !== $search2) {
$queryBuilder->andWhere('q.Adresse LIKE :search')
->setParameter('search', '%'.$search2.'%');
}
return $queryBuilder
->getQuery()
->getResult();
}
As for the permissions key in the controller, I think what you are trying to do, I'd recommend looking into security voters.

Laravel where clause not returning expected result

While making a request to my Laravel database something goes wrong. I'm trying to get different recipes on user input but Postman is returning 'No recipes found'.
My Laravel controller code:
public function search(Request $request) {
$fields = $request->validate([
'search' => 'required|string'
]);
// return response($request);
$recipes = Recipe::where('title', 'LIKE', '%'.$request.'%')->get();
if (count($recipes) > 0 ) {
return response($recipes);
} else {
return response('No recipes found');
}
}
if I return the response it returns "search": "maken" with the request http://127.0.0.1:8000/api/search?search=maken.
When I however hardcode the where clause to $recipes = Recipe::where('title', 'LIKE', 'maken')->get(); it returns some recipes and the search function works. Now I'm not sure whether the error is in my Postman request or in my search function in Laravel. Any help would be greatly appreciated!
You have to use $request->INPUT_NAME or $request->input('name') to get the value, so your code should be:
$recipes = Recipe::where('title', 'LIKE', '%'.$request->search.'%')->get();
Try this way
$recipes = Recipe::where('title', 'like', '%' . request('search') . '%')->get();
if ($recipes->count() > 0 ) {
return response($recipes);
} else {
return response('No recipes found');
}

Multiline Eloquent query

I'm trying to filter my products based on selected filters and possibly a search term/word. My filters have a relationship with categories, which in their turn have a relation ship with my products. My code below only works (without the if statement checking for a search term/word) when everything is chained together, but when I try to break the query into multiple lines (which I've read is possible, right?) it returns an empty array.
Here's a my code:
// Create array from selected categories/filters
$filter_ids = explode(',', $request->get('cats'));
// Query for active products
$products = Product::where('active', '=', 1);
$products->with(['categories' => function($query) use ($filter_ids) {
// Query for active categories
$query->where('active', 1)->whereHas('filters', function ($query) use ($filter_ids) {
// Query for the selected filters from the request
$query->whereIn('id', $filter_ids);
});
}]);
// Check for search term/word
if ($request->get('q')) {
$q = $request->get('q') ? urldecode($request->get('q')) : null;
$products->where('title', 'LIKE', "%{$q}%");
}
// Limit to 10 items and get results
$products->limit(10)->get();
return response()->json([
'status' => 'success',
'response' => $products
], 200);
I think you could but don't need to query all products with title first, before adding the relationships. But whats wrong here is that you must store the result of get() in a variable before adding it to your json response body:
Try to do something like:
if ($request->get('q')) {
$q = $request->get('q') ? urldecode($request->get('q')) : null;
$products->where('title', 'LIKE', "%{$q}%");
}
$products->with(['categories' => function($query) use ($filter_ids) {
// Query for active categories
$query->where('active', 1)->whereHas('filters', function ($query) use ($filter_ids) {
// Query for the selected filters from the request
$query->whereIn('id', $filter_ids);
});
}]);
$response = $products->limit(10)->get();
return response()->json([
'status' => 'success',
'response' => $response
], 200);
Lukas' answer led me to do some more debugging and eventually solving my problem, though it was not the position of the if statement checking if there's a search term/word.
The problem lies in the following line:
$products->limit(10)->get();
I needed to store the retrieved results from the get(); method in another variable, in my case:
$response = $products->limit(10)->get();
I eventually ended up with the following working code:
// Create array from selected categories/filters
$filter_ids = explode(',', $request->get('cats'));
// Query for active products
$products = Product::where('active', '=', 1);
$products->with(['categories' => function($query) use ($filter_ids) {
// Query for active categories
$query->where('active', 1)->whereHas('filters', function ($query) use ($filter_ids) {
// Query for the selected filters from the request
$query->whereIn('id', $filter_ids);
});
}]);
// Check for search term/word
if ($request->get('q')) {
$q = $request->get('q') ? urldecode($request->get('q')) : null;
$products->where('title', 'LIKE', "%{$q}%");
}
// Limit to 10 items, get results and store in '$response'
$response = products->limit(10)->get();
return response()->json([
'status' => 'success',
'response' => $response
], 200);

Problem with the function update() using Repository pattern to write REST API

I have a problem that all the create-read-delete using Repository Pattern is good but the update function is error. I still have the data but the information is not updated.
This is my code in EventController
public function update(EventRequest $request, $id)
{
$events = $this->repository->update($request->all());
return $this->sendResponse($events->toArray(), 'Successfully updated the Event!!');
}
This is i use DI for inject from the Repository, this is EventRepository.php
public function update($id, array $array) {
$events = $this->model->findOrFail($id);
$events->update($array);
return $events;
}
when i use dd($array) and the result returns [] without anything. Can anyone help me. Did i write anything wrong in this. Or i write the wrong Request
public function rules()
{
// $id = $this->events ? ',' . $this->events->id : '';
return $rules = [
'event_title' => 'required|max:255',
'event_type_id' => 'required|integer|between:1,3',
'from_date' => 'required|date_format:Y-m-d H:i:s',
'to_date' => 'date_format:Y-m-d H:i:s|nullable',
'is_recurring' => 'boolean|required',
'remarks' => 'nullable',
];
}
This method takes two arguments:
public function update($id, array $array) {
However, that's not how you are calling it:
$this->repository->update($request->all());
I take it $request->all() gives you an array, so pass the ID first.
$this->repository->update($id, $request->all());

how to pass two variables to view in controller (laravel 5.3)

I have two different queries which are saved in two variables.I want to pass the variables to view page from controller.
public function getApprovalList(){
// $users = select query..
// $request = select query..
return view('travelerHome',['users'=>$users,'request'=>$request]);
}
solution:
controller
return view('travelerHome',['users'=>$users,'requestList'=>$request]);
view
#foreach ($requestList as $req)
{{$req->traveler_name }}
#endforeach
return view('travelerHome')->with(array('users'=>$users,'request'=>$request));
You can use return view('travelerHome', compact('users', 'request')); too
Do like this
return view('travelerHome')->with('users'=>$users)->with('request'=>$request);
Code with you have written that is correct, you need to remove the comment only, I am also using the same method for pass the variable to View. Here is the example.
return view('admin.product.product.edit', ['product' => $product,
'attribute_set' => $productAttributes,
'category' => $cates,
'images' => $images,
'status' => $status,
'countries' => $countries,
'crane_manufacture' => $crane_manufacture,
'product_category' => $productCategory]);
}
And it's also working
So, in your code you need to
public function getApprovalList(){
$users = 'select query..';
$request = 'select query..';
return view('travelerHome',['users'=>$users,'request'=>$request]);
}

Categories