Laravel 5 nested search query - php

I'm trying to make a nested search query but I get this error. I'm trying to search for a company name joined by a company_id.
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'company.name' in 'where clause' (SQL: select count(*) as aggregate from `position` where `to_date` >= 2016-06-16 and `company_id` = 123795854693734 and `title` like %searchquery% and `company`.`name` like %searchquery% and `location` like %%)
Here is my controller function
public function Search(){
$keyword = Input::get('q');
$location = Input::get('l');
$data = Position::where('to_date', '>=', date('Y-m-d'))
->where('company_id', '=', $company_id)
->where('title', 'like', '%'.$keyword.'%')
->where('company.name', 'like', '%'.$keyword.'%')
->where('location', 'like', '%'.$location.'%')
->orderBy('from_date', 'desc')
->paginate(10);
$data = array(
'data' => $data,
);
return view('myview', $data);
}
The model works perfectly. But here it is anyway.
namespace App;
use Illuminate\Database\Eloquent\Model;
class Position extends Model {
protected $table = 'position';
protected $guarded = array("id");
protected $hidden = array();
protected $appends = array('local_ad');
protected $fillable = ['title', 'company_id', 'location'];
public function company() {
return $this->belongsTo('App\Company', 'company_id', 'id');
}
}

You are not using your relation or joining to the company table actually, that's why it can't find it.
Simply, you can use whereHas method to filter positions with company names.
$data = Position::whereHas('company', function ($q) use ($keyword) {
$q->where('name', 'like', '%'.$keyword.'%');
})->where('to_date', '>=', date('Y-m-d'))
->where('company_id', '=', $company_id)
->where('title', 'like', '%'.$keyword.'%')
->where('location', 'like', '%'.$location.'%')
->orderBy('from_date', 'desc')
->paginate(10);

This function should be
public function Search(){
$keyword = Input::get('q');
$location = Input::get('l');
$data = Position::where('to_date', '>=', date('Y-m-d'))
->where('company_id', '=', $company_id)
->where('title', 'like', '%'.$keyword.'%')
->with(['company' => function( $q ) use ($keyword) {
->where('name', 'like', '%'.$keyword.'%')
}])
->where('location', 'like', '%'.$location.'%')
->orderBy('from_date', 'desc')
->paginate(10);
$data = array(
'data' => $data,
);
return view('myview', $data);
}
but this does not do a join, this will fetch position, there is a whereHas in Eloquent, you should explore that also.

Related

Laravel Search Query which meets conditions

Hi I have this code that is to search for records.
Admins are able to see all records, this is the query for admins
$trainings = Training::where('staffName', 'LIKE', "%{$request->search}%")
->orWhere('programTitle', 'LIKE', "%{$request->search}%")
->orWhere('trainer', 'LIKE', "%{$request->search}%")
->paginate();
Whereas Employees should only see their records, so how do I add this condition into the existing query for the search function? This is the query I have for the Employee search currently
$employees = Training::where('staffName',$username)
->orWhere('staffName', 'LIKE', "%{$request->search}%")
->orWhere('programTitle', 'LIKE', "%{$request->search}%")
->orWhere('trainer', 'LIKE', "%{$request->search}%")
->paginate();
I have another version for Managers, which is meant to also refer to their roles from a different table. I am trying it like this but it only is working properly when it comes to the Manager, but when the function fetches anything related to staff under them it fetches all records instead of specific records.
$managers = DB::table('trainings')
->join('users','users.id','=','trainings.staff_id')
->select('trainings.staffName','programTitle','trainer','trainingDate','hours')
->where('trainings.staffName',$username)
->orWhere('reportingTo',$username)
->where(function ($query) use ($request) {
$query->where('trainings.staffName', 'LIKE', "%{$request->search}%")
->orWhere('programTitle', 'LIKE', "%{$request->search}%")
->orWhere('trainer', 'LIKE', "%{$request->search}%");
})
->paginate();
Your usage of orWhere is wrong because orWhere remove all conditions if it's true try this code below
Training::where('staffName', $username)
->where(function ($query) {
$query->where('staffName', 'LIKE', "%{$request->search}%")
->orWhere('programTitle', 'LIKE', "%{$request->search}%")
->orWhere('trainer', 'LIKE', "%{$request->search}%");
})
->paginate();
For the last query
$managers = DB::table('trainings')
->join('users', 'users.id', '=', 'trainings.staff_id')
->select('trainings.staffName', 'programTitle', 'trainer', 'trainingDate', 'hours')
->where(function ($query) use ($username) {
$query->where('trainings.staffName', $username)
->orWhere('reportingTo', $username);
})
->where(function ($query) use ($request) {
$query->where('trainings.staffName', 'LIKE', "%{$request->search}%")
->orWhere('programTitle', 'LIKE', "%{$request->search}%")
->orWhere('trainer', 'LIKE', "%{$request->search}%");
})
->paginate();
here's when query scopes comes to the rescue.
class Training extends Eloquent {
public function scopeFilterByRole($query, $roleId, $searchInput)
{
if ($roleId === 3) {
return $query->where('staffName', 'LIKE', "%{$searchInput}%")
}
return $query;
}
}
Then in your controller
Training::where('programTitle', 'LIKE', "%{$request->search}%")
->orWhere('trainer', 'LIKE', "%{$request->search}%")
->FilterByRole(3, $request->search)
->get();
You can write a global scope for that it will automatically apply in all existing queries:
protected static function boot()
{
parent::boot();
static::addGlobalScope(function (Builder $builder) {
if (auth()->check() and auth()->user()->role == 3) {
$builder->where('staffName', 'LIKE', "%{request()->get('search_name')}%")
}
});
}

