Each industry has many projects
each project belongs to only one industry
industries table has columns as below:
id, industry_name, industry_code, created_at, updated_at
projects table has columns as below:
id, industry_id (foreign key), user_id, project_name, project_start_date, project_end_date, created_at, updated_at
I want to show project name and industry name in my index.blade.php (view)
I have created Project & Industry models. How do I show the result in my view?
Industry.php model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Industry extends Model
{
public function project()
{
return $this->hasMany('App\Models\Project');
}
}
Project.php model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Project extends Model
{
public function industry()
{
return $this->belongsTo('App\Models\Industry');
}
}
like this ...
$Industry = App\Industry ::find(1);
echo $Industry ->Project ->project_name;
https://laravel.com/docs/5.5/eloquent-relationships#one-to-many
do try renaming your method "project" to "projects" in Industry.php since it is a "hasMany" relationship. this would prevent you from making errors.
in your controller, say PagesController.php
public function index() {
// find an industry with id of 1
$Industry = App\Industry ::find(1);
return view('some_view',compact('industry'));
}
therefore in your view, since an industry has many projects you can access them and loop over them by $Industry->projects. However you should consider eager loading them in order to prevent the n + 1 problem. there edit your query to $Industry = App\Industry ::with('projects')->find(1);
read more on eager loading https://laravel.com/docs/5.5/eloquent-relationships#eager-loading
https://laravel.com/docs/5.5/eloquent-relationships#one-to-many
If specifically you want only project_name and industry_name then
try this -
$result = App\Industry::with(array('projects'=> function($query){
$query->addSelect(['project_name']);
}))
->where('industry.id',$id)
->get([industry_name]);
else for all records try this -
$result = App\Industry::with('projects')
->where('industry.id',$id)
->get();
Hope this will help you.
Related
I have three relational table attached below.
https://drive.google.com/file/d/1q1kdURIwFXxHb2MgdRyBkE1e3DMug7r-/view?usp=sharing
I have also three separate models where defined relation among all of my table's.I can read the City Model's information from Country model using hasManyThrough() relation But cannot read the Country information from City model. I have tried to retrieve City model's using ``hasManyThrough``` but didn't get result (attached as commented country method ). Please read my model and it's relational method here..
Is there someone to help me for getting City model's information using Eloquent method hasManyThrough / hasManyThrough or using inverse of hasManyThrough / hasManyThrough ?
01.
<?php
namespace App\Hrm;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Country extends Model
{
//use SoftDeletes;
protected $fillable = ['name','description','status'];
public function districts(){
return $this->hasMany(District::class);
}
public function cities(){
return $this->hasManyThrough(City::class,District::class);
}
}
02.
<?php
namespace App\Hrm;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class District extends Model
{
//use SoftDeletes;
protected $fillable = ['country_id','name','description','status'];
public function country(){
return $this->belongsTo(Country::class);
}
public function cities(){
return $this->hasMany(City::class);
}
}
3.
namespace App\Hrm;
use App\User;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class City extends Model
{
//use SoftDeletes;
protected $fillable = ['district_id','name','description','status'];
public function district(){
return $this->belongsTo(District::class);
}
// public function country(){
// return $this->hasOneThrough(Country::class, District::class);
// }
Doesn't look like there is a native way to define the inverse of a "hasManyThrough" relationship yet in Laravel. There have been a few issues opened on github to request it, but they were closed.
You could use the staudenmeir/belongs-to-through package if you don't mind installing a third-party package for this functionality. Then you should be able to define a belongsToThrough relationship like this:
class City extends Model
{
use \Znck\Eloquent\Traits\BelongsToThrough;
public function country() {
return $this->belongsToThrough(Country::class, District::class);
}
}
Why can't use parent method?
$city = City::find(1);
$country = $city->district->country();
i just had a similar situation i was able to accomplish a belongsToThrough with hasOneThrough
public function country()
{
return $this->hasOneThrough(
Country::class, // model we are trying to get
District::class, // model we have an _id to
'id', // WHERE `district`.`id` = `city`.`district_id`
'id', // `countries`.`id`
'district_id', // local column relation to our through class
'country_id' // `district`.`country_id`
);
}
what this should generate is
SELECT * FROM `countries`
INNER JOIN `districts`
ON `districts`.`country_id` = `countries`.`id`
WHERE `districts`.`id` = ?
-- ? == city.district_id
Database structure:
City:
id: increments
district_id: integer
...
Country:
id: increments
...
District:
id: increments
country_id: integer
...
we can then do $city->country
note: i have not fully tested this but with the testing that i have done it 'works'
Edit: i originally thought that i needed to leave the localKey
parameter null otherwise the relation wont work. it turns out i didnt
fully understand what that column was doing and that was wrong. That
key is the local column that relates to our through column (unless i
still have more to learn/figure out), when left the value as null, it
would use the local id column which a. is the wrong value, b. can also
be out of range (which is how i discovered it was using the wrong
value)
in my testing i only had two rows, both with the same relations. what
i didnt realize though was that on the "through table" both row 1 and
2 and the same related (relation where are trying to reach) so i didnt
notice the issue right away. hopefully now its all working
I'm trying to create a variable that contains the last 7 images that have been liked by a user with certain id so I can pass that variable to my view. I believe I have to use whereHas() but so far nothing I've tried work so it's probable I might be doing it wrong.
The tables I have are:
Table: Votes
Columns: id, user_id, image_id, vote
Table: Users
Columns: id, username, password
Table: Images
Columns: id, name, user_id, path
In the votes table, if the vote value is 1, it is a like and of it is 0, it is a dislike.
I have models for the 3 tables like this:
Image
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Image extends Model
{
public function user(){
return $this->belongsTo('App\User');
}
public function votes(){
return $this->hasMany('App\Vote');
}
}
User:
<?php
namespace App;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
class User extends Model implements Authenticatable
{
use \Illuminate\Auth\Authenticatable;
public function images(){
return $this->hasMany('App\Image');
}
public function votes(){
return $this->hasMany('App\Vote');
}
}
Vote:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Vote extends Model
{
public function images(){
return $this->belongsTo('App\Images');
}
}
I was able to figure something close to what I have in mind:
$likedImages = Image::where('parent_id', NULL)->whereHas('votes', function($q) use ($vote) {
return $q->where('vote', $vote);
})->orderBy('created_at', 'desc')->limit(7)->get();
Unfortunately, this gets liked images by everyone and not just the specific user.
Normally whereHas() will do the trick, if you want the images that has been voted you do something like
Image::whereHas('votes',function($votes) {
//if you want to get only votes with 1 you do
$votes->where('vote',1);
})
//if you want to get the latest 7 images you order them and take 7
->orderBy('id','DESC')
->take(7)
->get();
That will get you all the images that has a votes row, If that fails, maybe your relationships are not set properly.
You need to use the Vote model, and fetch the recent 7 votes where the like value is 1 and LEFT JOIN the images table.
I am not an ORM specialist but...
An untested example:
$votes = Vote::where([
["user_id", "=", $userId],
["vote", "=", 1]])->leftJoin("images", "user_id", "=", "images.user_id")->latest()->take(7);
Again, this is untested, but I gave you the idea.
I am new to Laravel and also asked the question on Laracast without any success so far.
Here is my problem: I have a database layout something like this:
Table: categoryA_products
Table: categoryB_products
Table: categoryC_products
and per default the Laravel user table:
Table: user
I have create a two Laravel Eloquent models:
Product:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
// protected $table = '';
public function users()
{
return $this->belongsTo( User::class );
}
}
User:
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
public function products()
{
return $this->hasMany( Product::class );
}
}
As each product has a different table name I would normally create 1 model for each table but as they are all similar I would like to define the model table name at runtime.
I know I can do this with "$product->setTable()" but as I use the "newRelatedInstance" class from Laravel (hasMany and belongsTo) I cannot initiate the product class and set the table.
Is there a workaround for this?
Yes, I am aware that I could create a category table and link the products to each category but this is a fictional database model. There is a reason for this approach and I can explain it more in detail if needed. That said it make sense for this sample but I cannot use it for the live database.
I have a working solution with a model for each "category" but this is very messy.
Any help would be appreciated.
Since you're unable to load the relations, you could try referencing and re-initializing them like:
$relations = $product->getEagerLoads();
$attributes = $product->getOriginal();
table_name = 'categoryA_products'; // or categoryB_products or categoryC_products
$product->newQuery()
->newModelInstance($attributes)
->setTable($table_name)
->setEagerLoads($relations)
->...
I have the database structure that have a classes table, a users table and users_classes table that matches the other two, because a user can belong to multiple classes. I have a problem now. I have code like this:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
class Classes extends Model
{
protected $table = 'classes';
public function students()
{
}
}
And I want to be able to access the students of the class by typing $class = Classes::find(1) and then $class->students to access the students. How do I define the relationship without using the query builder? I want to use eloquent. Im a noobie in Laravel pls dont downvote.
You use a belongsToMany relation.
If your users_classes table has the fields user_id and class_id you can do the following:
public function students()
{
return $this->belongsToMany(Student::class, 'users_classes', 'class_id', 'user_id');
}
I have two tables like below:
users table:
id - fname - lname
users_projects table:
id - user_id - title
my models are inside a directory called Models:
Users model :
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Users extends Model
{
//
public function usersProjects()
{
return $this->belongsTo(UsersProjects::class);
}
}
UsersProjects model:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class UsersProjects extends Model
{
protected $table = 'users_projects';
//
public function users()
{
return $this->hasOne(Users::class);
}
}
now, I want to show last projects :
$projects = UsersProjects::limit(10)->offset(0)->get();
var_dump($projects);
return;
but my var_dump shows last projects ! I want to have fname and lname ! where is my wrong ?
I think you may have your relationships set up a little wrong. If a user can have more than one project, in your user model ...
public function usersProjects()
{
return $this->hasMany(UsersProjects::class);
}
You might want to use a little simpler naming too ...
public function Projects()
{
return $this->hasMany(UserProject::class);
}
(or simply Project if you don't have any other "Project" models)
The in your "Project" class ...
public function User()
{
return $this->belongsTo(User::class);
}
(assuming you rename your model to User instead of "Users". Your table name should be "users" but a model is by nature a singular object. So it's appropriate to call it "User" - and your UsersProjects model should just be UserProject or just Project)
Now if you call the method something other than "User" you will have to add the foreign key name ...
public function SomeOtherName()
{
return $this->belongsTo(User::class, 'user_id');
}
Then ...
$projects = Project::with('User')->limit(10)->offset(0)->get();
Will return a collection of projects with the User eager-loaded. (assuming you have renamed your UsersProjects model to "Project")
#foreach($projects as $project)
...
First Name: {{ $project->User->fname }}
...
#endforeach
Could you specify the relationships between the tables? (one to one, one to many) at first sight, I think that the relations are wrong