custom query function laravel - php

I often need to perform this query:
$Op = JobCardOp::where([
['JobCardNum', '=', $JobCardNum ],
['OpNum', '=', $OpNum ]
])->first();
So rather than writing this out every time I want a function like:
public function getOp($JobCardNum, $OpNum)
{
$Op = JobCardOp::where([
['JobCardNum', '=', $JobCardNum ],
['OpNum', '=', $OpNum ]
])->first();
return $Op;
}
That I can call in my controller. Where should I define my function, at the moment the I only need it in one controller but I may need it an another if thats possible. Any help appreciated.

You may define your function in JobCardOpt model as static:
public static function getOp($JobCardNum, $OpNum)
{
$Op = static::where([
['JobCardNum', '=', $JobCardNum],
['OpNum', '=', $OpNum]
])->first();
return $Op;
}
And use it like this in your controllers:
$jobCardOpt = JobCardOpt::getOp(1, 2);

You could put this method on your Model if you wanted to as a static function.
public static function getOp($cardNum, $opNum)
{
return static::where([
['JobCardNum', '=', $cardNum],
['OpNum', '=', $opNum]
])->first();
}
// controller
$res = YourModel::getOp($cardNum, $opNum);
Or add a query scope to the model
public function scopeGetOp($query, $cardNum, $opNum)
{
return $query->where([
['JobCardNum', '=', $cardNum],
['OpNum', '=', $opNum]
]);
}
// controller
$res = YourModel::with(...)->getOp($cardNum, $opNum)->first();
Kinda depends how you want to use it.

Related

how to use Join with Where condition in laravel controller?

i have this index function that will show data from two different tables:
public function index()
{
$complaints = DB::table('complaint')
->select(['complaint.id','complaint.createdDate','complaint.user_id','complaint.createdDate','complaint.complaint_title','tbl_users.phone','tbl_users.email'])
->join('tbl_users', 'complaint.user_id', '=', 'tbl_users.id')
->get();
return view('admin.complaints',compact('complaints'));
}
and in the next function i want to show a single row using the same thing above by 'id'
i tired this:
public function show($id)
{
$complaints = DB::table('complaint')
->select(['complaint.id','complaint.createdDate','complaint.user_id','complaint.createdDate','complaint.complaint_title','tbl_users.phone','tbl_users.email'])
->join('tbl_users', 'complaint.user_id', '=', 'tbl_users.id')
->where('id', $id)->first()
->get();
return $complaints;
}
but i'm getting this error
Call to undefined method stdClass::get()
For creating where statements, you can use get() and first() methods. The first() method will return only one record, while the get() method will return an array of records , so you should delete first() , so the code should be like that .
public function show($id)
{
$complaints = DB::table('complaint')
->select(['complaint.id','complaint.createdDate','complaint.user_id','complaint.createdDate','complaint.complaint_title','tbl_users.phone','tbl_users.email'])
->join('tbl_users', 'complaint.user_id', '=', 'tbl_users.id')
->where('id', $id)
->get();
return $complaints;
}

How to get Billing Address from Eloquent model with where clause?

For example I can use:
$address = $user->address
which will return the addresses for the user.
// User.php (model)
public function address()
{
return $this->hasMany(Address::class, 'refer_id', 'id');
}
public function billingAddress()
{
return $this->address()
->where('type', '=', 1)
->where('refer_id', '=', $this->id)
->first();
}
However, I would like to return the BillingAddress for the user depending on this where clause. How do I do it?
EDIT:
If I use this inside... OrderController#index it returns correctly
$orders = Order::with('order_fulfillment', 'cart.product', 'user.address', 'payment')->get();
return new OrderResource($orders);
However, If I change it to:
$orders = Order::with('order_fulfillment', 'cart.product', 'user.billingAddress', 'payment')->get();
return new OrderResource($orders);
I get this error:
Symfony\Component\Debug\Exception\FatalThrowableError
Call to a member function addEagerConstraints() on null
One option is you can use whereHas in your query. For example,
$orders = Order::with('order_fulfillment', 'cart.product', 'user.address', 'payment')
->whereHas(
'address', function ($query) {
$query->where('type', '=', 1)
->first();
}
)->get();
return new OrderResource($orders);
This is one option. try to dd($orders) an find if its working.
You had an another option like this, in your model
public function address()
{
return $this->hasMany(Address::class, 'refer_id', 'id');
}
Add relations like
public function billingAddress()
{
return $this->hasOne(Address::class, 'refer_id', 'id')->where('type', 1);
}
And
public function shippingAddress()
{
return $this->hasOne(Address::class, 'refer_id', 'id')->where('type', 2);
}
Then in your query,
$orders = Order::with('order_fulfillment', 'cart.product', 'user.address','user.billingAddress', 'user.shippingAddress', 'payment')->get(); return new OrderResource($orders);

