Get data where comparing two different table in laravel - php

I want to create a feature which the post are require approve by 5 admin in order to display. When a post is created, the post will store in Posts table. The post by default the approved column is false. In order to display the post , it require 3 approval out of 5 admin. So i want get the post from database and show in admin panel. Each time will randomly show 1 post for the admin. If admin approved the post.The approval is storing in other table name Approvals.
The model is
Post model
public function user(){
return $this->belongsTo('App\User');
}
public function post(){
return $this->belongsTo('App\Forum\Post');
}
In approval model
protected $fillable = [
'admin_id',
'post_id',
'approved'
];
public function admin(){
return $this->belongsTo('App\Admin');
}
public function post(){
return $this->belongsTo('App\Forum\Post');
}
In my controller i am using this to get random unapproved post. But now i need to filter out the post, if approval table are contain the approval data by one of the admin. He/she will not see the post again.
$post = Post::inRandomOrder()->where('approved', false)->first();
In case of it might having many post to approve. How can i know that the admin is approved the post so the same post will not showing again to the same admin.

Your post() relationship in your Post model seems like a bug. I think it should be a relationship with your Approval model, right? So first, in your Post model, replace the post() method with:
public function approvals() {
return $this->hasMany('App\Forum\Approval');
}
Then, here's one approach for your query:
$post = Post::inRandomOrder()->where('approved', false)
->with('approvals')
->get()
->filter(function($value, $key) {
// A post without any approvals yet is OK
if ($value->approvals->count() === 0) {
return true;
}
// If it has approvals, check the current admin isn't one of them
return !$value->approvals->contains('admin_id', \Auth::user()->id);
})
->first()

Related

Laravel store() method from api controller not returning updated data

I'm having an issue where the store method in my UserCountries API controller is returning data that seems to be one step behind and I'm not sure why. My app has two models: Country and User, which have a many-to-many relationship with a pivot table. In my app a particular user should be able to 'like' and 'unlike' a country.
This mostly works as expected, however my issue is that the data returned on each request is one step behind - e.g., if I send a POST request to like a particular country, I get a 200 response but I am returned a UserCountriesResource which does not include that country that should have just been added. If I then immeditaely send a GET request, it returns a UserCountriesResource which does include that country. Can anyone help me figure out why?
Here are my routes:
Route::group(["prefix" => "me/countries"], function(){
Route::get("", [UserCountries::class, "index"]); // see all countries liked by user
Route::post("", [UserCountries::class, "store"]); // add or remove country from user
});
My index method in the UserCountries controller is below:
public function index()
{
return CountryResource::collection(auth()->user()->countries);
}
My store method in the UserCountries controller is below:
public function store(UserCountriesRequest $request)
{
$user = auth()->user();
$user->setCountries($request->get("countries"));
return new UserCountriesResource($user);
}
The store method calls the setCountries method in the User model:
public function setCountries(array $strings) : User
{
$countries = Country::fromStrings($strings);
$countries->map(function($country) use($countries){
if($this->countries->contains($country)){
Country::find($country->id)->users()->detach($this->id);
} else {
$this->countries()->syncWithoutDetaching($country->id);
}
});
return $this;
}
The setCountries method above in turn calls the fromStrings method in the Country model:
public static function fromStrings(array $strings) : Collection
{
return collect($strings)->map(fn($str) => trim($str))
->unique()
->map(fn($str) => Country::firstOrCreate(["NAME"=>$str]));
}
Do let me know if there's anything else I can add to make this more helpful!
You are loading the relationship before you are adding/removing any of the related records. That loaded relationship, Collection, won't include these changes. You will need to reload the relationship to get the new list of related records.
I don't know the rest of your code but you would add a call like this, if this was the case:
$user->load('countries');
This is loading the relationship (if it wasn't already loaded):
if($this->countries->contains($country))

show data if you have user id - laravel

I am creating a data list and I print it with foreach, i would like it to display the data only if user_id matches the user_id reading the data. (previously I already have the user authentication created)
I want the users who enter to only see the data that contains their user_id.
I already made the relationship between the users table 'id' field with user_id
pass the data with:
public function index()
{
$servicios = App\Servicio::all();
return view('home', compact('servicios'));
}
How do I show the data that corresponds to the user_id of each one without others seeing their data??
You could set up a relationship inside the User.php model.
public function servicios() {
return $this->hasMany(Servicio::class);
}
Then in your controller:
public function index()
{
$servicios = auth()->user()->servicios;
return view('home', compact('servicios'));
}
You can get the user's list of services easily using Auth::user(), example:
User::with(['servicios'])->find(Auth::id());
you should get the user from your request, then filter by its id ...
public function index()
{
$user_id=app('request')->user()->id;
$servicios = App\Servicio::where('user_id',$user_id)->all();
return view('home', compact('servicios'));
}
the user will be present in your request, to make sure of that you should but
the route that use this method in (auth) middleware

PHP Laravel 5.2: Eloquent relationship for subscriptions

I think I got a little stuck and I just need someone to clarify things. So what I got is a user system which includes subscriptions for people to "subscribe" to their content (as you already know it from FB, Twitter, YT etc).
My database model looks like this:
Users
id
username
Subsccriptions
id
user_id
sub_id
Currently I have one model for Users and one Model for Subscriptions. The model from the user:
public function subscriptions()
{
return $this->hasMany('App\Subscription');
}
In comparison, my subscription object:
public function user()
{
return $this->belongsTo('App\User');
}
So in my personal opinion this is a 1:many relationship. If I call the user object with User->subscriptions()->get() I can get the subscription and it's sub id, so I know who THE CURRENT user has subscribed.
People told me the opposite and it's supposed to be a many-to-many relationship. Did I do something wrong? Can I automatically convert the sub_id into a user through relationships in Eloquent?
// EDIT:
Here is the current code to receive my subscribers for a user
public function index()
{
$subs = Auth::user()->subscriptions()->get()->all();
$submodels = [];
foreach($subs as $sub) {
array_push($submodels,User::find($sub->sub_id));
}
return view('home', [
'subscriptions' => $submodels
]);
}
}

