How to fetch specific columns from multiple tables in Laravel 5? - laravel

I have 3 tables,
Country:
id,
name
Province:
id,
name,
country_id
City:
id,
name,
province_id
I have defined relationships in Model as follows,
Country Model:
public function Provinces()
{
return $this->hasMany('App\Province');
}
Province Model:
public function Country()
{
return $this->belongsTo('App\Country');
}
public function Cities()
{
return $this->hasMany('App\City');
}
City Model:
public function Province()
{
return $this->belongsTo('App\Province');
}
I am using the below query, but it overwrites all the data with Country name.
$city = DB::table('cities')
->join('provinces', 'cities.province_id', '=', 'provinces.id')
->join('countries', 'provinces.country_id', '=', 'countries.id')
->select('cities.name','provinces.name','countries.name')
->get();
I want to fetch a result of only City Name, Province Name, Country Name from these tables in laravel 5. Can you help me with that ?

Try just using as:
->select('cities.name as city_name', 'provinces.name as province_name', 'countries.name as country_name')

Would you try with this :
$city = DB::table('cities')
->join('provinces', 'cities.province_id', '=', 'provinces.id')
->join('countries', 'provinces.country_id', '=', 'countries.id')
->get(['cities.name', 'provinces.name', 'countries.name']);
I hope it helps you !

ok this is going to be a specific answer
learn about realtions in laravel and look at these
class example1 extends Model
{
public function examplefunction() {
return $this->hasMany('App\othermodel', 'id');
}
}
then use this query
$abc=example1::with('examplefunction')->get();
and there you go just take a look at a laravel relationship by using this u can get combined result

$products = User::select('id', 'email', 'first_name', 'last_name','country_code','mobile')->get()->toArray();
$gaurang = Ticket_Thread::select('body','title','resolv_note')

Related

How to get data from Laravel relation

I have 2 models: publictxt and Pulicetxtrecive
publictxt model:
class Publictxt extends Model
{
protected $fillable=['sender','reciver','description','useridseen'];
public function Publictxtrecives()
{
return $this->hasMany(Pulicetxtrecive::class,'publictxt_id', 'id');
}
}
Pulicetxtrecive model:
protected $fillable=['publictxt_id','user_id','seen'];
public function publictxts()
{
return $this->belongsTo(Publictxt::class);
}
I want to get the values ​​from the Publictxt that are available in the Pulicetxtrecive.
When a record is stored in the Publictxt, users are registered in the Pulicetxtrecive after viewing.
$pulictxtcount=Publictxt::where('reciver',Auth::user()->shift)->orwhere('reciver',1)->with('Publictxtrecives')->whereHas('Publictxtrecives',function($q){$q->where('seen', '=', 0);})->count();
this code doesn't work.
There are some conflicts in your database structure.
You said when a user sees a letter the Publictxtrecives will be created.
That means if a Publictxt has a Publictxtrecives that definitely has been seen .
But there is a seen column in Publictxtrecives table.
You should pick one.
But anyway as this structure:
$pulictxtcount=Publictxt::where(
function($query){
$query->where('reciver',Auth::user()
->shift)->orwhere('reciver',1);
})
->Where(function($query)
{
$query->whereHas('Publictxtrecives',
function($q){$q->where('seen',1);
}
)->orWhereDoesntHave('Publictxtrecives');
})
->with('Publictxtrecives');
$pulictxtcount = Publictxt::with([
'Publictxtrecives' => function($query){
$query->where('seen', 0);
}
])
->where('reciver', Auth::user()->shift)
->orwhere('reciver', 1)
->get();
I solved this problem:
$pulictxtcount = Publictxt::where(function($q){$q->where('reciver',Auth::user()->shift)->orwhere('reciver',1);})->whereDoesntHave('Publictxtrecives', function($q){$q->where('user_id', Auth::user()->id);
})->count();

mb_strpos() expects parameter 1 to be string, object given when querying 2 tables in Laravel