Use variable in relationship

I have some customfield functionality on my site where users can add custom fields to a model.
I've just found that if you enter data into one of the fields the same field won't show up for another model because of the way I get the empty fields for a model
public function Customfield()
{
return $this->hasMany(Customfield::class);
}
public function getEmptyCustomfields($model)
{
return $this->has('customfield', '<', 1)
->select('customfieldslabels.id as label_id', 'customfieldslabels.datatype as datatype', 'customfieldslabels.label_name as label_name',
'customfieldslabels.customfield_tab_id as customfield_tab_id', 'customfieldstabs.name as name')
->join('customfieldstabs', 'customfieldstabs.id', '=', 'customfieldslabels.customfield_tab_id')
->where('customfieldstabs.model', '=', $model)
->get();
}
public function getEmptyCustomfieldsByTab($tabIDm)
{
return $this->has('customfield', '<', 1)->where('customfield_tab_id', '=', $tabID)->get();
}
This is what I had originally and I realised that if a label has a field that is assigned to another model then the relationship exists and won't return as empty for another model.
So I'm trying to also check against the model ID now but I'm not quite sure how to use the model ID while checking the relationship
public function Customfield()
{
return $this->hasMany(Customfield::class);
}
public function customfieldByModel($modelID)
{
return $this->has('customfield' => function ($query) use ($modelID){
$query->where('model_id', '=', $modelID);
})->get();
}
public function getEmptyCustomfields($model, $modelID)
{
return $this->has($this->customfieldByModel($modelID), '<', 1)
->select('customfieldslabels.id as label_id', 'customfieldslabels.datatype as datatype', 'customfieldslabels.label_name as label_name',
'customfieldslabels.customfield_tab_id as customfield_tab_id', 'customfieldstabs.name as name')
->join('customfieldstabs', 'customfieldstabs.id', '=', 'customfieldslabels.customfield_tab_id')
->where('customfieldstabs.model', '=', $model)
->get();
}
public function getEmptyCustomfieldsByTab($tabIDm, $modelID)
{
return $this->has($this->customfieldByModel($modelID), '<', 1)->where('customfield_tab_id', '=', $tabID)->get();
}
I would like to return empty fields for one model that they haven't been filled in for yet.
They return just find once there is data for a model assigned to a field as it doesn't need to check for empty fields anymore.
UPDATE
I've tried using a left join which I think will work but I can't get to the method because I get an error saying: 'The method name must be a string'
I changed this
public function getEmptyCustomfieldsByTab($tabID, $modelID)
{
return $this->has($this->customfieldByModel($modelID), '<', 1)->where('customfield_tab_id', '=', $tabID)->get();
}
To this:
public function getEmptyCustomfieldsByTab($tabID, $modelID)
{
return $this->has('customfieldbymodel', '<', 1)->where('customfield_tab_id', '=', $tabID)->get();
}
But now I can't send the $modelID as a parameter. Is it possible to sned a parameter while doing a has?
MY SOLUTION
I have created a protected variable on the model that just gets reassigned everytime.
protected $modelID;
public function customfieldByModel()
{
return $this->hasMany(Customfield::class)->where('model_id', '=', $this->modelID);
}
public function getEmptyCustomfields($model, $modelID)
{
$this->modelID = $modelID;
return $this->has('customfieldByModel', '<', 1)
->select('customfieldslabels.id as label_id', 'customfieldslabels.datatype as datatype', 'customfieldslabels.label_name as label_name',
'customfieldslabels.customfield_tab_id as customfield_tab_id', 'customfieldstabs.name as name')
->join('customfieldstabs', 'customfieldstabs.id', '=', 'customfieldslabels.customfield_tab_id')
->where('customfieldstabs.model', '=', $model)
->get();
}
public function getEmptyCustomfieldsByTab($tabID, $modelID)
{
$this->modelID = $modelID;
return $this->has('customfieldByModel', '<', 1)->where('customfield_tab_id', '=', $tabID)->get();
}