Complex query in Laravel using Query Builder

On my website I am trying to implement search functionality. When someone enters keyword I am supposed to find all posts and users that may match that keyword based on posts title or body, or based on users name, username or bio. However I am having trouble with executing this query.
public function search(Request $request) {
$keyword = $request->get('q');
$posts = Post::where('deleted', 0)
->where('title', 'like', '%'.$keyword.'%')
->orWhere('body', 'like', '%'.$keyword.'%')
->orderBy('title')
->get();
$users = User::where('name', 'like', '%'.$keyword.'%')
->where('active', 1)
->orWhere('username', 'like', '%'.$keyword.'%')
->orWhere('bio', 'like', '%'.$keyword.'%')
->orderBy('username')
->get();
return view('searchresults', compact('users', 'posts'));
}
The specific problem I am having is that after function search $posts variable contains posts which were deleted.
This is what I actually need:
select * from posts where deleted = 0 and (title like $keyword or body like $keyword)
I appreciate any help.
Thanks. :)
Use closure to group where() and orWhere() like this:
$posts = Post::where('deleted', 0)
->where(function($q) use($keyword) {
$q->where('title', 'like', '%' . $keyword . '%')
->orWhere('body', 'like', '%' . $keyword . '%');
})
->orderBy('title')
->get();
public function search(Request $request) {
$keyword = $request->get('q');
$posts = Post::whereNull('deleted')
->where('title', 'like', '%'.$keyword.'%')
->orWhere('body', 'like', '%'.$keyword.'%')
->orderBy('title')
->get();
$users = User::where(function($query) use($keyword){
$query->where('name', 'like', '%'.$keyword.'%');
$query->orWhere('username', 'like', '%'.$keyword.'%');
$query->orWhere('bio', 'like', '%'.$keyword.'%');
})
->where('active', 1)
->orderBy('username')
->get();
return view('searchresults', compact('users', 'posts'));
}
Hope it's help you!!

How can I use wherehas and join simultaneously?

I use Laravel 5.3
My code is like this :
public function getWishlist($param)
{
$num = 20;
$q = $param['q'];
$location = $param['location'];
$result = $this->product_repository->whereHas('favorites', function ($query) use($q, $location) {
$query->where('favorites.user_id', '=', auth()->user()->id)
->where('products.status', '=', 1);
if($q)
$query->where('products.name', 'like', "%$q%");
})
->join('stores', 'stores.id', '=', 'products.store_id');
if($location)
$result->where('stores.address', 'like', "%$location%");
if($q)
$result->where('products.name', 'like', "%$q%")
->where('stores.address', 'like', "%$q%", 'or');
dd($result->toSql());
// ->paginate($num);
return $result;
}
When executed, the result is empty
Seems wherehas and join not work simultaneously
Is there any solution to solve my problem?
I think you can use advanced where
$result = $result->where(function($query) use ($q) {
$query->where('products.name', 'like', "%$q%")
->where('stores.address', 'like', "%$q%", 'or');
})

