ErrorException Argument 1 passed to (Laravel 5.2) - php

So i'm trying to "like" a status and when I do, I get this error in return
ErrorException in User.php line 107:
Argument 1 passed to SCM\User::hasLikedStatus() must be an instance of Status, instance of SCM\Status given, called in C:\xampp\htdocs\app\Http\Controllers\StatusController.php on line 66 and defined
When I remove "use Status;" from my User.php the function works and it updated my database with the like ID. Could this be because I linked my status's public function like "SCM\Status"?
Routes.php
<?php
/*
|--------------------------------------------------------------------------
| Routes File
|--------------------------------------------------------------------------
|
| Here is where you will register all of the routes in an application.
| It's a breeze. Simply tell Laravel the URIs it should respond to
| and give it the controller to call when that URI is requested.
|
*/
/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| This route group applies the "web" middleware group to every route
| it contains. The "web" middleware group is defined in your HTTP
| kernel and includes session state, CSRF protection, and more.
|
*/
Route::group(['middleware' => ['web']], function () {
Route::get('/login', function () {
return view('auth/login');
});
Route::get('/register', function () {
return view('auth/login');
});
/**
*User Profile
*/
Route::get('/user/{username}', [
'as' => 'profile.index', 'uses' => 'ProfileController#getProfile'
]);
Route::get('/profile/edit', [
'uses' => 'ProfileController#getEdit', 'as' => 'profile.edit', 'middleware' => ['auth'],
]);
Route::post('/profile/edit', [
'uses' => 'ProfileController#postEdit', 'middleware' => ['auth'],
]);
Route::get('/settings', [
'uses' => 'ProfileController#getEdit', 'as' => 'layouts.-settings', 'middleware' => ['auth'],
]);
Route::post('/settings', [
'uses' => 'ProfileController#postEdit', 'middleware' => ['auth'],
]);
/**
* Friends
*/
Route::get('/friends', [
'uses' => 'FriendController#getIndex', 'as' => 'friend.index', 'middleware' => ['auth'],
]);
Route::get('/friends/add/{username}', [
'uses' => 'FriendController#getAdd', 'as' => 'friend.add', 'middleware' => ['auth'],
]);
Route::get('/friends/accept/{username}', [
'uses' => 'FriendController#getAccept', 'as' => 'friend.accept', 'middleware' => ['auth'],
]);
/**
* Statuses
*/
Route::post('/status', [
'uses' => 'StatusController#postStatus', 'as' => 'status.post', 'middleware' => ['auth'],
]);
Route::post('/status/{statusId}/reply', [
'uses' => 'StatusController#postReply', 'as' => 'status.reply', 'middleware' => ['auth'],
]);
Route::get('/status/{statusId}/like', [
'uses' => 'StatusController#getLike', 'as' => 'status.like', 'middleware' => ['auth'],
]);
});
Route::group(['middleware' => 'web'], function () {
Route::auth();
Route::get('/', [
'as' => 'welcome', 'uses' => 'WelcomeController#index'
]);
Route::get('/profile', function () {
return view('layouts/-profile');
});
Route::get('profile/{username}', function () {
return view('layouts/-profile');
});
Route::get('/home', 'HomeController#index');
});
/**
* Search
*/
Route::get('/search', [
'as' => 'search.results', 'uses' => 'SearchController#getResults'
]);
User.php (model)
<?php
namespace SCM;
use Status;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'username', 'email', 'password',
];
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
protected $primaryKey = 'id';
public function getAvatarUrl()
{
return "http://www.gravatar.com/avatar/{{ md5 ($this->email)}}?d=mm&s=40 ";
}
public function statuses()
{
return $this->hasMany('SCM\Status', 'user_id');
}
public function likes()
{
return $this->hasMany('SCM\Like', 'user_id');
}
public function friendsOfMine()
{
return $this->belongsToMany('SCM\User', 'friends', 'user_id', 'friend_id');
}
public function friendOf()
{
return $this->belongsToMany('SCM\User', 'friends', 'friend_id', 'user_id');
}
public function friends()
{
return $this->friendsOfMine()->wherePivot('accepted', true)->get()->
merge($this->friendOf()->wherePivot('accepted', true)->get());
}
public function friendRequests()
{
return $this->friendsOfMine()->wherePivot('accepted', false)->get();
}
public function friendRequestsPending()
{
return $this->friendOf()->wherePivot('accepted', false)->get();
}
public function hasFriendRequestPending(User $user)
{
return (bool) $this->friendRequestsPending()->where('id', $user->id)->count();
}
public function hasFriendRequestReceived(User $user)
{
return (bool) $this->friendRequests()->where('id', $user->id)->count();
}
public function addFriend(User $user)
{
$this->friendOf()->attach($user->id);
}
public function acceptFriendRequest(User $user)
{
$this->friendRequests()->where('id', $user->id)->first()->pivot->update([
'accepted' => true,
]);
}
public function isFriendsWith(User $user)
{
return (bool) $this->friends()->where('id', $user->id)->count();
}
public function hasLikedStatus(Status $status)
{
return (bool) $status->likes
->where('likeable_id', $status->id)
->where('likeable_type', get_class($status))
->where('user_id', $this->id)
->count();
}
}
Status.php (model)
<?php
namespace SCM;
use Illuminate\Database\Eloquent\Model;
class Status extends Model
{
protected $table = 'statuses';
protected $fillable = [
'body'
];
public function user()
{
return $this->belongsTo('SCM\User', 'user_id');
}
public function scopeNotReply($query)
{
return $query->whereNull('parent_id');
}
public function replies()
{
return $this->hasMany('SCM\Status', 'parent_id');
}
public function likes()
{
return $this->morphMany('SCM\Like', 'likeable');
}
}
Likes.php (model)
<?php
namespace SCM;
use Illuminate\Database\Eloquent\Model;
class Like extends Model
{
protected $table = 'likeable';
public function likeable()
{
return $this->morphTo();
}
public function user ()
{
return $this->belongsTo('SCM\User', 'user_id');
}
}
StatusController.php
<?php
namespace SCM\Http\Controllers;
use Flash;
use Auth;
use Illuminate\Http\Request;
use SCM\User;
use SCM\Status;
class StatusController extends Controller
{
public function postStatus(Request $request)
{
$this->validate($request, [
'status' => 'required|max:1000',
]);
Auth::user()->statuses()->create([
'body' => $request->input('status'),
]);
return redirect()->route('welcome')->with('info', 'Status posted.');
}
public function postReply(Request $request, $statusId)
{
$this->validate($request, [
"reply-{$statusId}" => 'required|max:1000',
], [
'required' => 'The reply body is required.'
]);
$status = Status::notReply()->find($statusId);
if (!$status) {
return redirect()->route('welcome');
}
if (!Auth::user()->isFriendsWith($status->user) && Auth::user()->id !==
$status->user->id) {
return redirect()->route('welcome');
}
$reply = Status::create([
'body' => $request->input("reply-{$statusId}"),
])->user()->associate(Auth::user());
$status->replies()->save($reply);
return redirect()->back();
}
public function getLike($statusId)
{
$status = Status::find($statusId);
if (!$status) {
return redirect()->route('welcome');
}
if (!Auth::user()->isFriendsWith($status->user)) {
return redirect()->route('welcome');
}
if (Auth::user()->hasLikedStatus($status)) {
return redirect()->back();
}
$like = $status->likes()->create([]);
Auth::user()->likes()->save($like);
return redirect()->back();
}
}

