I work on a website for my last school project, it's a website where (as a normal user) you can match with a coach and once you two have matched together, you can share a page where the coach can update your daily workout routine.
I'm stucked at the matching method, my entity User has a propriety idCoach which is an array that can contains other Users. The idea is when you are on the coach's profile page, and you press on the match button, it adds the coach on your idCoach propriety.
This is my propriery from my User entity:
/**
* #ORM\OneToMany(targetEntity="App\Entity\User", mappedBy="idSportif")
*/
private $idCoach;
this is what i tried on the controller :
/**
* #Route("/user/match/{id}", name="match")
*/
public function matchCoach(ObjectManager $om, User $user) {
$currentUser = $this->getUser();
$currentUser->addIdCoach($user);
$om->persist($currentUser);
$om->flush();
return $this->render('profile/index.html.twig', [
'user' => $currentUser,
]);
}
but it gives me an error message :
Call to a member function addIdCoach() on null.
so getUser() returns null, that's why you get the error.
Does your Controller extend AbstractController and getUser() should therefore return the currently logged in user? In this case, it seems like you are not logged in. I would check the security configuration to make sure only logged in users can access this url.
Further comments:
Your naming is a little confusing, what is an "idCoach"? If this property holds the associated coaches, I would name it "coaches".
Your method changes data, so it should only be called via POST, not GET.
Related
I have used dektrium/yii2-user in my application.
And there is a method named getID() in User.php of vendor/dektrium and this method can be accessed by Yii::$app->user->getID() and returns id of the logged in user.
However, there is another method named getProfile() whose function is to return complete profile details of currently logged in user. But, this method is giving 500-internal server error.
exception 'yii\base\UnknownMethodException' with message 'Calling unknown method: yii\web\User::getProfile()' in ... ...
I Googled the issue but found nothing... Help me folks..
I believe that you can get the profile of the currently logged in user like this:
Yii::$app->user->identity->profile;
because Yii::$app->user->identity returns the current user - the User object.
You are confusing Yii's web user object with the user model :)
EDIT:
Yii::$app->user is referring to yii\web\User - the application component that manages the user authentication status.
You ask that User component to get the 'identity' which is :
IdentityInterface is the interface that should be implemented by a class providing identity information
In this case, Dektrium User model implements the IdentityInterface and you are able to call getId on it and get the id for the User model.
class User extends ActiveRecord implements IdentityInterface
This code:
Yii::$app->user->identity->profile;
Will return the Profile model data associated with the User
And you can access it's fields directly:
Yii::$app->user->identity->profile->location;
See dektrium\user\models\Profile for details.
People always gets confused about yii\web\User, the IdentityInterface and the User model..
Myself included :p
If you have an instance of an user ($user), you can use the getProfile() function:
$profile = $user->getProfile()->one();
And it returns profile record from that user.
If you don't have an instance of user, but the id ($user_id), you could get an instance of Profile model directly:
$profile = Profile::find()->where(['user_id' => $user_id)->one();
And Yii::$app->user is an interface to the user model defined in your app (dektrium user model in this case): http://www.yiiframework.com/doc-2.0/yii-web-user.html
to sum up:
$user_id = Yii::$app->user->getID();
$profile = Profile::find()->where(['user_id' => $user_id)->one();
Try this one
\app\models\User::findOne(Yii::$app->user->identity->id)->profile;
What would be the best way to create a relationship if it doesn’t exist already, within Eloquent, or at least a central location.
This is my dilemma. A User must have a Customer model relationship. If for whatever reason that customer record doesn’t exist (some bug that stopped it from being created) - I don’t want it to throw errors when I try to retrieve it, but I also request the customer object in multiple locations so I don’t want to test for existence in all those places.
I thought of trying the following in the User model:
public function getCustomerAttribute($value) {
// check $value and create if null
}
But that doesn’t work on relationships, $value is null.
EDIT
I already create a customer upon user creation, but I have come across a situation where it wasn't created and caused exceptions in many places, so I want to fallback.
User::created(function($user) {
$customer = Customer::create([
'user_id' => $user->id
]);
});
Is it possible for you to assume when a user is created that a customer needs to be created as well? If the rest of your system depends on this assumption I would make a model event.
use App\{User, Customer}; // assuming php7.0
UserServiceProvider extends ServiceProvider
{
/**
* Boot
*/
public function boot()
{
// on a side note, we're using "created" not "creating" because the $user->id needs to exist in order to save the relationship.
User::created(function($user) {
$customer = Customer::create([
'user_id' => $user->id
]);
});
}
}
I want to get the role id of the logged user to make visible specific links of website. currently I have student and tutor tables and separate login for both users. student table has role as 1 and tutor table as role as 2, how can I check the logged user's role .
I tried
<?php echo Yii::app()->user->role;?>
but it returns following error
Property "CWebUser.role" is not defined.
pls advice
There are two solutions:
Using setState() in extended CUserIdentity class. It calls once during user auth and woudn't be updated on next page refresh. Don't store there important information like roles or passwords, cause it could be stored in cookie. It easy to store there information like name, last visit time, etc.
Here is an example: http://www.yiiframework.com/wiki/6/how-to-add-more-information-to-yii-app-user
Extends CWebUser and add some public methods, for example getRole():
main.php
'user' => array('class' => 'application.components.WebUser')
WebUser.php
class WebUser extends CWebUser {
public $role;
public function getRole(){
if ($this->role === null) {
// Here you need to get User role
$this->role = Yii::app()->db->createCommand("SELECT role FROM {{user}} WHERE id=:id")->queryScalar(array(':id' => Yii::app()->user->id));
}
return $this->role;
}
}
Then call if where you need Yii::app()->user->role or Yii::app()->user->getRole()
I have two models 'a' and 'b' and a->hasMany('b') and b->belongsTo('a')
So when I create one 'b' this should belongs to exactly one 'a'.
The problem is with the usual Route::resource('b', 'bController') I can just create this 'b' and don't know to which 'a' this belongs.
I tried editing the create() method in bController to create($id) but
Redirect::action('bController#create', $a->id)
Still redirects to /b/create?2 an gives an error
Missing argument 1 for bController::create()
Maybe a bit easier to unserstand when I use phoneand user.
Every phone belongs to one user.
How can I create a phone? How do I give the create() the parameter of the user and still use the Route::resource?
I think you are on a wrong direction because User and Phone are two models and hence a User has many phones so here Phone model is a child model (related) of User class and a Phone can't exist without a User so you only need to create a User through the controller and Phone will be created when the User gets created, for example:
Route::resource('users', 'UserController');
Now assume that you have tow models as User and Phone and the User model has phones method which builds the relationship (phones = User->hasMany('Phone')) and the Phone model has a user method which builds the relationship (user = Phone->belomgsTo('User')).
// User model
class User extends Eloquent {
//...
public function phones()
{
return $this->hasMany('Phone');
}
}
// Phone model
class Phone extends Eloquent {
//...
public function user()
{
return $this->belongsTo('user');
}
}
Now to create a User the store method will be used like this:
// UserController.php
class UserController extends BaseController {
// Other methods
// Creates a User
// URI: /users Method: POST
public function store()
{
// Create a User using User model
$user = User::create(...);
if($user) {
// Initialize/Create a Phone
$phone = new Phone(array(...));
if($phone) {
// Save the Phone and relate with User
$user->phones()->save($phone);
}
}
}
}
This is the basic idea and the final thing is that, a Phone doesn't require a Controller to be created, because it's the part of a User so when you create a new User then create a (or more) Phone from the UserController after you create a User or update a Phone when you update a User.
So if you want to load a User with it's related Phone models then you may do it like this:
$user = User::with('phones')->find(1);
So, when you load a user, you can load all the phones related with that user so during editing of an user; you only need to load a User with related Phone models and pass that model to the view.
To add a new Phone to an existing User you need to edit the User model so you can load a User model with phones and pass that User model to the view for editing. When new Phone being added to the user, you only need to attach that Phone with existing User, that's it. Hope it makes sense.
In my laravel app I have multiple user accounts who have resources that are assigned to them. Say, for example, a "payment". To edit or view a payment a user would visit the /payment/edit/{payment} route (where payment is the payment ID).
Although I have an auth filter to stop un-logged in users from accessing this page there is nothing to stop, for example, user 1 from editing user 2's payment.
Is there a filter I can user that checks which user a payment (or any other resource) belongs to prevent this kind of issue?
[I am using Laravel's model bindings which automatically fetches the model specified by the route rather than me get it in the controller using eloquent.]
No such filter exists by default, however you can easily create one (depending on how your database is set up). Within app/filters.php, you may do something like this:
Route::filter('restrictPermission', function($route)
{
$payment_id = $route->parameter('payment');
if (!Auth::user()->payments()->find($payment_id)) return Redirect::to('/');
});
This compares the currently logged in user's payment_id (in your database) to the {payment} argument passed into the route. Obviously, depending on how your database is set up (for instance if the payment_id is in a separate table) you need to change the conditional.
Then, apply the filter to your route:
Route::get('/payment/edit/{payment}', array('before' => 'restrictPermission'));
One way is to place a where statement in every relevant query. Although not very pretty, it works.
$payment = Payment::where('user_id', '=', Auth::user()->id)->find($id);
It's also possible to use url filters like seeARMS is suggesting, however I think it's not very elegant. The most logical place to nest such logic is in the model itself. One possibility is to use model events, but this gives you only the option to intercept update, insert or delete statements, not selects. This might change in the future. Maybe you could use boot() event, but I'm not sure if this is gonna work.
Last but not least you could use query scopes.
class Payment extends Eloquent {
public function scopeAuthuser($query)
{
return $query->where('user_id', '=', Auth::user()->id);
}
}
and in the queries you attach the scope
Payment::authuser()->find($id);
You could do this on a base Model and extend from it, so you have that method in all your relevant models.
Consider using Laravel Policies:
https://laravel.com/docs/6.x/authorization#policy-methods
<?php
namespace App\Policies;
use App\Post;
use App\User;
class PostPolicy
{
/**
* Determine if the given post can be updated by the user.
*
* #param \App\User $user
* #param \App\Post $post
* #return bool
*/
public function update(User $user, Post $post)
{
return $user->id === $post->user_id;
}
}
By policies you can control if given record could be edited by logged user or not.
Cheers!