How to select some field and order by on Querying Relationship Existence? Laravel 5.3

My code is like this :
public function getFavoriteStore($param)
{
$num = 20;
$q = $param['q'];
$location = $param['location'];
$result = $this->store_repository->whereHas('favorites', function ($query) use($q, $location) {
$query->select('stores.id', 'stores.name', 'stores.photo','stores.address')
->where('stores.status', '=', 1)
->where('favorites.favoritable_type', 'like', 'App\\\Models\\\Store');
if($location)
$query->where('stores.address', 'like', "%$location%");
if($q) {
$query->where('stores.name', 'like', "%$q%")
->where('stores.address', 'like', "%$q%", 'or');
}
$query->orderBy('favorites.updated_at', 'desc');
})->paginate($num);
return $result;
}
It works
But, order by does not work
Besides, the above query, I only select some field. But when I debug the query, the result display all field
It seems there are still wrong
Is there anyone who can help me?
I follow this tutorial : https://laravel.com/docs/5.3/eloquent-relationships#querying-relationship-existence
UPDATE
My favorite model is like this :
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Favorite extends Model
{
protected $fillable = ['user_id', 'favoritable_id', 'favoritable_type'];
public function favoritable()
{
return $this->morphTo();
}
}
My store model is like this :
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Store extends Model
{
protected $fillable = ['name', 'address', 'phones', 'address', 'email'];
public function favorites()
{
return $this->morphMany(Favorite::class, 'favoritable');
}
}
Favorites table has field id, user_id, favoritable_id, favoritable_type
Stores table has field id, name, address, phones, addres, email, photo
The relation between store and favorite are id (stores table) and favoritable_id (favorites table)
whereHas() is only used to check the existence of a relation so, you have to use join() to order the results with related table
$query = $this->store_repository
->join('favorites', function ($join) {
$join->on('stores.id', '=', 'favorites.favoritable_id')
->where('favorites.favoritable_type', 'like', 'App\\\Models\\\Store');
})
->where('stores.status', '=', 1)
->select('stores.id', 'stores.name', 'stores.photo','stores.address');
if($location)
$query->where('stores.address', 'like', "%$location%");
if($q) {
$query->where('stores.name', 'like', "%$q%")
->where('stores.address', 'like', "%$q%", 'or');
}
$result = $query->orderBy('favorites.updated_at', 'desc')->paginate($num);
I have not tested it but I am pretty sure it will work.

Laravel 5.1 testing: Getting "The response was not a view" error