Remove the use statement for Status in your Users.php. When you're doing that, you're actually trying to use \Status. Your file is already in the namespace SCM, so you don't need any use statement to use classes in the same namespace.
So in your method definition you're saying you want an instance of \Status as your parameter, but are passing in a SCM\Status.

Related

Laravel: LogicException in Model.php line 2673: Relationship method must return an object of type Illuminate\Database\Eloquent\Relations\Relation

I have one DB which has 3 tables: user, statuses and friends.
My status table has a relationship column "parent id" which is NULL but stores the user_id of a user that replies to a status. Below is my Status.php code:
namespace Pictogram\Models;
use Illuminate\Database\Eloquent\Model;
class Status extends Model
{
protected $table = 'statuses';
protected $fillable = [
'body'
];
public function user()
{
return $this->belongsTo('Pictogram\Models\User', 'user_id');
}
public function scopeNotReply($query)
{
return $query->whereNull('parent_id');
}
public function replies()
{
return $this->hasMany('Pictogram\Models\Status', 'parent_id');
}
}
And blow is from my route file: This controls replies to status
Route::post('/status', [
'uses' => '\Pictogram\Http\Controllers\StatusController#postStatus',
'as' => 'status.post',
'middleware' => ['auth'],
]);
Route::post('/status/{statusId}/reply', [
'uses' => '\Pictogram\Http\Controllers\StatusController#postReply',
'as' => 'status.reply',
'middleware' => ['auth'],
]);
And my status controller .php
class StatusController extends Controller
{
public function postStatus(Request $request)
{
$this->validate($request, [
'status' => 'required',
]);
Auth::user()->statuses()->create([
'body' => $request->input('status'),
]);
return redirect()
->route('home')
->with('info', 'Status updated.');
}
public function postReply(Request $request, $statusId)
{
$this->validate($request, [
"reply-{$statusId}" => 'required',
], [
'required' => 'The reply body is required.'
]);
$status = Status::notReply()->find($statusId);
if (!$status) {
return redirect()->route('home');
}
if (!Auth::user()->isFriendsWith($status->user) && Auth::user()->id !== $status->user->id)
{
return redirect()->route('home');
}
$reply = Status::create([
'body' => $request->input("reply-{$statusId}"),
])->user()->associate(Auth::user());
$status->replies()->save($reply);
return redirect()->back();
}
}
And lastly this is the line 2673 of models .php below:
protected function getRelationshipFromMethod($method)
{
$relations = $this->$method();
if (! $relations instanceof Relation) {
throw new LogicException('Relationship method must return an object of type '
.'Illuminate\Database\Eloquent\Relations\Relation');
}
return $this->relations[$method] = $relations->getResults();
}
I am using Laravel 5.2. Now my issue is that the reply gets save to the table because the empty parent_id then takes the user_id of the user who replied but then it brings up an error page that has these errors below.
Error1/2
Error2/2
Make sure your relationship name is proper in Status model.
check your replies() realtion in Status model.
it return the Status Relationship i should be the realtion of replies i.e Reply
public function replies()
{
return $this->hasMany('Pictogram\Models\Reply', 'parent_id');
}

