In my database, i have two tables notification and alertFrequency. The notification has field id and website_url and the alert frequency has id and notification_id. Both tables has models which is one to many. The notification can have one or many alertFrequency.
class Notification extends Model {
public function alertFrequencies() {
return $this - > belongsToMany('AlertFrequency::class');
}
}
namespace App;
use Illuminate\ Database\ Eloquent\ Model;
class AlertFrequency extends Model {
protected $table = 'alertFrequencies';
public function notification() {
return $this - > belongsTo(Notification::class);
}
}
in the notification model, i wrote a function called alert, that will give me the laastest alert associated with a specific websie.
public function alert(){
$alert_frequency = AlertFrequency::find('notification_id')->first();
$o_notification = $this->alertFrequencies()->where('notification_id',$alert_frequency->id)
->select('created_at')->orderBy('created_at')->first();
if($alert_frequency ==null){
return false;
}
return created_at;
}
Is this a right way to extract the data? i would appreciate any suggestions and helps?
Notification hasMany AlertFrequency
public function alertFrequencies(){
return $this->hasMany('App\AlertFrequency');
}
and,
$alert_frequency = AlertFrequency::with('notification')->orderBy('created_at','desc')->first();
loads the latest AlertFrequency along with it's notification.
See One to Many relationship and Eager loading in documentation.
to get laastest alert associated with a specific websie with url $website_url.
Notification::where('website_url', $website_url)->orderBy('created_at')->first();
hasMany relation :
public function alertFrequencies(){
return $this->hasMany('App\AlertFrequency','notification_id');
}
Related
I have a model called RealEstate, this model has a relation with another model called TokenPrice, I needed to access the oldest records of token_prices table using by a simple hasOne relation, So I did it and now my relation method is like following:
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasOne;
class RealEstate extends Model
{
public function firstTokenPrice(): HasOne
{
return $this->hasOne(TokenPrice::class)->oldestOfMany();
}
}
By far it's fine and no complexity. But now, I need to involve another relation into firstTokenPrice.
Let me explain a bit more:
As my project grown, the more complexity was added it, like changing firstTokenPrice using by a third table called opening_prices, so I added a new relation to RealEstate called lastOpeningPrice:
public function lastOpeningPrice(): HasOne
{
return $this->hasOne(OpeningPrice::class)->latestOfMany();
}
So the deal with simplicity of firstTokenPrice relation is now off the table, I want to do something like following every time a RealEstate object calls for its firstTokenPrice:
Check for lastOpeningPrice, if it was exists, then firstTokenPrice must returns a different record of token_price table, otherwise the firstTokenPrice must returns oldestOfMany of TokenPrice model.
I did something like following but it's not working:
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasOne;
class RealEstate extends Model
{
public function lastOpeningPrice(): HasOne
{
return $this->hasOne(OpeningPrice::class)->latestOfMany();
}
public function firstTokenPrice(): HasOne
{
$lop = $this->lastOpeningPrice;
if ($lop) {
TokenPriceHelper::getOrCreateFirstToken($this, $lop->amount); // this is just a helper function that inserts a new token price into `token_prices` table, if there was none exists already with selected amount
return $this->hasOne(TokenPrice::class)->where('amount', $lop->amount)->oldestOfMany();
}
return $this->hasOne(TokenPrice::class)->oldestOfMany();
}
}
I have checked the $this->hasOne(TokenPrice::class)->where('amount', $lop->amount)->oldestOfMany() using by ->toSql() method and it returns something unusual.
I need to return a HasOne object inside of firstTokenPrice method.
You can use ofMany builder for that purpose:
public function firstTokenPrice(): HasOne
{
$lop = $this->lastOpeningPrice;
if ($lop) {
TokenPriceHelper::getOrCreateFirstToken($this, $lop->amount); // this is just a helper function that inserts a new token price into `token_prices` table, if there was none exists already with selected amount
return $this->hasOne(TokenPrice::class)->ofMany([
'id' => 'min',
], function ($query) use ($lop) {
$query->where('amount', $lop->amount);
});
}
return $this->hasOne(TokenPrice::class)->oldestOfMany();
}
I used ->oldest() with a custom scope called amounted in TokenPrice model:
class TokenPrice extends Model
{
public function scopeAmounted(Builder $query, OpeningPrice $openingPrice): Builder
{
return $query->where('amount', $openingPrice->amount);
}
/....
}
And then changed my firstTokenPrice
public function firstTokenPrice(): HasOne
{
$lop = $this->lastOpeningPrice;
if ($lop) {
TokenPriceHelper::getOrCreateFirstToken($this, $lop->amount);
return $this->hasOne(TokenPrice::class)->amounted($lop)->oldest();
}
return $this->hasOne(TokenPrice::class)->oldestOfMany();
}
It's working, but I don't know if it's the best answer or not
I have a little problem,
i can't see how can i make a three table relation on Laravel.
DELETED
If someone can help me, I take notes !
Thanks !
As far as I can see, you need to create a relationship to your pivot table and then, you can create relationships to both table.
class Contact extends Model
{
public function filmJobs()
{
return $this->hasMany(ContactFilm::class);
}
}
class ContactFilm extends Model
{
public function film()
{
return $this->hasOne(Film::class);
}
public function job()
{
return $this->hasOne(Job::class);
}
}
You can now use it like that: $contact->filmJobs[0]->film and $contact->filmJobs[0]->job.
I have Room, Gallery and Images. I want to associate a gallery to the room and then I want to access the Images of the assigned Gallery using the Room model. I'm new into Laravel, I looked in YouTube lessons, and the documentation but didn't found out a solution for my problem.
Room.php:
class Room extends Model
{
protected $table = 'rooms';
public function gallery()
{
return $this->hasOne('App\Gallery');
}
}
Gallery.php:
class Gallery extends Model
{
protected $table = 'gallery';
public function images()
{
return $this->hasMany('App\Image');
}
public function room()
{
return this->belongsTo('App\Room');
}
}
RoomController.php:
$room = Room::findOrFail($id);
$room_gallery = $room->gallery()->images;
return $room_gallery;
With Eloquent relationships, you access them as properties to access the related model(s) or access the method to query or perform additional manipulation.
Since you want a gallery model and it's related image models, you would access the properties of both:
$room_gallery = $room->gallery->images;
With a HasOne, $room->gallery is essentially equal to $room->gallery()->first(). With HasMany, $gallery->images would be essentially equal to $gallery->images()->get().
However, this may be a case where the HasManyThrough relationship would come in handy.
I have a Laravel 5.5 application and I have the following models.
Jobs
JobSheets
Users
I have a relation on my Users model
public function jobs() {
$this->hasMany('App\Job','user_id')->with('jobSheets');
}
I have a relation on my Jobs model
public function jobSheets() {
$this->belongsToMany('App\JobSheet','jobs_jobsheets','job_id','sheet_id');
}
I'm trying to return all my current logged in users' jobs with the latest job sheet.
A job can have many job sheets but I only want to return the latest.
I've tried in my controller
return Auth::user()->jobs;
However that returns all the jobs sheets against the job.
I've also tried creating another method on my job model.
public function latestJobsheet()
{
return $this->jobsheets->first();
}
and amending my jobs method on the user model to:
public function jobs() {
$this->hasMany('App\Job','user_id')->with('latestJobsheet');
}
but I get the following error:
Call to undefined method
Illuminate\Database\Query\Builder::addEagerConstraints()
You could split the BelongsToMany relationship and add a model for the pivot table (jobs_jobsheets):
class Job {
public function latestJobSheetPivot() {
return $this->hasOne(App\JobSheetPivot::class)->orderBy('sheet_id', 'DESC');
}
}
class JobSheetPivot {
protected $table = 'jobs_jobsheets';
public function jobSheet() {
return $this->belongsTo(App\JobSheet::class);
}
}
class User {
public function jobs() {
return $this->hasMany(App\Job::class)->with('latestJobSheetPivot.jobSheet');
}
}
Assuming your jobs_jobsheets table contains an id column it would probably be best to order the jobSheets returned from newest to oldest.
Here's what that would look like:
public function jobSheets()
{
$this->belongsToMany('App\JobSheet','jobs_jobsheets','job_id','sheet_id')->orderBy('id', 'DESC');
}
If you want to limit the number of results returned you can chain ->limit($num_results) to the end of the belongsToMany method
You can override the $with property on your Job model and have it eager load the relation latestJobsheet. From there, when you access the jobs relation on your User model, you should have the latest job sheet available to you. How you determine the latest job sheet is a separate matter.
I was creating a like system for my website. in this I wanted one user can only like one time for a post. and a post can be liked by many user. Also many user can like many post.
So if I guess it right, It is a many to many reletionship.
in this context,
I create the following table
... users table:
id
name
....
posts table :
id
post
...post_likes table
id
user id
poost_id
Now I am having the following model for
user :
class User extends SentryUserModel {
public function post_likes()
{
return $this->has_many('Post_like', 'id');
}
}
post :
class Post extends Eloquent {
public function post_likes()
{
return $this->has_many('Post_like', 'id');
}
}
post_like :
class Post_like extends Eloquent {
public function posts()
{
return $this->belongs_to('Post', 'post_id');
}
public function users()
{
return $this->belongs_to('User', 'user_id');
}
}
now when I am going to insert into the database (for post_likes table) I am getting an error called
Illuminate \ Database \ Eloquent \ MassAssignmentException
user_id
Also I want to know is there any way to inset into database like
$user->like()->save($user); ?????
Thank you in advance. Happy coding . \m/
I'll start with a basic issue, firstly you might want to make sure all your tables are lower case (still as a snake case as well), it's not required but it's ultimately how it's expected to be with Laravel so it makes life easier to keep with that. Also a note to the wise, like Class names, database tables are typically in the singular so user instead of users
Secondly yes you can do an insert with $user->post_likes()->save($debate); as your post_likes method on the user class returns has_many.
Thirdly, your design of the Post_like class is a bit off, you could be better off make it like so:
class PostLike extends Eloquent { // note that PostLikes is a more standard naming for a class, they should ideally be camel case names but with all capitals for words
protected $table = 'post_like'; // specifies the table the model uses
public function post() // this should be singular, the naming of a belngs_to method is important as Laravel will do some of the work for you if let it
{
return $this->belongs_to('Post'); // by naming the method 'post' you no longer need to specify the id, Laravel will automatically know from the method name and just adding '_id' to it.
}
public function users()
{
return $this->belongs_to('User');
}
}
Fourthly, your other classes could be better as:
class Post extends Eloquent {
public function post_likes()
{
return $this->has_many('PostLike'); // doesn't require you to specify an id at all
}
}
I can't exactly tell you why you're getting that mass assign error, your post is a bit garbled and doesn't look like you've included the code that actually causes the exception? I have a feeling though is that you're trying to do an insert for multiple database rows at one time but haven't defined a fillable array for PostLike such as with here: http://four.laravel.com/docs/eloquent#mass-assignment
According to Laravel 5:
User Model:
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model {
public function post_likes()
{
return $this->hasMany('App\PostLike');
}
}
Post Model:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model {
public function post_likes()
{
return $this->hasMany('App\PostLike');
}
}
PostLike Model:
namespace App;
use Illuminate\Database\Eloquent\Model;
class PostLike extends Model {
protected $table = 'post_like';
public function posts()
{
return $this->belongsTo('App\Post');
}
public function users()
{
return $this->belongsTo('App\User');
}
}
and if you want to save the post_like data then:
$inputs['post_id'] = 1;
$inputs['user_id'] = 4;
$post_like = PostLike::create($inputs);
Hope this helps!!