Creating Left join method in Laravel Model - laravel

I have below left join in Controller, which shows all records of specific teachers in one report, and it returns all correct records. I want to use the exact same query in many other reports, so I want to create Method in eloquent Model to call it where ever I want.
how to use this query in model
and how to call it in view.
public function edit(Teacher $teacher)
{
$teachers= DB::table('teachers')
->leftjoin('religions', 'teachers.religion_id', '=', 'religions.id')
->leftjoin('areas', 'teachers.area_id', '=', 'areas.id')
->select('teachers.*')
->where('teachers.id',$teacher->id)
->first();
$areas = area::all();
$religions = religion::all();
return view('teachers.report1',['teachers' => $teachers, 'teacher'=>$teachers,'areas'=>$areas,
'religions'=>$religions]);

In Teacher model you can do
public function teacherRecords(){
$teachers= DB::table('teachers')
->leftjoin('religions', 'teachers.religion_id', '=', 'religions.id')
->leftjoin('areas', 'teachers.area_id', '=', 'areas.id')
->select('teachers.*')
->where('teachers.id',$this->id)
->first();
}
and use it like $teach->teacherRecords();
If I can understand, the relationship between tables/models, I can provide a better solution.
If teacher has only one religion and one area, just do it like
class Teacher extends Model{
public function area()
{
return $this->hasOne('App/Area');
}
public function religion()
{
return $this->hasOne('App/religion');
}
}
In Area model
class Area extends Model{
public function teacher()
{
return $this->hasOne('App/Teacher');
}
}
In Religion model
class Religion extends Model{
public function teacher()
{
return $this->hasOne('App/Teacher');
}
}
Now you can do $teacher->area and $teacher->religion

Related

How to call model in Controller request $request

I have a query in my model, which I want to call in my controller (request $request). It's working fine when the controller parameter is controller($id). But how to pass it in $request controller.
teacher Model with Query:
class teacher extends Model
{
public static function teacher($id)
{
return DB::table('teachers')
->leftjoin('religions', 'teachers.religion_id', '=', 'religions.id')
->leftjoin('areas', 'teachers.area_id', '=', 'areas.id')
->select('teachers.*','religions.*','areas.*')
->where('teachers.id',$id)
->first();
}
Controller which calls this model perfectly fine passing direct id:
public function report1($id)
{
$teacher = Teacher::teacher($id);
return View('teachers.report1' ,compact('teacher'));
}
Controller where I want to call it:
public function printreports(Request $request)
{
$teachers = $request->get('select2');
return view('teachers.report1',compact('teachers'));
}
Note: select2 contains teacher ids where I want to run model query.
Supposing you are have an array of ids in your select2 request param, probably easiest way is to change query at teacher model as follows:
use Illuminate\Support\Arr;
class teacher extends Model
{
public static function teacher($id)
{
return DB::table('teachers')
->leftjoin('religions', 'teachers.religion_id', '=', 'religions.id')
->leftjoin('areas', 'teachers.area_id', '=', 'areas.id')
->select('teachers.*','religions.*','areas.*')
->whereIn('teachers.id', Arr::wrap($id))
->get();
}
}

how to use laravel Scope in a relationship?

I'm using laravel
I have two models
Product
class Product extends Model
{
public function productcategories(){
return $this->hasOne('App\Product\Productcategorie','CategoryID','ProductCategoryId');
}
}
and Productcategorie
class Productcategorie extends Model
{
protected $primaryKey = 'CategoryID';
public function product(){
return $this->belongsToMany('App\Product\Product','ProductCategoryId','CategoryID');
}
public function scopeCp($query,$id){
return $query->where('categoryparent_id', '=', $id);
}
}
The Product model has a scope Cpscope
and i have ProductController with function
function productCatgoryPaFilter(Request $request){
$categories= Categoryparent::with('categories')->get();
$id=$request->id;
return $product = Product::with('productcategories')->with('productoption.option')->orderBy('created_at','DESC')->get();
}
i want to get all products with categoryparent_id equal to passed parametre in scope
how can i do it?
If you want to filter data in relational model, use whereHas(). Though i have not tested, give it a try
Product::whereHas('productcategories', function ($query) use($id) {
$query->cp($id);
})
->orderBy('created_at','DESC')->get()

How I can make the same SQL query whith the halp of Eloqument ORM methods and models

I have followng database:
And database diagramm is on next picture. Simply speaking, Users have many shops, Shops have many products etc.
In need to select all products from all shops of particular user. In my Controller it's look like so:
But it's does't work (
Instade of this I try to write direct SQL
I just need to make following request by Eloqument methods
SELECT * FROM tmp.products
WHERE tmp.products.shop_id IN
(SELECT id FROM shops where user_id = 1);
with dynamics parametrs of course.
You could get all products by using whereHas filter like
$products = Product::whereHas('shop.user', function ($query) use($request) {
$query->where('id', '=', $request->user()->id);
})->get();
I assume you have defined proper mappings in your models like
class Product extends Model {
public function shop() {
return $this->belongsTo('Shop', 'shop_id');
}
}
class Shop extends Model {
public function user() {
return $this->belongsTo('User', 'user_id');
}
public function products() {
return $this->hasMany('Product', 'shop_id');
}
}
class User extends Model {
public function shops() {
return $this->hasMany('Shop', 'user_id');
}
}

Laravel Eloquent - Get all records of child relation model

My data model is this:
Users > Offices > Organization
This is my model
class Organization extends Model {
protected $table = 'organizations';
public function offices()
{
return $this->hasMany('App\Models\Office');
}
public function users()
{
return $this->offices()->users();
}
....
So.. I want to get all users from an organization (of all the offices).
But I don't know how to do something like
$this->offices()->users();
(Avoiding user a manual collection or map to do that)
Thanks!
So, you have organization ID. You can load all users by using whereHas():
$users = User::whereHas('office', function ($q) use ($organizationId) {
$q->where('organization_id', $organizationId);
})
->get();
Make sure office() relationship is defined correctly in User model:
public function office()
{
return $this->belongsTo('App\Office');
}
Alternatively, you could define hasManyThrough() relationship:
public function users()
{
return $this->hasManyThrough('App\Office', 'App\User');
}
And use it:
$organization->users()

Laravel: One to Many to Many, retrieve distinct() values

Laravel 4 Project, using Eloquent ORM.
I have three tables: customers, orders and products (+ 1 pivot table order_product). Customers are linked one-to-many to Orders. Orders are linked many-to-many to Products.
Customers 1-->N Orders N<-->N Products
I would like to have a method on Customer model that retrieves a list of products that customer is buying.
To better understand this, assume products are consumable.
For example Customer #1 can place:
Order #1 for Products A, B and C;
Order #2 for Products A, C and D;
Order #3 for Products C and E;
...and the result I want to retrieve is a Collection with Products A, B, C, D and E.
Models are (pseudo-coded on the fly):
class Product extends Eloquent {
public function orders()
{
return $this->belongsToMany('Order');
}
}
class Orders extends Eloquent {
public function customer()
{
return $this->belongsTo('Customer', 'customer_id');
}
public function products()
{
return $this->belongsToMany('Product');
}
}
class Customers extends Eloquent {
public function orders()
{
return $this->hasMany('Orders', 'customer_id');
}
public function products()
{
// What to put here ???
}
}
Thanks to #deczo's answer, I was able to put up a single query method to retrieve items:
public function items()
{
$query = DB::table('items')->select('items.*')
->join('item_order', 'item_order.component_id', '=', 'items.id')
->leftJoin('orders', 'item_order.order_id', '=', 'orders.id')
->leftJoin('customers', 'customers.id' , '=', 'orders.customer_id')
->where('customers.id', $this->id)
->distinct()
->orderBy('items.id');
$eloquent = new Illuminate\Database\Eloquent\Builder( $query );
$eloquent->setModel( new Item );
return $eloquent->get();
}
This is a Many-to-Many relationship, but with the Orders table as the pivot table.
class Customers extends Eloquent {
public function orders()
{
return $this->hasMany('Orders', 'customer_id');
}
public function products()
{
return $this->belongsToMany('Products', 'orders', 'customer_id', 'product_id');
}
}
I've included the last two parameters, but if you follow the singular_id pattern they can be left out.
It's possible to receive distinct Product models like this:
public function products()
{
return $this->belongsToMany('Products', 'orders', 'customer_id', 'product_id')
->distinct();
}
#deczo's answer probably works fine, and is probably a lot more performant as all the data reduction is done in the database itself, but here's a 'pure Laravel' way that's undoubtedly more readable:
use Illuminate\Database\Eloquent\Collection;
class Customer extends Eloquent
{
...
public function products()
{
$products = new Collection;
foreach ($this->orders as $order) {
$products = $products->merge($order->products);
}
return $products;
}
}
Note that this method will not act like normal relationship methods - to get the resulting collection you call the method (i.e. $products = $customer->products();) and you can't access it as a property like you can with relationships (i.e. you can't do $products = $customer->products;).
Also, I'm kinda going on my understanding of the Illuminate\Database\Eloquent\Collection#merge() method here that it automatically does a DISTINCT-like thing. If not, you'll have to do a $collection->unique() kinda thing.
I can't think of easy relation method for this one, but here's a workaround:
$productsIds = DB::table('customers')
->leftJoin('orders', 'orders.customer_id', '=', 'customers.id')
->join('order_item', 'order_item.order_id', '=', 'orders.id')
->leftJoin('items', 'order_item.item_id' , '=', 'items.id')
->distinct()
->get(['items.id']);
$productsIds = array_fetch($productsIds, 'id');
$productsCollection = Product::whereIn('id', $productsIds);

Resources