laravel 5.5 return redirect route not working

I'm having a strange issue with my laravel app .
I have a route defined as :
web.php
Route::get('/', ['as' => '/', 'uses' => 'LoginsController#getLogin']);
Route::post('/login', ['as' => 'login', 'uses' => 'LoginsController#postLogin']);
Route::group(['middleware' => ['authenticate', 'roles']], function (){
Route::get('/logout', ['as' => 'logout', 'uses' => 'LoginsController#getLogout']);
Route::get('/dashboard','DashboardController#dashboard')->name('dashboard');
});
In a controller , i'm trying to redirect to this route
LoginController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class LoginsController extends Controller
{
use AuthenticatesUsers;
protected $username = 'username';
protected $redirectTo = '/';
protected $guard = 'web';
public function getLogin()
{
if (Auth::guard('web'))
{
return redirect()->route('dashboard');
}
return view('login');
}
public function postLogin(Request $request)
{
$auth = Auth::guard('web')->attempt([
'username' => $request->username,
'password' => $request->password,
'active' => 1]);
if ($auth)
{
return redirect()->route('dashboard');
}
return redirect()->route('/');
}
public function getLogout()
{
Auth::guard('web')->logout();
return redirect()->route('/');
}
}
Where I am typing http://localhost:8000 in address bar of browser. I see.

Simple approach of route protection based on roles Laravel 5.2