Update a column that exist in the many to many relationship table in laravel 5.2

I have three tables which are User table, Events table, and Events_user table. I have four columns in the Events_user table which are :
Schema::create('events_user', function(Blueprint $table){
$table->increments('id');
$table->integer('user_id')->unsigned()->index();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->integer('events_id')->unsigned()->index();
$table->foreign('events_id')->references('id')->on('events')->onDelete('cascade');
$table->integer('eventstatus')->unsigned()->index();
$table->timestamps();
});
I have a function which add an event base on the user id, show one user can have many of the events. But the event can share to other user. The function is like this :
public function store(EventsRequests $request){
$id = Auth::user()->id;
$events= Events::create($request->all());
$events->user()->attach($id); //Store the User_ID and the Event_ID at the events_user table.
Flash::success('Your event has been created!');
return redirect('/');//Return into home page
// return $events;
}
Then it will help me update my events_user table, but how do I update the column which is eventstatus?
Can anyone show me how could I update it? Cause I want to use the eventstatus help me determine if there is '1' then cant be edit, then the edit button will disappear.
How many way can accomplish to the function?
For the show page:
I have use the function when the user click the event that exist on the calendar view, then the javascript will pass the id back and redirect to the view with the id.
public function show($id){
// $user_id=Auth::user()->name;
$showevents = Events::findOrFail($id);
return view('events.show',compact('showevents','user'));
}
How about when i want to pass the eventstatus into the view? So i can check on my view, if the eventstatus equal to one, the edit button wont show up.
Updated relationship model
User.php
public function events(){
return $this->belongsToMany('App\Events');
}
Events.php
public function user(){
return $this->belongsToMany('App\User')->withPivot('eventstatus');
}
If you want to update the field while making the association, you can pass an array of field=>value pairs as the second parameter to the attach() method. You can read in the documentation here.
$events->users()->attach($id, ['eventstatus' => 1]);
If you want to update the field for an existing association, you can pass an array of field=>value pairs to the save() method:
$user = Auth::user();
$event = $user->events()->first();
$user->events()->save($event, ['eventstatus' => 1]);
If you want to access the field to read the data, you can access it through the pivot property:
$user = Auth::user();
foreach ($user->events as $event) {
echo $event->pivot->eventstatus;
}
In addition to all of this, you need to make sure your relationship definitions include access to the extra property:
// User class:
public function events() {
return $this->belongsTo(Event::class)->withPivot('eventstatus');
}
// Event class:
public function users() {
return $this->belongsTo(User::class)->withPivot('eventstatus');
}
Edit
updated answer for additional question
To get the information you're looking for, you need to be able to get to the pivot record. The pivot record is available on the models in the loaded relationship.
Since you have the Event, you need to go through the related User models, find the user you want (assuming the logged in user), and then get the status off of the pivot attribute on that user.
public function show($id)
{
// get your event
$showevents = Events::findOrFail($id);
// get your user
$user = Auth::user();
// default status to send to view
$status = 0;
// if there is a user...
if ($user) {
// find the user in the "user" relationship
// NB: calling "find" on a Collection, not a query
$eventUser = $showevents->user->find($user->id);
// if the user is associated to this event,
// get the status off the pivot table,
// otherwise just set the default status
$status = $eventUser ? $eventUser->pivot->eventstatus : $status;
}
// add your status to the data sent to the view
return view('events.show', compact('showevents', 'user', 'status'));
}
In addition to all this, make sure both relationship definitions include the ->withPivot('eventstatus'). You want to make sure you can get at it from both sides, if need be.
Can you share your event and user model relationship code?
so , it will help me to get into deep.
OR
you can try this in event model like:
public function user()
{
return $this->belongsToMany('App\Event')
->withPivot('eventstatus')
->withTimestamps();
}
then while updating you can do something like this iam not sure but hope this help.
$events->user()->attach($id,['eventstatus' => 1]);
Thanks
For fetching extra column:
public function show($id){
$showevents = Events::findOrFail($id);
$event_status = $showevents->pivot->eventstatus;
return view('events.show',compact('showevents','event_status'));
}
but for that you have to define this column in models:
// User class:
public function events() {
return $this->belongsTo(Event::class)->withPivot('eventstatus');
}
// Event class:
public function users() {
return $this->belongsTo(User::class)->withPivot('eventstatus');
}

