Querying one-to-one in laravel - php

I have two models city and business.I have to perform below queries
Find Business by city name.
Find Top 10 cities which have the maximum business.
Here is the models
Business
class Business extends \Eloquent
{
protected $fillable = [
'business_type',
'first_name',
'last_name',
'email',
'password',
'designation_id',
'name',
'description',
'portfolio_id',
'image',
'city_id',
'package_id',
'group_tag_id'
];
public function city()
{
return $this->belongsTo('City');
}
}
City
class City extends \Eloquent
{
protected $fillable = ['name', 'district_id'];
public function business()
{
return $this->hasMany('Business');
}
}
So How can i do this?

Hi You can fetch this by this ways :
Find Top 10 cities which have the maximum business:
$city = City::with('business')->get()->sortBy(function($query) {
return $query->business->count();
}, SORT_REGULAR, true)
->take(10);
Find Business by city name.
Business::whereHas('city', function ($q) {
$q->where('name', 'like', 'search_string');//name is the city_name as per your attributes name
})->get();

Related

Is there a way to get a nested Eloquent model based on ids from another table?

Hey there stackoverflow
I am currently building a course application as part of my laravel project.
My problem lies in how the eloquent handle model relations, i'm still kinda new to eloquent, so hopefully you can answer my question.
The structure
The Course has many episodes and each episode has many sections.
Which means I have 3 tables in the DB. Courses -> course_episodes -> course_episode_sections
ID table is where i connect courses with users - course_users.
Right now i can create courses and and put in all the data correctly.
The Problem
I need to retrieve all the courses and its nested children that the user has bought, which is connected in the course_users table with columns course_id and user_id
Course structure
Same stucture in DB
course: {
name: null,
sub_title: null,
estimate: null,
trailer: null,
type: null,
text: null,
course_episodes: [
{
name: null,
section: [
{
order: null,
type: null,
content: null,
},
]
},
]
}
Model Pictures
My models as of right now.
class CourseUsers extends Model {
protected $fillable = [
'id',
'course_id',
'user_id',
'active',
];
protected $hidden = [
'deleted_at',
'updated_at',
'deleted_at'
];
public function courses()
{
return $this->belongsToMany(Course::class);
}
public function user(){
return $this->belongsTo(User::class);
}
public function scopeFindForUserId($query, $userId)
{
return $query->where(function ($q) use ($userId) {
$q->where(function ($q) use ($userId) {
$q->where('user_id', $userId);
});
});
}
Course model
class Course extends Model{
protected $fillable = [
'id',
'name',
'sub_title',
'type',
'estimate',
'trailer',
'gateway_id',
'text',
'active',
];
protected $hidden = [
'deleted_at',
'updated_at',
'deleted_at'
];
public function courseEpisode()
{
return $this->hasMany(CourseEpisode::class);
}
public function courseUsers() {
return $this->hasMany(CourseUsers::class);
}
public function scopeActive(Builder $builder)
{
return $builder->where('active', true);
}
Course episode Model
class CourseEpisode extends Model implements HasMedia {
use HasMediaTrait;
protected $fillable = [
'id',
'course_id',
'order',
'name',
];
protected $hidden = [
'deleted_at',
'updated_at',
'deleted_at'
];
public function course()
{
return $this->belongsTo(Course::class);
}
public function courseSection()
{
return $this->hasMany(CourseEpisodeSection::class);
}
Course episode sections
class CourseEpisodeSection extends Model {
protected $fillable = [
'id',
'course_episode_id',
'order',
'type',
'content'
];
protected $hidden = [
'deleted_at',
'updated_at',
'deleted_at'
];
public function courseEpisode()
{
return $this->belongsTo(CourseEpisode::class);
}
According to your explanation, course_users table holds many-to-many relationship between Course and User model. In case of a many-to-many relationship, you actually don't need a CourseUser model. This kind of table which holds many-to-many relationship is called pivot table. Read more from the Official Documentation
I am defining only the relationships with your Course, User, CourseEpisode, CourseEpisodeSection models.
Course.php
class Course extends Model
{
public function courseEpisodes()
{
return $this->hasMany(CourseEpisode::class);
}
public function users()
{
return $this->belongsToMany(User::class,'course_users')->withPivot('active');
}
}
CourseEpisode.php
class CourseEpisode extends Model
{
public function courseSections()
{
return $this->hasMany(CourseSection::class);
}
}
User.php
class User
{
public function courses()
{
return $this->belongsToMany(Course::class,'course_users')->withPivot('active');
}
}
If you want to get all the children relationships from a user, use nested eager loading :
$user_with_nested_course_data = User::with('courses.courseEpisodes.courseSections')->find($id);

Laravel : How to get all users who have a certain role?

I have three roles: 1. Admin 2. Client 3. Store
I have three tables: 1. users 2. roles 3.role_user
How can I get all users who have the role Client?
I tried this
$clients = User::roles()->where('App\Models\Role',Role::CLIENT)->get();
I'm getting following error.
Non-static method App\Models\User::roles() should not be called
statically
Role Model
class Role extends Model
{
public const ADMIN = 'Admin';
public const CLIENT = 'Client';
public const STORE = 'Store';
public function users()
{
return $this->belongsToMany('App\Models\User')->using('App\Models\UserRole');
}
}
User Model
class User extends Authenticatable
{
use Notifiable;
protected $fillable = [
'name',
'first_name',
'last_name',
'email',
'password',
'activated',
'token',
'signup_ip_address',
'signup_confirmation_ip_address',
'signup_sm_ip_address',
'admin_ip_address',
'updated_ip_address',
'deleted_ip_address',
];
protected $hidden = [
'password', 'remember_token',
];
protected $casts = [
'email_verified_at' => 'datetime',
];
public function hasRole(String $roleName)
{
return $this->roles()->where('name', $roleName)->exists();
}
public function roles()
{
return $this->belongsToMany('App\Models\Role');
}
public function addRole(String $roleName)
{
$role = Role::where('name', $roleName)->first();
if ($role) $this->roles()->save($role);
}
}
You can do it with whereHas() method. it's a way to condition on relation using exists in query
$clients = User::whereHas('roles', function($role) {
$role->where('name', '=', Role::CLIENT);
})->get();
If you want to get the role too, stack the with() method
$clients = User::whereHas('roles', function($role) {
$role->where('name', '=', Role::CLIENT);
})->with(['roles' => function($role) {
$role->where('name', '=', Role::CLIENT);
}])->get();
That's because you're trying to call the roles method on the Model class and not the instance, here's how it should be
$clients = Role::whereName('client')->first()->users;

Laravel 5.2 Model Relationships

im new to Laravel and have a relationship question.
The goal is to get all News where news.page_id = page.id AND page.pagetype_id = pagetype.id WHERE pagetype.component = news AND page.app_id = 1
class News extends Model
{
protected $table = 'news';
protected $fillable = ['page_id', 'title', 'description', 'active', 'created_at', 'updated_at'];
}
class Page extends Model
{
protected $table = 'pages';
protected $fillable = ['app_id', 'unique_id', 'pagetype_id', 'title', 'picture_url', 'short_description', 'description', 'valid_since', 'valid_until', 'extras', 'active', 'created_at', 'updated_at'];
public function pagetype() {
return $this->belongsTo('App\Models\PageType', 'pagetype_id');
}
}
class PageType extends Model
{
protected $table = 'pagetypes';
protected $fillable = ['pagetype', 'component', 'active', 'created_at', 'updated_at'];
public function page() {
return $this->belongsToMany('App\Models\Page', 'pagetypes', 'id', 'id');
}
}
// now i need All News Items where page.pagetype_id = pagetypes.id and patchtypes.component = news
// First Attempts are
Page::whereHas('pagetype', function ($q) {
$q->where('component', 'news');
})->where(['app_id' => 1])->get();
// result is all Pages which has the proper component news.
This is what i have tried yet, but in my attempt i'll only receive the proper pages but of course not the news.
My "current" solution is to get all the pages and then loop through News::where('page_id', $myPageId). But im pretty sure its possible to get a proper relationship to get also news.
I cant do any other model since there are many different pagetypes and components aswell.
Thanks so far.
You need to add relationship function to news model.
public function pages() {
return $this->belongsTo('App\Models\Page');
}
And call it through News model.
News::with('pages')->where('app_id',1);
First off all I think that you are wrong with you PageType relation
class PageType extends Model
{
protected $table = 'pagetypes';
protected $fillable = ['pagetype', 'component', 'active', 'created_at', 'updated_at'];
public function page() {
return $this->hasMany('App\Models\Page');
// if i understood you correctly you haven't got any pivot table
}
}
Then you should link your News and Page like so
News.php
class News extends Model
{
protected $table = 'news';
protected $fillable = ['page_id', 'title', 'description', 'active', 'created_at', 'updated_at'];
public function page() {
return $this->belongsTo('App\Models\Page');
}
}
Page.php
class Page extends Model
{
protected $table = 'pages';
protected $fillable = ['app_id', 'unique_id', 'pagetype_id', 'title', 'picture_url', 'short_description', 'description', 'valid_since', 'valid_until', 'extras', 'active', 'created_at', 'updated_at'];
public function pagetype() {
return $this->belongsTo('App\Models\PageType');
}
public function news() {
return $this->hasMany('App\Models\News');
}
}
Then you can achieve your goal
News::whereHas('page', function($q) use($appId) {
$q->where('app_id',$appId);
})->whereHas('page.pagetype', function($q) {
$q->where('component', 'news');
})->get();

Laravel Relationships recursive

I have 3 Models:
City:
protected $fillable = [
'name', 'latitude', 'longitude', 'code', 'country_id', 'status', 'weather_code',
];
public function translations() {
return $this->hasMany('App\Models\CityTranslation');
}
public function country() {
return $this->hasMany('App\Models\Country');
}
CityTranslation
protected $fillable = [
'name', 'lang', 'city_id',
];
public function city() {
return $this->hasOne('App\Models\City', 'id', 'city_id');
}
and Country
protected $fillable = [
'code', 'latitude', 'longitude', 'currency_id', 'timezone', 'dam_date', 'status',
];
public function city() {
return $this->hasMany('App\Models\City');
}
My problem is when a go through my CityTranslations and display the city name for the selected language i want also to show information about the city and its country.
There is no problem to call $cityTranslation->city->longitude, but when i call $cityTranslation->city->country->code it gives me a MySQL error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'countries.city_id' in 'where clause' (SQL: select * from `countries` where `countries`.`city_id` = 4439 and `countries`.`city_id` is not null)
How can I make recursive relations?
Try
$cityTranslation = \App\CityTranslation::with('city.country')->get();
Thats if you want to get all city Translation and it related city and country. The you can loop through and get the country code.
if you want to pick only one city Translation and it related item you can do
$cityTranslation = \App\CityTranslation::with('city.country')->find($id);
Change this (in your city model)
public function country() {
return $this->hasMany('App\Models\Country');
}
to
public function country() {
return $this->belongsTo('App\Models\Country');
}
Because country can have many cities and every city must belong to a country

How to use the `where` method along with the `with` method in laravel 4?

Given the following, very simple, example:
Country Class
class Country extends Eloquent {
protected $table = "countries";
protected $fillable = array(
'id',
'name'
);
public function state() {
return $this->hasMany('State', 'country_id');
}
}
State Class
class State extends Eloquent {
protected $table = "states";
protected $fillable = array(
'id',
'name',
'country_id' #foreign
);
public function country() {
return $this->belongsTo('Country', 'country_id');
}
}
How can I list all the states, based on the id or the name of the country.
Example:
State::with('country')->where('country.id', '=', 1)->get()
The above returns an area, as country is not part of the query (Eloquent must attach the join later, after the where clause).
I think you're either misunderstanding the relations or over-complicating this.
class Country extends Eloquent {
public function states() {
return $this->hasMany('State', 'state_id');
}
}
$country = Country::find(1);
$states = $country->states()->get();

Categories