I have implemented a like/favourite function in my application, where a user can favourite a Charity - this is then stored in a table in my database - which is working reasonably well.
How would I go about outputting the users favourites list to them on their profile page?
Profile View (Where I want to output):
<div class="favourite_section">
<div class="col-md-5 pull-right">
<div class="panel panel-default">
<div class="panel-heading">
Edit
<h3 class="panel-title"> Your Favourites </h3>
</div>
<div class="panel-body">
<!-- Output users' favourites. -->
<h4> </h4>
</div>
</div>
</div>
Like Controller:
<?php
namespace App\Http\Controllers;
use App\Like;
use Illuminate\Support\Facades\Auth;
class LikeController extends Controller
{
public function likePost($id)
{
$this->handleLike('App\charity', $id);
return redirect()->back();
}
public function handleLike($type, $id)
{
$existing_like = Like::withTrashed()->whereCharityImg($type)->whereCharityDesc($type)->whereCharityName($type)->whereCharityId($id)->whereUserId(Auth::id())->whereId($id)->first();
if (is_null($existing_like))
{
Like::create([
'id' => $id,
'user_id' => Auth::id(),
'charity_id' => $id,
'charity_name' => $type,
'charity_desc' => $type,
'charity_img' => $type
]);
}
else
{
if (is_null($existing_like->deleted_at))
{
$existing_like->delete();
}
else
{
$existing_like->restore();
}
}
}
}
You're able to retrieve the currently logged in user with Laravel's Authentication Facade or, if you prefer using helpers, auth()->user(). In a similar vein, you can do Auth::id() to skip the object and get the user's id directly. In your controller, you'll want to query the Like model where the user_id of the Like is equal to the user id of the logged in user:
$likes = Like::whereUserId(Auth::id())->get();
This will return a collection of likes which should be passed to the view from the controller, like so:
return view('profile', compact('likes'));
Replace 'profile' with whatever the view file for the profile page is. Then in the Blade template, you'll have access to a $likes variable, which you can iterate over:
#foreach($likes as $like)
// Do what you want with each like
#endforeach
Your situation is called many to many relationship.
Laravel docs
Laravel makes it easy. You should write a method to you User model.
Something like:
public function favourites() {
return $this->belongsToMany('App\Charity', '[Like model table name]', 'user_id', 'charity_id');
}
You then can use it like: $user->favourites and it will return collection of favourite charities.
You can read docs if you want.
Related
I want to show the emails that the logged in user has sent from the database
This is the route code:
Route::get('/myEmails/{id}','PagesController#myEmailsShow');
This is the function in the controller:
public function myEmailsShow($id)
{
$myEmails = DB::table('emails')->where('user_id',$id)->get();
return view('content.myEmails', compact('myEmails'));
}
This is the a link where the user click to open the page:
#if(Auth::check())
<a class="nav-link text-white" href="/myEmails/{id}"> my emails</a>
#endif
And here where i want to show the data (i am showing only the name for test):
<div class="row">
#foreach($myEmails as $myEmail)
{{$myEmail->name}}
#endforeach
</div>
I think the best way to accomplish your goals here would be using a hasMany relationship between User and Emails (if emails is a Model).
//User.php
public function emails()
{
return $this->hasMany('App\Models\Email');
}
In the controller, apply the Auth middleware to the myEmailsShow method in a constructor:
//PagesController.php
public function __construct()
{
$this->middleware('auth')->only(['myEmailsShow']);
}
Then, in your myEmailsShow method, do something like the following:
//PagesController.php
public function myEmailsShow()
{
// Middleware Eliminates the need for ID in the function.
$user = auth()->user();
$myEmails = $user->emails;
return view('content.myEmails', compact('myEmails'));
}
You can remove the ID parameter from the route and just make it something like Route::get('/myEmails', 'PagesController#myEmailsShow');. Only users who are logged in will be able to access this page, and they will only see emails belonging to them.
Route::get('/myEmails/{user}','PagesController#myEmailsShow')->name('myemails');
with the controller
use App\Email;
use App\User;
public function myEmailsShow(User $user)
{
///calling the model Email at parameters instead of $id eloquent automatically the data from DB
$myEmails = Email::where('user_id',$user->id)->get();
return view('content.myEmails')->with('myEmails', $myEmails);
}
The link has little modifications
#if(Auth::check())
<a class="nav-link text-white" href="{{route('myemails', $user->id)}}"> my emails</a>
#endif
displaying the value
#foreach($myEmails as $myEmail)
{{$myEmail->name}}
#endforeach
I have a few problems.
I can't seem to display the saved data inside my form inputs.
I can't get my urls to validate unique.
My controller code looks very redundant.
Getting the urls to validate unique takes priority though.
Also I created the table for sharing social links with a user one to many relationship. I think thats correct. If not, please correct me.
update Just a thought...I think I'm probably complicating things by only have a single 'type' column. It would be easier if I had a column for each type of link i.e facebook col, twitter col etc. I just didn't want empty columns if user didn't provide info for some services
Heres my code:
UPDATE I gave up and just added individual columns for the different types of urls and changed to a one-to-one relationship.
form
{!! Form::model($user_links,['method' => 'PATCH', 'action'=> ['UserController#update_social']]) !!}
<div class='row form-group'>
<div class='col-md-2'>
{!! Form::label('facebook', 'Facebook Username') !!}
</div>
<div class='col-md-7'>
{!! Form::text('facebook', '',['class'=>'form-control']) !!}
</div>
</div>
<div class='row form-group'>
<div class='col-md-2'>
{!! Form::label('twitter', 'Twitter Username') !!}
</div>
<div class='col-md-7'>
{!! Form::text('twitter', null,['class'=>'form-control']) !!}
</div>
</div>
<div class='row form-group'>
<div class='col-md-2'>
{!! Form::label('reddit', 'Reddit Username') !!}
</div>
<div class='col-md-7'>
{!! Form::text('reddit', null,['class'=>'form-control']) !!}
</div>
</div>
<div class='row form-group'>
<div class='col-md-3'>
{!! Form::submit('Save Changes',['class'=>'btn btn-md btn-success']) !!}
</div>
</div>
{!! Form::close() !!}
controllers
public function show_social(Request $request){
$user_links= $request->user()->links;
return view('user.edit.social_connect',compact('user_links'));
}
public function update_social(SocialRequest $request){
$facebook= Input::get('facebook');
$twitter= Input::get('twitter');
$reddit= Input::get('reddit');
$user = $request->user();
$this->validate($request,['url'=>'unique']);
if(Input::has('facebook')||Input::has('google')||Input::has('reddit')||Input::has('twitter'))
{
if($facebook != ""){
$link = new SocialLinks();
$link->type = 'facebook';
$link->url='https//www.facebook.com/'.$facebook;
$link->user_id=$user->id;
$link->save();
}
if($twitter != ""){
$link = new SocialLinks();
$link->type = 'twitter';
$link->url='https//www.twitter.com/'.$twitter;
$link->user_id=$user->id;
$link->save();
}
if($reddit != ""){
$link = new SocialLinks();
$link->type = 'reddit';
$link->url='https//www.reddit.com/user'.$reddit;
$link->user_id=$user->id;
$link->save();
}
return Redirect::back()->with('message','Your profile has been updated');
}
return Redirect::back();
}
my model file
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Eloquent;
class SocialLinks extends Eloquent{
protected $table= 'social_links';
protected $fillable=[
'type',
'url'
];
public function user()
{
return $this->belongsTo('App\User');
}
}
?>
my request
<?php
namespace App\Http\Requests;
use App\Http\Requests\Request;
class SocialRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'url'=>'unique|user_id'
];
}
}
Okay, there are a few things wrong here. Your request file is being used incorrectly. You need a model for that, unless ofcourse you're just getting "request file" and "model" mixed up. For the purpose of this comment, I'm going to use Laravel's validation method from within the controller.
Something worth noting, your "url" is not present within the form. The validation looks for a "url" parameter inside of the request, but as you do not appear to be sending that within the form, it is quite redundant. Also, when you use the "unique" validator, you need to supply a database table for it to search and check against the supplied value, in this case; url.
I've added that in, but, really it's not doing anything because the url will always be empty until you supply it in your form, so the request will always pass.
public function show_social(Request $request)
{
$user_links = $request->user()->links;
return view('user.edit.social_connect', compact('user_links'));
}
public function update_social(Request $request)
{
$facebook = $request->facebook;
$twitter = $request->twitter;
$reddit = $request->reddit;
$user = $request->user();
$this->validate($request, [
'url' => 'unique:social_links,column',
]);
if($request->has('facebook') || $request->has('google') || $request->has('reddit') || $request->has('twitter'))
{
if($facebook != ""){
$link = new SocialLinks();
$link->type = 'facebook';
$link->url = 'https//www.facebook.com/'.$facebook;
$link->user_id = $user->id;
$link->save();
}
if($twitter != ""){
$link = new SocialLinks();
$link->type = 'twitter';
$link->url = 'https//www.twitter.com/'.$twitter;
$link->user_id = $user->id;
$link->save();
}
if($reddit != ""){
$link = new SocialLinks();
$link->type = 'reddit';
$link->url = 'https//www.reddit.com/user'.$reddit;
$link->user_id = $user->id;
$link->save();
}
return Redirect::back()->with('message','Your profile has been updated');
}
return Redirect::back();
}
As you can see, I removed the type hinting for your request because what you were actually doing (from what I can tell), was type hinting the model. Your "request file" which you supplied is a model and should be in the App/ directory, and referenced using a namespace.
If you are indeed using that file as a model, then your relationship looks okay, assuming of course you've got the right foreign column setup in your database, referencing the user table.
As for your model binding not working, have you tried dumping the $user_links variable, like so: dd($user_links); - to see if it actually contains anything? As you're using a request there, I cannot tell where you're getting the information.
Hopefully this helps, if you have any more questions, feel free to ask.
I'm creating a project using Laravel. Users are able to like comments. I want to display a "like" button so a user can like a comment and if the user has already liked the comment I want that button to be "unlike" so a user can unlike the liked comment
In my database I have a likes table:
| id | user_id | comment_id |
My Like Model looks like this:
class Like extends \Eloquent {
protected $fillable = ['user_id', 'comment_id'];
protected $table = 'likes';
public function owner()
{
return $this->belongsTo('Acme\Users\User', 'user_id');
}
}
Comment Model looks like this:
class Comment extends \Eloquent {
protected $fillable = ['user_id', 'post_id', 'body'];
protected $table = 'comments';
public function owner()
{
return $this->belongsTo('Acme\Users\User', 'user_id');
}
public function likes()
{
return $this->hasMany('Acme\Likes\Like');
}
}
User model:
class User extends Eloquent {
public function comments()
{
return $this->hasMany('Acme\Comments\Comment');
}
public function likes()
{
return $this->hasMany('Acme\Likes\Like');
}
}
Likes controller :
class LikesController extends \BaseController {
use CommanderTrait;
/**
* Like a comment
* #return Response
*/
public function commentLike()
{
// using a command bus. Basically making a post to the likes table assigning user_id and comment_id then redirect back
extract(Input::only('user_id', 'comment_id'));
$this->execute(new CommentLikeCommand($user_id, $comment_id));
return Redirect::back();
}
public function unlike()
{
$like = new Like;
$user = Auth::user();
$id = Input::only('comment_id');
$like->where('user_id', $user->id)->where('comment_id', $id)->first()->delete();
return Redirect::back();
}
}
In my view I'm able to get the comments via $comment, and I'm able to get likes via $comment->like have:
#foreach($post->comments as $comment)
<div class="user-comment">
<p class="comment">
{{ $comment->owner->first_name }} {{ $comment->owner->last_name }} {{ $comment->body }}
</p>
<div class="com-details">
<!-- how long ago the comment was posted -->
<div class="com-time-container">
{{ $comment->created_at->diffForHumans() }} ·
</div>
<!-- HERE IS WHERE I WANT THE LIKE AND UNLIKE BUTTONS TO DISPLAY -->
#if ($comment->likes->owner->id === $currentUser->id)
{{ Form::open(['route' => 'like']) }}
{{ Form::hidden('user_id', $currentUser->id) }}
{{ Form::hidden('comment_id', $comment->id) }}
<button type="submit" class="com-like">Like</button>
{{ Form::close() }}
#else
{{ Form::open(['route' => 'unlike']) }}
{{ Form::hidden('user_id', $currentUser->id) }}
{{ Form::hidden('comment_id', $comment->id) }}
<button type="submit" class="com-like">Unlike</button>
{{ Form::close() }}
#endif
<!-- how many users like this comment -->
<span class="likes"> · {{ $comment->likes->count() }}</span>
</div>
</div><!--user-comment end-->
#endforeach
Im trying to set up an if statement to see if the current user has liked the status but im not sure how this is done? If the user has not liked the comment yet I want the "like" button to display. If the user has liked the comment I want the "unlike" button to display. I thought I could say #if($comment->likes->owner->id === $currentUser->id) but I get Undefined property. How would I go about doing this?
$comment->likes is a Collection of Like objects. To access the owner property, you would need to iterate the collection.
However, another option is to use the available methods on the Collection to do what you need:
#if (in_array($currentUser->id, $comment->likes->lists('user_id')))
$comment->likes->lists('user_id') will return an array of all the user_id values in the Collection of Likes for the Comment. in_array() will check if the $currentUser->id is in that array.
I haven't worked much with Laravel, so my syntax and terminology might be a bit off, but it should be the right idea.
Basically, $comment->likes is a list of likes on that comment. You need to iterate through those likes and check if one of them is by the current user. If one of them is by the current user, then show the unlike button. Otherwise, show the like button.
Not sure what that'd look like in Blade, but here's some pseudo-code:
$currentUserLiked = false;
// go through all of the comment's likes
foreach ($comment->likes as $like)
{
// check if this like is by the current user
if ($like->owner->id == $currentUser->id)
{
$currentUserLiked = true;
break;
}
}
if ($currentUserLiked)
{
showUnlikeButton();
}
else
{
showLikeButton();
}
I'm building my first basic laravel web app, after following a few tutorials this is the first one I'm tinkering with on my own. I'm running into to some trouble with routing to a controller and then getting the correct url.
Ideally at this point I should only have two routes / and /{user}. On the homepage you can search via a form for the user and the form should take you to /{user}.
Routes (I have three cause I'm still trying to get this to work, and I think I need a POST):
Route::get('/', 'HomeController#index');
Route::get('/{user}', 'HomeController#student');
Route::post('/', 'HomeController#studentLookUp');
Home Controller:
public function index()
{
return View::make('helpdesk');
}
public function student($user) {
return View::make('selfservice')
->with('user', $user);
}
public function studentLookUp() {
$user = Input::get('ID');
return View::make('selfservice')
->with('user', $user);
}
Form:
{{ Form::open(array('class'=>'navbar-form navbar-left', 'role'=>'search'), array('action' => 'HomeController#student')) }}
<div class="form-group">
{{ Form::text('ID', '', array('placeholder'=>'ID', 'class'=>'form-control') ); }}
</div>
{{ Form::button('Search', array('class'=>'btn btn-default')) }}
{{ Form::close() }}
At this point I can search from the homepage ('/') and it will take me back to the homepage but with the searched for user which is how I want it to work except it doesn't have the right url of homepage.com/username.
Any help would be much appreciated!
First register a route to listen your search request:
1. Search Route:
Register search route.
//route search
Route::get('/search',['uses' => 'SearchController#getSearch','as' => 'search']);
2. Search View:-
Now create a search form in a view:-
<form action="/search" method="get">
<input type="text" name="q" placeholder="Search.."/>
<button type="submit">Search</button>
</form>
3. SearchController :
Now create SearchController to handle your searching logic.
SearchController :
<?php
class SearchController extends \BaseController {
public function getSearch()
{
//get keywords input for search
$keyword= Input::get('q');
//search that student in Database
$students= Student::find($keyword);
//return display search result to user by using a view
return View::make('selfservice')->with('student', $students);
}
}
Now you have to create one view selfservice to display your search result.
4. Selfservice View:
#foreach ($students as $key=> $student)
<div>
{{$student->name}}
</div>
#endforeach
Here for each student result, one link will be created. That link will be link:-
website.domain/{student}
5. Update Routes for Student
Route::get('/{student}',['uses' => 'HomeController#student','as' => 'student.show']);
UPDATE updated the answer to get student page directly
To redirect from search to website.domain\{user} follow these steps:-
1. Modify SearchController
<?php
class SearchController extends \BaseController {
public function getSearch()
{
//get keywords input for search
$keyword= Input::get('q');
//search that student in Database
$student= Student::find($keyword);
//redirect directly to student.show route with student detail
return Redirect::route('student.show', array('student' => $student));
}
}
2. Now add a function for Route student.show in HomeController
Route::get('/{student}',['uses' => 'HomeController#student','as' => 'student.show']);
In HomeController
public function student($student)
{
//here display student detail
}
I'm sort of a newb to Laravel 4 and Sentry 2, but i've managed to survive so far. I'm running into a problem right now, cause when im logged in as userid(1) and i want to view the profile of userid(2) i'm just seeing the information of userid(1) on the profile of userid(2).
I'm aware that using filters might come in handy at this, but if i have to be honest. I have no idea what i should look at etc.
I know this site is not meant for giving answers. But if someone could give me a bit of an answer, where to look, what i should keep in mind etc. that would be very much appreciated.
---EDIT---
Route:
Route::group(array('before'=>'auth'), function(){
Route::get('logout', 'HomeController#logout');
Route::get('profile/{username}', 'ProfileController#getIndex');
});
Route::filter('auth', function($route)
{
$id = $route->getParameter('id');
if(Sentry::check() && Sentry::getUser()->id === $id) {
return Redirect::to('/');
}
});
ProfileController
public function getIndex($profile_uname)
{
if(Sentry::getUser()->username === $profile_uname) {
// This is your profile
return View::make('user.profile.index');
} else {
// This isn't your profile but you may see it!
return ??
}
}
View
#extends('layouts.userprofile')
#section('title')
{{$user->username}}'s Profile
#stop
#section('notification')
#stop
#section('menu')
#include('layouts.menus.homemenu')
#stop
#section('sidebar')
#include('layouts.menus.profilemenu')
#stop
#section('content')
<div class="col-sm-10 col-md-10 col-xs-10 col-lg-10">
<div class="panel panel-info">
<div class="panel-heading"><h3>{{ $user->username }}</h3></div>
</div>
</div>
#stop
#section('footer')
#stop
This might work for you:
<?php
public function getIndex($profile_uname)
{
if(Sentry::getUser()->username === $profile_uname) {
// This is your profile
return View::make('user.profile.index');
} else {
// This isn't your profile but you may see it!
return View::make('user.profile.index')->with('user', Sentry::findUserByLogin($profile_uname));
}
}
If username is not your login column, then you can do it in two steps:
$userId = \Cartalyst\Sentry\Users\Eloquent\User::where('username', $profile_uname)->first()->id;
return View::make('user.profile.index')->with('user', Sentry::findUserById($userId));
If you have a User model tied to your users table, you can just do:
$userId = User::where('username', $profile_uname)->first()->id;
return View::make('user.profile.index')->with('user', Sentry::findUserById($userId));
And in this last case you probably will be able to use that same model, since they would be the same in Sentry and pure Eloquent:
$user = User::where('username', $profile_uname)->first();
return View::make('user.profile.index')->with('user', $user);
Also, to avoid a conflict between your views related to the current logged user, you should rename the $user variable you are instantiating via View::share() or View::composer() from $user to $loggedUser or something like that.