I have a static method in User model.
namespace Tol;
...
class User extends Model implements AuthenticatableContract, CanResetPasswordContract
{
...
public static function signup(array $data)
{
$user = new User([
'email' => $data['email'],
'password' => Hash::make($data['password']),
'username' => $data['username'],
'type' => $data['type'],
]);
$user->save();
if ($user && $user->id) {
$profile = new UserProfile([
'first_name' => trim($data['first_name']),
'last_name' => trim($data['last_name']),
'gender' => $data['gender'],
]);
$user->profile()->save($profile);
EmailVerification::sendTo($user, 'signup');
}
return $user;
}
...
}
And I'm trying to call call this method simply from my controllers.
like this
$user = User::signup($input);
And it throws error like this:
I don't know why it is referring it as a method on the Builder class. The code is very simple and everything was working when it was Laravel 4.
Please help.
thanks
your code should have no problem, im afraid the problem is in your auth.php file, please ensure
'model' => 'App\User',
is set it to your model file in your case
'model' => 'Tol\User',
and to ensure your calling the right file you might want to give this a try
\Tol\User::signup($array);
Related
Hi I am fairly new to Laravel framework. I am trying to create a separate controller replicating the registeredusercontroller.php in laravel breeze to have a function for admin user to be able to add new users. But I am having trouble with auto login and as soon as I add a new user it automatically logs in to the new user. How can I stop this from happening. I saw posts stating to remove
$this->guard()->login($user);
but when I see the app/Auth/registeredusercontroller.php I don't see that line.
public function store(Request $request)
{
$request->validate([
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|confirmed|min:8',
]);
Auth::login($user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
]));
$user->attachRole('user');
event(new Registered($user));
return redirect(RouteServiceProvider::HOME);
}
how can I stop the auto login after registration.
Any help is greatly appreciated.
You can do this proper way like using custom request handler.
The parameter you need is name, email, password.
So add CreateUserRequest above app/http/request
<?php
namespace App\Http\Requests;
use Illuminate\Http\Request;
class CreateUserRequest extends Request
{
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|confirmed|min:8',
];
}
}
And into your controller just do this;
public function store(CreateUserRequest $request) // add your custom request as a parameter
$user = User::create($request)
These codes makes your code structure clear and clean.
I am trying to create a customer at the same time as a user is created in the RegisterController (part of the Laravel Auth package), if that user registers as a customer. However, I have tried adding an 'accessor' to the User class by adding the following code to my User model, to access the user_id property, but the accessor does not seem to work as intended. (SEE: https://laravel.com/docs/8.x/eloquent-mutators#defining-an-accessor)
public function getUserIdAttribute($user_id)
{
return $user_id;
}
Then I try to access it directly from the model in the RegisterController with this function:
protected function create(array $data)
{
$user = User::create([
'name' => $data['name'],
'email' => $data['email'],
'username' => $data['username'],
'password' => Hash::make($data['password']),
'utype' => $data['utype'],
]);
if ($data['utype'] == "customer") {
Customer::create([
'user_id' => $user->user_id,
]);
}
return $user;
}
For some reason, the $user->user_id returns NULL though. What is the issue? Why is the accessor not being applied properly?
With the help of #lagbox, I figured out what the issue was. Turns out, the column name was simply 'id'.
I am trying to cleanup my controller. I have a lot form fields so I want to use observer to insert for the other model that have relationship with the main model
I have already successfully insert the request to the database in a controller but it seems to long and heavy. See code below
function insert(Request $request){
$bankStatementName = time().'.'.request()->bankStatement->getClientOriginalExtension();
request()->bankStatement->move(public_path('bankStatement'), $bankStatementName);
$identityName = time().'.'.request()->identity->getClientOriginalExtension();
request()->identity->move(public_path('identity'), $identityName);
$passportName = time().'.'.request()->passport->getClientOriginalExtension();
request()->passport->move(public_path('passport'), $passportName);
$customer = Customer::find(Auth::user()->id);
$relations = new Customer_relationship([
'kinName' => $request->kinName,
'kinGender' => $request->kinGender,
'kinEmail' => $request->kinEmail,
'kinRelation' => $request->kinRelation,
'kinAddress' => $request->kinAddress
]);
$company = new Customer_company([
'compName' => $request->compName,
'compEmail' => $request->compEmail,
'compPhone' => $request->compPhone,
'compAddress' => $request->compAddress
]);
$bank = new Customer_bank([
'accNumber' => $request->accNumber,
'bankName' => $request->bankName,
'accName' => $request->accName
]);
$document = new Customer_document([
'identity' => $identityName,
'bankStatement' => $bankStatementName,
'passport' => $passportName
]);
$customer->relation()->save($relations);
$customer->company()->save($company);
$customer->bank()->save($bank);
$customer->document()->save($document);
Customer::where('user_id', Auth::user()->id)
->update([
'title' => $request->title,
'middlename' => isset($request->middlename) ? $request->middlename : "",
'phone' => $request->phone,
'gender' => $request->gender,
'DOB' => $request->DOB,
'marital' => $request->marital,
'residential_address' => $request->residential_address,
'city' => $request->city,
'state' => $request->state,
'lga' => $request->lga,
'nationality' => $request->nationality,
'complete_registration' => 1 ]);
}
So how can I access the form request field from Updating function from observer to do a controller cleanup
Welcome to SO!
If you want to use Observers here, you should start by reading up on https://laravel.com/docs/5.8/eloquent#observers and https://laravel.com/docs/5.8/queues
This will likely work if you have all the data needed on your parent model, since you would just pass that model into the job that was triggered by the observer. If not, then observer/job might not be the best solution in your case. Instead I would probably create some sort of service, where you move the responsibility for creating these relationships. That way you can keep a clean controller level that only calls a service to create the models and then returns the result.
An example of this could be:
namespace App\Http\Controllers;
use App\Models\Something\SomeService;
class SomeController extends Controller
{
/**
* #var SomeService
*/
private $someService;
public function __construct(SomeService $someService)
{
$this->someService = $someService;
}
public function store()
{
$request = request();
$name = $request->input('name');
$something = $this->someService->create($name);
return response()->json(['data' => $something]);
}
}
namespace App\Models\Something;
class SomeService
{
public function create(string $name): Something
{
// Do whatever in here...
}
}
This is a simplified example of how I would do it. Hope it helps you a bit.
If you still want to use a job to take care of this, then I still don't think an observer is the right solution for you, as those are triggered on model events, such as created. This mean that you will not have access to the request object at that time, but only was was created (The model). Instead you could dispatch a job directly from the controller/service. That is all described in the queue link I posted at the top of the answer.
i can't do any more operations in create() method of RegisterController.php since it returns right after the user is created , i also don't have AuthController.php in my files ( although i have ran php artisan make:auth , but its missing .
NOTE : i need to do more operation , because i have another table called logs , i want to pass the id of the user created , but it can't be done , as i said in create() method it returns and don't let me do anymore operation .
i don't want to wright a function myself , i use remember token and other benefits . how do i do it then ? my code : protected function create(array
$data)
{
$v = new Verta();
// REMEMBER TO CREATE THEM IN MIGRATIONS
$user = User::create([
'name' => $data['name'],
'family' => $data['family'],
'national_code' => $data['national_code'],
'gender' => $data['gender'],
'birth_date' => $v->formatDate(),
'username' =>$data['username'],
'password' => bcrypt($data['password']),// REMEMBER TO CREATE THEM IN MIGRATIONS
'cell_phone' => $data['cell_phone'],
'email' => $data['email'],
'created_at_shamsi' => $v->formatDate()
]);
Logs::create([
'logDate' => $v->formatDate(),
'logTime' => $v->formatTime(),
'user_id' => $user->id,
'logCode' => '010',
'log_desc' => 'حساب با موفقیت ایجاد شد'
]);
}
In your RegisterConntroller, add the log before the returning the User object.
protected function create(array $data)
{
$user = User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
]);
// create your logs here, Log::create($user->id);
return $user;
}
Alternatively, you can use Events to insert the log whenever an user is created. From the docs:
Eloquent models fire several events, allowing you to hook into the
following points in a model's lifecycle: retrieved, creating, created,
updating, updated, saving, saved, deleting, deleted, restoring,
restored. Events allow you to easily execute code each time a specific
model class is saved or updated in the database.
You could:
(easy way) Modify the create function, such that:
protected function create(array $data)
{
$user = User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
]);
// DO YOUR LOG HERE
return $user;
}
Or, cleaner way, listen to the event and execute it when model was created:
a. Create Observers app/Observers/UserObserver.php (Read more about observers)
<?php
namespace App\Observers;
use App\User;
class UserObserver
{
public function created(User $user)
{
// PUT YOUR LOG HERE
}
}
b. Register your observer at app/Providers/AppServiceProvider.php:
<?php
namespace App\Providers;
use App\User;
use App\Observers\UserObserver;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
User::observe(UserObserver::class);
}
/**
* Register the service provider.
*
* #return void
*/
public function register()
{
//
}
}
Or, register events, let the model emit event, and catch it from your listeners and execute logging there. Docs
I have a custom function within one of my models. It looks like this:
public function newWithTeam($data, $team_id = false){
$levels = Permissions::get_levels();
$this->email = $data['email'];
$this->password = bcrypt($data['password']);
$this->username = $data['username'];
$this->save();
$profile = new Profile(['name' => $data['name'],'bio' => $data['bio']]);
$this->profile()->save($profile);
}
Here, you can see I store the email, password and username as object properties, before hitting save()
Instead, I'd like to do this in one line, something like:
$this->store(['email' => $data['email], 'password' => $data['password], 'username' => $data['username']]);
$this->save();
I am aware that the create() method exists, but when I use this, the following line
$this->profile()->save($profile); does not work properly. I think the create() function does not work the same as save() for some reason! Is there any equivalent to the store() function as above?
You can use the fill() method to achieve what you are looking for.
But before using it, you should know a few things.
Laravel models are protected against mass-assignment by security reasons, to use the fill() method you will need to define what properties of your model can be filled using the fillable or the guarded properties.
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class UserModel extends Model
{
protected $fillable = ['email', 'password', 'username'];
public function newWithTeam($data, $team_id = false){
$levels = Permissions::get_levels();
$this->fill([
'email' => $data['email'],
'password' => bcrypt($data['password']),
'username' => $data['username']
]);
$this->save();
$profile = new Profile([
'name' => $data['name'],
'bio' => $data['bio']
]);
$this->profile()->save($profile);
}
}
The fillable property functions like a white-list for mass-assignment. If you want the other way, you can use the guarded property that will function like a black-list. Which means that every column listed within the guarded property will not be available for mass-assignment and everything else will, it's your choice.
About your last statement, if you look at the implementation of the create() method you will find that it accepts a regular php array, while the save() method will accept an Eloquent Model instance. That's why create() will not work receiving your $profile variable.
I hope this helps.
The method that You're looking for is fill:
$this->fill([
'email' => $data['email'],
'password' => $data['password'],
'username' => $data['username']]
);
$this->save();
You can use it for both creating and updating.
You can use fill directly:
$this->fill($data);
$this->save();
It will use the array keys as object attributes, so make sure you'll use the same.
Also, make sure you have set the $fillable in your model (http://laravel.com/docs/eloquent#mass-assignment):
class x extends Eloquent {
protected $fillable = ['email','password','username'];
...
}
I'm not 100 % sure I understood you correctly, but it sounds like you want to make a oneliner update without screwing up the profile creation. In that case, you can simply use the update() method:
$this->update(['email' => $data['email], 'password' => bcrypt($data['password]), 'username' => $data['username']]);
That saves the new values for you.
So what happens when you run $this->create()? Are you getting an error?
Consider that create() will return the new object that you created so you could try:
$user = $this->create([
'email' => $data['email],
'password' => $data['password],
'username' => $data['username']
]);
$user->profile()->create([
'name' => $data['name'],
'bio' => $data['bio']
]);
Didn't test this so see how you get on and leave a comment if you have any further issues. Happy coding!