Ok, so I don't know if this can be done, but I need to combine the results of 2 Where clauses from 2 tables into one variable.
So far I have this working to query one table:
$allCompanies = Products::where('category_id', $id->id)->groupBy('company_id')->get();
And this for the other:
$companies = Company::where('visible', 0)->get();
But is there any way to get them into the same query string? Something like so I can get where the ID matches the ID column in one table AND where visible is 0 in the other?
I tried this:
$allCompanies = Products::with('company', function($q){
$q->where('visible', 0);
})->where('category_id', $id->id)
->groupBy('company_id')->get();
but got this error:
mb_strpos() expects parameter 1 to be string, object given
Company Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Company extends Model
{
public function products()
{
return $this->hasMany('App\Products');
}
}
Products Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Products extends Model
{
protected $fillable = [
'name',
'description',
'image',
'size',
'price',
'stock',
'company_id',
'category_id'
];
public function category()
{
return $this->belongsTo('App\Categories', 'category_id');
}
public function company()
{
return $this->belongsTo('App\Company', 'company_id');
}
}
When using callback in with, you should pass callback as value of associative-array.
Your query should be:
$allCompanies = Products::with(['company' => function($q) {
$q->where('visible', 0);
}])
->where('category_id', $id->id)
->groupBy('company_id')
->get();
Ref: https://laravel.com/docs/8.x/eloquent-relationships#nested-eager-loading-morphto-relationships
The most Laravel way of achieving this is through Relationships and whereHas. If you have a relationship defined you could do the following:
$products = Products::where('category_id', $id->id)
->whereHas('company', function($q) {
$q->where('visible', 0);
});
Which will query for all the products with a certain category_id that also have a relationship with a company that has a column visible with value 0
Depends on what you want:
If you want all the products from visible companies:
$products = Products::whereHas('company', function($q) {
$q->where('visible',0);
})->get();
If you want all the companies with their products (which I would advise):
$Companies = Company::with('products')->where('visible',0)->get();

Laravel: getting an array inside an objet bei joinig two tables

I have two tables: films and actors. Thy have a n-m relation.
I have a connection table actor_film with two columns film_id and actor_id.
In order to get the list of films added in the current month with the actors that play in each film I did this:
$current_month_film = DB::table('films')
->join('actor_film', 'actor_film.film_id', '=', 'films.id')
->join('actors', 'actors.id', '=', 'actor_film.actor_id')
->select('films.*', 'actors.name as actors_name')
->whereMonth('films.created_at', '=', Carbon::now()->month)
->orderBy('films.created_at', 'desc')
->groupBy('films.name')
->get();
return view('statistics.month')->withCurrent_month_film($current_month_film);
I get 40 films each of it showing just ONE actor, even if I know there are several actors in one film.
If I delete the "->groupBy('films.name')" I get 132 record: one film several times and each time one actor.
How could I get a list of actors inside each film, joinig the two tables? something like:
[
{
film.id: 1,
film.name,
film.actors
{
actor[1].name: Morgan Freeman,
actor.[2].name: Meryl Streep
actor [n].name: ....
}
},
{
film.id: 2,
film.name,
film.actors
{
actor[1].name: Morgan Freeman,
actor.[2].name: Meryl Streep
actor [n].name: ....
}
}
]
If you want to use Eloquent and you have your relation in place then your can do it as:
Film::whereMonth('created_at', Carbon::now()->month)
->orderBy('created_at', 'desc')
->with(['actors' => function($q) {
$q->select('name');
}])
->get()
Docs
As you're using Laravel, you should make the use of Laravel Relationships. You should have a models like this:
class Actor extends Model
{
public function films() {
return $this->belongsToMany(Film::class, 'actor_film');
}
}
class Film extends Model
{
public function actors() {
return $this->belongsToMany(Actor::class, 'actor_film');
}
}
and to get the film with their respective actors, you can use with method like this:
$films = Film::with(['actors' => function($q) {
$q->select('name');
}])
->whereMonth('created_at', Carbon::now()->month)
->orderBy('created_at', 'desc')
->get();
foreach($films as $film) {
$film_name = $film->name;
$actors_arr = $film->actors->toArray();
}
See more about Laravel's Eloquent Relationships & Eager Loading
Hope this helps!
In Controller
$current_month_film = Film::select('*')->with(['actor_film','actors'])
->whereMonth('films.created_at', '=', Carbon::now()->month)
->orderBy('films.created_at', 'desc')
->groupBy('films.name')
->get();
In App\Model\Film Model
namespace App;
use Illuminate\Database\Eloquent\Model;
class Film extends Model
{
//
protected $primaryKey = "id"; //primary key
protected $table = 'film';
public function actor_film(){
return $this->belongsTo('App\Model\ActorFilm','film_id','id');
}
public function actors(){
return $this->hasMany('App\Model\Actors','id','actor');
}
}

Laravel: get data from variouos tables based on optional conditions