I'm writting a unit test for a Laravel 5.1 controller, but having problem while trying to test search method:
<?php
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class HomeControllerTest extends TestCase
{
/**
* A basic test example.
*
* #return void
*/
public function testGetIndex(){
$response = $this->call('GET', '/');
$this->assertEquals(200, $response->getStatusCode());
$this->assertViewHas(['menu_highlight',
'page_title',
'meta_description',
'featured_reviews',
'featured_categories',
'images',
'reviews']);
}
public function testGetSearch(){
$response = $this->call('GET', '/search?search_terms=test');
$this->assertEquals(200, $response->getStatusCode());
/* problem arises bellow: */
$this->assertViewHas(['page_title',
'meta_description',
'products',
'reviews',
'brands',
'images',
'categories',
'review_reporting_reasons',
'search_terms']);
}
}
The testGetIndex() method is O.K. the problem arises with the testGetSearch() method. What might cause the error?
HomeController code is as follows:
<?php namespace App\Http\Controllers;
use View;
use Input;
use Settings;
use DB;
use App\Brand;
use App\Category;
use App\Review;
use App\Product;
use App\Image;
use App\User;
use App\FeaturedReview;
use App\ReviewReportingReason;
class HomeController extends Controller
{
public function getIndex() {
$featured_reviews = FeaturedReview::OrderBy('id', 'DESC')->take(5)->get();
$reviews = Review::where('active', '=', 1)->OrderBy('id', 'DESC')->take(5)->get();
$featured_categories = Category::OrderBy('id', 'DESC')->where('featured', '=', 1)->get();
$images = Image::OrderBy('id', 'DESC')->take(5)->get();
if ($reviews) {
return view('home')->with('menu_highlight', 'menu_home')
->with('page_title', Settings::get('site_name'))
->with('meta_description', Settings::get('meta_description'))
->with('featured_reviews', $featured_reviews)
->with('featured_categories', $featured_categories)
->with('images', $images)
->with('reviews', $reviews);
}
else {
throw new \Exception('Please install the application');
}
}
public function getSearch() {
$search_terms = Input::get('search_terms');
try {
$products = Product::LeftJoin('categories', 'categories.id', '=', 'products.category_id')
->LeftJoin('brands', 'brands.id', '=', 'products.brand_id')
->select(
'products.*',
'categories.id as cid',
'categories.name as cname',
'brands.id as bid',
'brands.name as bname'
)
->whereRaw("MATCH (products.name) AGAINST (?)", array($search_terms))
->orWhereRaw("MATCH (categories.name) AGAINST (?)", array($search_terms))
->orWhereRaw("MATCH (brands.name) AGAINST (?)", array($search_terms))
->where('products.active', '=', 1)
->OrderBy('products.rating', 'DESC')
->OrderBy('products.reviews_count', 'DESC')
->GroupBy('products.id')
->paginate(Settings::get('front_end_pagination'));
$products->setPath('search');
}
catch(\Exception $e) {
return view('/products/no_products')->with('search_terms', $search_terms);
}
$reviews = Review::whereRaw("MATCH (text) AGAINST (?)", array($search_terms))
->OrWhereRaw("MATCH (title) AGAINST (?)", array($search_terms))
->OrWhereRaw("MATCH (pros) AGAINST (?)", array($search_terms))
->OrWhereRaw("MATCH (cons) AGAINST (?)", array($search_terms))
->where('active', '=', 1)
->orWhere('title', 'LIKE', '%' . $search_terms . '%')
->orWhere('pros', 'LIKE', '%' . $search_terms . '%')
->orWhere('cons', 'LIKE', '%' . $search_terms . '%')
->OrderBy('id', 'DESC')
->paginate(Settings::get('front_end_pagination'));
$reviews->setPath('search');
$brands = DB::table('brands')
->select(DB::raw('brands.*, count(reviews.id) as reviews, (select count(products.id) from products where products.brand_id = brands.id) as products'))
->LeftJoin('products', 'brands.id', '=', 'products.brand_id')
->LeftJoin('reviews', 'reviews.product_id', '=', 'products.id')
->WhereRaw("MATCH (brands.name) AGAINST (?)", array($search_terms))
->GroupBy('brands.id')
->OrderBy('reviews', 'DESC')
->paginate(Settings::get('front_end_pagination'));
$brands->setPath('search');
$categories = DB::table('categories')
->select(DB::raw('categories.*, count(reviews.id) as reviews, (select count(products.id) from products where products.category_id = categories.id) as products'))
->LeftJoin('products', 'categories.id', '=', 'products.category_id')
->LeftJoin('reviews', 'reviews.product_id', '=', 'products.id')
->WhereRaw("MATCH (categories.name) AGAINST (?)", array($search_terms))
->GroupBy('categories.id')
->OrderBy('reviews', 'DESC')
->paginate(Settings::get('front_end_pagination'));
$categories->setPath('search');
$images = Image::whereRaw("MATCH (description) AGAINST (?)", array($search_terms))
->OrderBy('id', 'DESC')
->paginate(Settings::get('front_end_pagination'));
$review_reporting_reasons = ReviewReportingReason::OrderBy('ID', 'DESC')->get();
return view('home/search_results')
->with('page_title', 'Search results for' . ' ' . $search_terms)
->with('meta_description', 'Search results for '.$search_terms)
->with('products', $products)
->with('reviews', $reviews)
->with('brands', $brands)
->with('images', $images)
->with('categories', $categories)
->with('review_reporting_reasons', $review_reporting_reasons)
->with('search_terms', $search_terms);
}
}
The problem was in the view file, where a file with a html source code for a modal window was included with #include('modal') instead of #yield('modal'). The file was not formated as a blade template, just plain html without blade directives.

Categories