In my Unit Test in Laravel I am setting the currently authenticated user with the code below. This is exactly how Laravel documented it on their website. I use the default User model which Laravel provide.
public function testLoggedInUserCanCreateCat() {
Route::enableFilters();
$user = new User(array(
'name' => 'john'
));
$this->be($user);
$this->call('GET', '/cats/create');
$this->assertResponseOk();
}
For some reason, when I run phpunit in SSH, I get the following error:
1) GlobalTest::testLoggedInUserCanCreateCat
Illuminate\Database\Eloquent\MassAssignmentException: name
Does anyone know whats goes wrong here? I searched for a couple of hours on the internet, but couldn't find any help..
The problem is in the error:
MassAssignmentException: name
You are trying to mass assign the variable name - but your model does not allow this.
Change your User model from this:
protected $fillable = [];
to this:
protected $fillable = ['name'];
You can read more about mass assignment here.
Related
I have to build a new system with a kind of old-style pre-existing MySQL database tables with Laravel 8 with Breeze.
Already have a user data table that is totally different from the basic Auth system in Laravel 8.
I am trying to figure out to make Auth system but it doesn't work right.
This is my User model class.
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
protected $table = 'tb_user_info';
/**
* The attributes that should be hidden for serialization.
*
* #var array<int, string>
*/
protected $hidden = [
//'passwd',
'remember_token',
];
public function setPasswordAttribute($password)
{
$this->attributes['passwd'] = \DB::raw("password('$password')");
}
public function getAuthPassword()
{
return $this->passwd;
}
}
And this is my store method in AuthenticatedSessionController, which I figured it is using in login.
public function store(LoginRequest $request)
{
$credentials = $request->validate([
'mem_id' => ['required', 'email'],
'passwd' => ['required'],
]);
$user = User::select('mem_id', 'passwd')->where('mem_id', $request->mem_id)->first();
if ($user->mem_id == $request->mem_id && $user->passwd == $this->sql_password($request->passwd)) {
$request->session()->regenerate();
return redirect('/dashboard');
}
return back()->withErrors([
'mem_id' => 'The provided credentials do not match our records.',
]);
}
I thought it simply works, but after I try to login, it doesn't work at all, just keep redirecting back to the login page. I looked up the Network tab in Chrome, it seems like the dashboard page was called but it shows 302 Found and called the login page again.
Which part should I lookup for this situation?
I am working on this for 3 days, nothing came up for a good solution.
Please, please help me, I would be appreciated just a few tips.
Ps. Please don't answer like stop using the MySQL password for password or why don't you make a new database table? because it's meaningless answers. I would do that already if I can. This is a very limited situation at work. Please understand.
A similar problem happens to me once.
if you check dd() in store function and it does not work I think. I think 302 reason is not in current store method check LoginRequest $request method. before hit to the store method function need to fullfill the LoginRequest $request therefore problem should be there
go to the LoginRequest method and there should be validation or usecase with password and you are using passwd instead of using password try to fix that error
I have some problem with laravel and protected $attributes and mutators.
I have user ranking with points. I want add to User Model another attribution with ranking Position.
In user model I have public function like this:
public function getRankPositionAttribute(){
$userPoints= Ranking::where('user_id','=',$this->id)->first();
$userPosition = Ranking::where('points','>',$userPoints->points)->count()+1;
return $userPosition;
}
I also set:
protected $attributes = array('RankPosition'='');
But it's not working (I don't see value like RankPosition in attributes). Strange thing is that when I add (for example) value like this:
protected $attributes =array('test'=>'yes');
Laravel also don't see test...
But when I add this:
protected $appends = array('RankPosition');
and in my controller I find all user and get response to json then in json response i see value like RankPosition with the correct value... :(
What Im doing wrong? Why "my laravel" skips protected $attributes?
Please help me.
This is because if you provide protected $attributes in your class then Laravel doesn't override it when the source of attributes are the table . Here the source of $attributes is database column.
But when you do something like this:
$user = new User;
then you will see a test attribute.
So to dynamically adding the attributes you should use appends property on the model.
I'm looking at this tutorial here:
http://laravel.com/docs/master/quickstart-intermediate#creating-the-task.
But rather than follow it blindly, I'm trying to make it relevant to my needs. I have come across a problem. I'm looking at this code:
/**
* Create a new task.
*
* #param Request $request
* #return Response
*/
public function store(Request $request)
{
$this->validate($request, [
'name' => 'required|max:255',
]);
$request->user()->tasks()->create([
'name' => $request->name,
]);
return redirect('/tasks');
}
Ok. So in my application I want to create a country. No user associated with it, it's just a form posting the name of a country to this route. My form passes validation and if I use the following code, I can save the new country record to my database:
If I substitute
$request->user()->tasks()->create([
'name' => $request->name,
]);
with...
$country = new Country;
$country ->name = $request->name;
$country ->save();
...then this works out ok. I don't really want this though.
What I would like to do is use something similar to the code in the tutorial.
Can anyone tell me what I should do please?
I have tried a few different guesses, but no luck. They are exactly that tho. Guesses...
Thanks.
DS
The code you see in the tutorial can be summarized as "create a task for given user". Creating Task objects the way you can see in the tutorial is possible because there is a relation set between User and Task model - see tasks() method in User class. That's why you can, given $user stores an object of class User, call $user->tasks()->create() - as a result an object of class Task will be created and automatically linked to that user.
If you want to create objects of class Country the same way, there needs to be a relation defined between countries and users - but while it makes sense in case of tasks (users have their own tasks), it doesn't sound like something you want in your application (users have their own countries?).
The documentation doesn't go into much detail about saving data to mongodb.
I've installed a fresh install of laravel and set the up the mongo connections as in the docs, installed mongodb itself.
Created a model
use Jenssegers\Mongodb\Model as Eloquent;
class Notifications extends Eloquent {
protected $connection = 'mongodb';
protected $collection = 'notifications';
public static function foo()
{
return 'test returning from model';
}
}
And create a simple route to test
Route::get('notifiction' , function(){
$notifiction = new Notifications();
$arr = array('name' => 'John Doe');
$notifiction->save($arr);
});
But when I run localhost/mongo/public/notifiction I get Whoops, looks like something went wrong. I'm not sure what else needs doing to save information to mongodb through laravel?
This error is most likely to do with mass assignment. That is laravel treats every thing as unsafe before saving it to database. Thus we have to whitelist the fields we are trying to save.
The way we do this is in model. Lets say you are trying to save data in Users table using USER model. First open app/models/user.php and add following line:
class User extends Eloquent {
protected $fillable = ['name'];
}
Above, in fillable we are listing name as we want to save name from controller (if you have any additional data fill in the array). Now we can save data from controller.
Eg: User::create(array('name' => 'John')); will save name in Users collection. Please note the name of collection will be the name of the model unless specified otherwise.
[If this does not solve your problem, enable debug by going to app/config/app.php and setting debug =true. Find the error and try searching.]
You need not to do like model for SQL.
You try model like this
class User extends Moloquent {
protected $connection = 'mongodb';
protected $collection = 'collection1';
protected $fillable = ['_id','userName','passwd'];
}
You can try this to insert
DB::connection('mongodb')->collection('collection1')
->insert(array(
'_id' => 'H12345',
'userName' => 'Nithil',
'passwd' => 'qwoeuig'));
Using Moloquent is more convenient in using multiple DBS. For using Moloquent, you may register an alias for the MongoDB model by adding the following to the alias array in app/config/app.php:
'Moloquent' => 'Jenssegers\Mongodb\Model',
This will allow you to use the registered alias like:
class MyModel extends Moloquent {}
As OP has mentioned the error was due to
Did not installed the MongoDB PHP Library
Apart from that, to do mass assignment in Laravel, the fields should either be "white listed" or "black listed"
To whitelist the field(s) add
// name, age, username and email could be mass assigned
protected $fillable = ['name', 'age', 'username', 'email'];
To blacklist the field(s) add
// except _id everything could be mass assigned
protected $guarded = ['_id'];
to your model file
I have a User and Account model. The relationship is User belongs to Account, Account has many Users.
Here is the model code for both:
User Model:
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'account' => array(self::BELONGS_TO, 'Account', 'account_id'),
);
}
Account Model:
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'users' => array(self::HAS_MANY, 'User', 'account_id'),
'userCount'=>array(self::STAT,'User','account_id'),
);
}
I have this code in my UserIdentity.php for logging in which WAS working just fine:
public function authenticate()
{
$user=User::model()->findByAttributes(array('username'=>$this->username));
if($user===null)
$this->errorCode=self::ERROR_USERNAME_INVALID;
else{
if($user->password!==$user->encrypt($this->password))
$this->errorCode=self::ERROR_PASSWORD_INVALID;
else{
$this->_id=$user->id;
if($user->last_login_time==null)
$lastLogin=time();
else
$lastLogin=strtotime($user->last_login_time);
$this->setState('lastLoginTime', $lastLogin);
$this->setState('account',array('id'=>$user->account->id,'name'=>$user->account->name,));
$this->errorCode=self::ERROR_NONE;
}
}
return !$this->errorCode;
}
It started giving an error when I added another user to the account:
PHP Notice: Trying to get property of non-object.
The error points to
$this->setState('account',array('id'=>$user->account->id,'name'=>$user->account->name,));
When broken up into multiple lines:
'id'=>$user->account->id, is where the error lies.
To fix this, I simply changed it to this:
$account=Account::model()->findByPk($user->account_id);
$this->setState('account',array('id'=>$account->id,'name'=>$account->name,));
So the relationship worked just fine when I had a single user, but when I had 2 users, the relationship fails. I can continue using Yii as above, but I did like the simplicity of accessing the object directly. Did I not set up the relationships correctly? Why is this not working now with 2 users in one account?
EDIT:
var_dump($user) - http://pastebin.com/TEyrFnme
Also interesting is that I can access the user from the account using: $users=$account->users; and access all the $user[0] attributes just fine. So in reverse, the relationship seems to be working, just going forward seems to have difficulty.
Don't declare a variable in your model with the same name as a relation.
public $account;
will prevent the model from looking for the account relation, as Yii will first look for (and use) actual attributes before checking for relations of the same name.