I want to write a query based on optional condition that will fetch data from different tables. My schema looks like
myboxes Table
id,
type_id --> foreign key to box_type table
postal_code
po_box
created_at
updated_at
mybox_access table
id
mybox_id -> foreign key to myboxes table
email
box_type table
id
type_name
And here are my models
MyBox.php
class MyBox extends Model {
public function type() {
return this->hasOne(BoxType::class, 'id', 'type_id');
}
public function access() id
return this->hasOne(MyBoxAccess::class, 'mybox_id', 'type_id');
}
}
MyBoxType.php has following relation ship
public function mybox() {
return this->hasOne(MyBox::class, 'id', 'type_id');
}
And MyBoxAccess.php has following relationship
public function vbox() {
return $this->belongsTo(MyBox::class, 'id', 'mybox_id');
}
Now I want to get based on following condition
I have email as required param and postal_code and po_box as optional params (but one of them will be must and both can also be present).
So I want to get data of all my_boxes that have type_id 3 OR all myboxes whoes id matches to email in mybox_access table AND postal_code or po_box matches to params in myboxes table
For simple match of params postal code and po_box I can write some thing like
$result = new MyBox();
if(!empty($request['postal_code'])) {
$result->where('postal_code', like, '%'.$request['postal_code']);
}
if(!empty($request['po_box'])) {
$result->where('po_box', like, '%'.$request['po_box']);
}
$result = $result->get();
But I don't know how to get data for above mentioned condition. When I try to do using with() like
MyBox::with(['access' => function(Builder $query) use ($request){
$query->where('mybox_id',$request['id']);
}])->get();
I get
`Argument 1 Passed to {closure} () must be an instance of Illuminat\Database\Query\Builder, instance of Illuminate\Databaase\Eloquent\Relation\HasOne given`
Can any body please let me know how can I get data based on above mentioned condition
$query is a relationship, not a builder instance.
So this should not throw any Exception.
MyBox::with(['access' => function ($query) {
$query->where('mybox_id', $request['id']);
}])->get();
But I don't think it'd resole your issue because your Box <=> Access relationship is not right. It should be HasMany.
// MyBox.php
public function type()
{
return $this->hasOne(BoxType::class, 'id', 'type_id');
}
public function access()
{
return $this->hasMany(MyBoxAccess::class, 'mybox_id', 'id');
}
Then in your Controller you could do this.
// $results where type_id is 3
$results = MyBox::where('type_id', 3)->get();
// List of boxes accessible by email
$results = MyBox::whereHas('access', function ($query) {
$query->where('email', request()->input('email'));
})->get();
// Results where postal_code and po_box matches the request
$results = MyBox::with('access')->where(function ($query) {
if (request()->has('postal_code')) {
$query->where('postal_code', 'like', '%' . request()->input('postal_code'));
}
if (request()->has('po_box')) {
$query->where('po_box', 'like', '%' . request()->input('po_box'));
}
})->get();
And if you want to merge all conditions:
$results = MyBox::where(function ($query) {
if (request()->has('type_id')) {
$query->where('type_id', request()->input('type_id'));
}
if (request()->has('email')) {
$query->whereHas('access', function ($query) {
$query->where('email', request()->input('email'));
});
}
if (request()->has('postal_code')) {
$query->where('postal_code', 'like', '%' . request()->input('postal_code'));
}
if (request()->has('po_box')) {
$query->where('po_box', 'like', '%' . request()->input('po_box'));
}
})->get();
I always use the request() facade when using in closures, it feels cleaner to me.
Try this query:
MyBox::with('access')->get();

How get rows from closest table using one to one?

I have two tables:
Hotels | Countries
country id name
I need to get all notes from Hotels , and get Hotels.country will be name of country: Countries.name
There is function in Hotel model:
public function country()
{
return $this->hasOne('App\Country', 'country', 'id');
}
In controller I try to get all hotels with related countries:
$hotels = Hotel::all();
After I try to get country name for each row from $hotels:
foreach($hotels as $item){
echo $item->country["name"]; // It does not work
}
It should be
public function country()
{
return $this->belongsTo('App\Country', 'country', 'id');
}
After that,
#foreach ($hotels as $hotel) {{ $hotel->country->name }}
should work.
You will need to use eager loading.
$hotels = Hotel::with('country')->get();
Check out the documentation here.
In order to access the country name, it's a normal object:
$hotel->country->first()->name
If you want to have a direct function, in your Hotel Model
Hotel.php
public function countryName()
{
return $this->country->first()->name
}

Resources