Laravel Object queries - 3 tables

I have three tables like this:
**Users**
id
**Posts**
id
user_id
**Favorites**
id
user_id
post_id
Currently, I made it so when I query my posts for display, it pulls all the related user data who created the post with that row which is great! But what I'm trying to do now is also add to see if the user Authorized (Logged in) has favorited the post (row) so I can display to that they already favorited it. I don't want to re-query for every post (i think its called the N+1 problem?). I'm using Laravel4
Post model
class Post extends Eloquent{
public function user(){
return $this->belongsTo('User');
}
User model
public function posts(){
return $this->hasMany('Post');
}
PostsController
public function index()
{
$posts = Post::with('user')->paginate(25);
return View::make('index', compact('posts'));
}
Step 1. Add favorites relationship in Post model.
public function favorites() {
return $this->hasMany('Favorite');
}
When querying the Model.
$auth_user_id = Auth::user()->id;
$posts = Post::with(array('user', 'favorites' => function($query) use ($auth_user_id){
$query->where('user_id', '=', $auth_user_id);
}))->get();
For more information refer to the eager load constraints,
http://laravel.com/docs/eloquent#eager-loading
Adding a many-to-many relationship using the favorites table as pivot would be one approach.
Add favorites relationship in User model:
public function favorites() {
return $this->belongsToMany('Post', 'favorites');
}
You should then be able to get all favorites by simply accessing
Auth::user()->favorites
To find whether the current post is a favorite, use
$isFavorite = Auth::user()->favorites->has($post->id);

Categories