I want to protect my routes based on roles.
This is what I have done but I can't seem to get it to work.
Role model:
protected $table = 'roles';
protected $fillable = array(
'name', 'description'
);
public function users(){
return $this->belongsToMany('App\User', 'user_role', 'role_id', 'user_id');
}
Role migration
Schema::create('roles', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->string('name', 40);
$table->string('description', 255);
});
RoletableSeeder file
Role::create([
'id' => 1,
'name' => 'Admin',
'description' => 'Admin User.'
]);
Role::create([
'id' => 2,
'name' => 'Vendor',
'description' => 'Vendor User.'
]);
Role::create([
'id' => 3,
'name' => 'User',
'description' => 'Simple User.'
]);
A sample route:
Route::get('/admin/dashboard', [
'uses' => 'AdminController#adminDashboard',
'as' => 'admin.dashboard',
'middleware' => ['auth', 'roles'],
'roles' => ['Admin']
]);
User model:
protected $fillable = [
'email','username', 'password', 'confirmation_code'
];
protected $hidden = [
'password', 'remember_token',
];
public function orders() {
return $this->hasMany('App\Order');
}
public function roles(){
return $this->belongsToMany('App\Role', 'user_role', 'user_id', 'role_id');
}
public function hasRole($roles){
$this->have_role = $this->getUserRole();
if($this->have_role->name == 'Admin') {
return true;
}
if(is_array($roles)){
foreach($roles as $need_role){
if($this->checkIfUserHasRole($need_role)) {
return true;
}
}
} else{
return $this->checkIfUserHasRole($roles);
}
return false;
}
private function getUserRole(){
return $this->roles()->getResults();
}
private function checkIfUserHasRole($need_role){
return (strtolower($need_role)==strtolower($this->have_role->name)) ? true : false;
}
CheckRole.php file which is inside middleware:
<?php namespace App\Http\Middleware;
use Closure;
class CheckRole{
public function handle($request, Closure $next)
{
$roles = $this->getRequiredRoleForRoute($request->route());
if($request->user()->hasRole($roles) || !$roles){
return $next($request);
}
return response([
'error' => [
'code' => 'INSUFFICIENT_ROLE',
'description' => 'You are not authorized to access this resource.'
]
], 401);
}
private function getRequiredRoleForRoute($route)
{
$actions = $route->getAction();
return isset($actions['roles']) ? $actions['roles'] : null;
}
}
and last I added one line to the kernel:
protected $routeMiddleware = [
...
'roles' => 'App\Http\Middleware\CheckRole',
];
Does anyone have any idea? Or a better/simpler way to do this? Thanks in advance!
This was my solution and i'm not saying it's the best practice nor it's better than yours.
i have created this middleware:
<?php
namespace App\Http\Middleware;
use Closure;
class MustHaveRole
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next, $role)
{
if(auth()->check() && auth()->user()->active && (auth()->user()->hasRole($role) || auth()->user()->hasRole('admin')) ){
return $next($request);
} else {
abort(403);
}
}
}
inside app/Http/Kernel.php added the last line:
protected $routeMiddleware = [
'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'role' => \App\Http\Middleware\MustHaveRole::class,
];
and inside user model created 2 methods:
// define connection with roles table
public function roles()
{
return $this->belongsToMany(Role::class);
}
// check if user has that $role
public function hasRole($role)
{
return $this->roles->contains('name', $role);
}
and i have a model called Role:
<?php
namespace App;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Model;
class Role extends Model
{
use SoftDeletes;
public function users()
{
return $this->belongsToMany(User::class)->withTimestamps();
}
}
and a seeder for that table:
<?php
use Illuminate\Database\Seeder;
class RolesTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
// check if table roles is empty
if(DB::table('roles')->get()->count() == 0){
// multiple insertion
DB::table('roles')->insert([
['name' => 'admin'],
['name' => 'agency'],
['name' => 'endcustomer'],
]);
} else { echo "\e[31mTable is not empty, therefore NOT "; }
}
}
and now inside my Controller constructor i can call that middleware:
class ItemsController extends Controller
{
public function __construct() {
$this->middleware('auth');
$this->middleware('role:endcustomer');
}
...
This is all done without any additional packages...just plain laravel...if you have any more questions feel free to ask.
Well this is what I did and actually worked.
RoleTableSeeder, Role migration, Role model and the middleware register remain the same as the original post.
In CheckRole.php:
<?php
namespace App\Http\Middleware;
use Closure;
class CheckRole{
public function handle($request, Closure $next){
if ($request->user()=== null) //for guests
return redirect()->route('product.index');
$actions = $request->route()->getAction();
$roles = isset($actions['roles']) ? $actions['roles'] : null;
if ($request->user()->hasAnyRole($roles) || !$roles)
return $next($request);
return redirect()->route('product.index'); //for unauthorized users
}
}
In User model: (the relations is exactly as the original post)
public function hasAnyRole($roles){
if (is_array($roles)){
foreach ($roles as $role) {
if ($this->hasRole($role)) {
return true;
}
}
} else if ($this->hasRole($roles)) {
return true;
}
return false;
}
public function hasRole($role){
if ($this->roles()->where('name', $role)->first()){
return true;
}
return false;
}
And an example of a route:
Route::get('...', [
...
'middleware' => 'roles',
'roles' => 'Admin' //or whatever you have in `RolesTableSeeder` in name column
]);

laravel 5.2 - Auth::user()->username is empty

If I use Auth::user()->username in a Blade file laravel returns me an empty String but Auth::user()->email is filled. I use my own AuthController and my Login,Register and Logout work perfectly but I can't get the username.
Routes.php
<?php
Route::group(['middleware' => ['web']] , function () {
Route::get('/', function () {
return view('welcome');
})->name('home');
});
Route::group(['middleware' => ['web','guest']], function () {
Route::auth();
#Sign up Routes
Route::get('/signup', function () {
return view('auth.signup');
})->name('auth.signup');
Route::post('/signup', 'AuthController#signup');
#Sign in Routes
Route::get('/signin', function () {
return view('auth.signin');
})->name('auth.signin');
Route::post('/signin', 'AuthController#signin');
});
Route::group(['middleware' => ['web','auth']], function () {
Route::auth();
#Sign out Routes
Route::get('/signout', 'AuthController#signout')->name('auth.signout');
});
And my custom Auth Controller is:
<?php
namespace App\Http\Controllers;
use Auth;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\User;
class AuthController extends Controller
{
public function signup(Request $request) {
$this->validate($request, [
'email' => 'required|unique:users|email|max:255',
'username' => 'required|unique:users|alpha_dash|min:2|max:20',
'password' => 'required|min:6'
]);
User::create([
'email' => $request->input('email'),
'username' => $request->input('username'),
'password' => bcrypt($request->input('password')),
]);
return redirect()->route('home');
}
public function signin(Request $request) {
$this->validate($request, [
'email' => 'required',
'password' => 'required'
]);
if(!Auth::attempt($request->only(['email', 'password']), $request->has('remember'))) {
return redirect()->back()->with('flash-message','We can not sign you in with this data!');
}
return redirect()->route('home');
}
public function signout() {
Auth::logout();
return redirect()->route('home');
}
}
Maybe someone can help me
.
Note:
I added the username into User.php under the filled array.
Most likely you are missing username in $fillable of your User model.
The create method only accept fields coming from $fillable.
Please edit your User model like this:
protected $fillable = [
'email', 'username', 'password',
];
Only $fillable fields insert by Create method.

Protected routes error in laravel 5.2

I have this protected route to be accessed only when the user is authenticated:
Route::get('/checkout', [
'middleware' => 'auth',
'uses' => 'Front#checkout'
]);
and the other routes are:
// Authentication routes...
Route::get('auth/login', 'Front#login');
Route::post('auth/login', 'Front#authenticate');
Route::get('auth/logout', 'Front#logout');
// Registration routes...
Route::post('/register', 'Front#register');
And my controller is:
<?php
namespace App\Http\Controllers;
use Request;
use Redirect;
use App\User;
use Illuminate\Support\Facades\Auth;
use App\Http\Controllers\Controller;
class Front extends Controller {
public function register() {
if (Request::isMethod('post')) {
User::create([
'name' => Request::get('name'),
'email' => Request::get('email'),
'password' => bcrypt(Request::get('password')),
]);
}
return Redirect::away('auth/login');
}
public function authenticate() {
if (Auth::attempt(['email' => Request::get('email'), 'password' => Request::get('password')])) {
return redirect()->intended('/checkout');
} else {
return view('auth/loginerror', array('title' => 'Welcome', 'description' => '', 'page' => 'home'));
}
}
public function login() {
return view('auth/login', array('page' => 'home'));
}
public function checkout() {
return view('contactme', array('page' => 'home'));
}
public function logout() {
Auth::logout();
return Redirect::away('auth/login');
}
}
how is this error in the route?
NotFoundHttpException in RouteCollection.php line 161:

Categories