Laravel post data to function within the controller

Currently my HomeController looks like this:
class HomeController extends BaseController {
public function getHome()
{
$scripts = Script::select('script.*', DB::raw('COALESCE(SUM(vote.rating), 0) as rating'))
->leftJoin('script_vote as vote', 'vote.script_id', '=', 'script.id')
->with('tags')
->orderBy('rating', 'desc')
->orderBy('views', 'desc')
->groupBy('id')
->paginate(8);
return View::make('home')->with('scripts', $scripts);
}
public function postSearch()
{
$input = array(
'query' => Input::get('query'),
'sort_col' => Input::get('sort_col'),
'sort_dir' => Input::get('sort_dir'),
);
$scripts = Script::select('script.*', DB::raw('COALESCE(SUM(vote.rating), 0) as rating'))
->leftJoin('script_vote as vote', 'vote.script_id', '=', 'script.id')
->where('title', 'LIKE', '%' . $input['query'] . '%')
->orderBy($input['sort_col'], $input['sort_dir'])
->orderBy('views', 'desc')
->groupBy('id')
->with('tags')
->paginate(8);
Input::flash();
return View::make('home')->with('scripts', $scripts);
}
}
As you can see, I'm using (almost) the same big query twice. I would like to call the postSearch() function within the getHome() function and give the three parameters (query = '', sort_col = 'rating', sort_dir = 'desc') with it. Is this possible?
If you plan on using this frequently I would move this out of your controller and put it in your Model as a Custom Query Scope. This really doesn't have a place in the Controller even as a private function.
public function scopeRating($query)
{
return $query->select('script.*', DB::raw('COALESCE(SUM(vote.rating), 0) as rating'))
->leftJoin('script_vote as vote', 'vote.script_id', '=', 'script.id')
->with('tags')
->orderBy('rating', 'desc')
->orderBy('views', 'desc')
->groupBy('id');
}
This could then be called like this
Script::rating();
here are a few possibilities:
write a private function getScripts(...) within the controller (not so sexy)
add a getScripts(...) function on your Scripts model (so-lala sexy)
create a service provider to encapsulate the model(s) and inject them into the controller

How to make Laravel 4 pagination

Hello everyone I'm trying to make pagination in Laravel 4 but my code doesn't work.
I have controller with action:
public function getSingleProduct($prodName, $id)
{
$singleProduct = Product::getOne($id);
$getAllReviews = Review::getAllBelongsToProduct($id);
$this->layout->content = View::make('products.single')
->with('reviews', $getAllReviews)
->with('products', $singleProduct);
}
and I want to paginate getAllReviews (5 per page). I tried like this:
$getAllReviews = Review::getAllBelongsToProduct($id)->paginate(5); but it doesn't work for me. Here is also my Review model
public static function getAllBelongsToProduct($id) {
return self::where('product_id', '=', $id)
->join('products', 'reviews.product_id', '=', 'products.id')
->select('reviews.*', 'products.photo')
->orderBy('created_at', 'desc')
->get();
}
Where I have a mistake?
Instead of that static method on your model use query scope, this will be flexible:
// Review model
public function scopeForProduct($query, $id)
{
$query->where('product_id', $id);
}
public function scopeWithProductPhoto($query)
{
$query->join('products', 'reviews.product_id', '=', 'products.id')
->select('reviews.*', 'products.photo');
}
Then use it:
// get all
$reviews = Review::forProduct($id)->withProductPhoto()->latest()->get();
// get paginated
$reviews = Review::forProduct($id)->withProductPhoto()->latest()->paginate(5);
latest is built-in method for orderBy('created_at', 'desc').
If you want to have just a single call in your controller, then chain the above and wrap it in methods on your model.

Categories