passing value from request in function to other function in same controller - laravel-8

I would like in My ContactController.php (which manages my US contact) replace the recipient's email address with a value get from the database in a table called Student ..
'''
<?php
namespace App\Http\Controllers;
use Mail;
use App\Models\Student;
use App\Models\ContactUs;
use Illuminate\Http\Request;
class ContactController extends Controller
{
public function showForm(Request $request)
{
return view('welcome');
}
public function Infos(Request $request)
{
$info = Student::find(1)->value('monemail');
//// do something
}
public function storeForm(Request $request)
{
///get value of $info
$this->validate($request, [
'name' => 'required|max:100',
'email' => 'required|email',
'phone' => 'required|numeric',
'subject' => 'required|max:100',
'message' => 'required|max:400'
]);
ContactUs::create($request->all());
\Mail::send('email', array(
'name' => $request->get('name'),
'email' => $request->get('email'),
'phone' => $request->get('phone'),
'subject' => $request->get('subject'),
'form_message' => $request->get('message'),
), function ($message) use ($request) {
$message->from($request->email);
//change test#test.fr by value of $info in Infos method
$message->to('test#test.fr', 'Message de Transport Parisien')->subject($request->get('subject'));
});
return back()->with('success', 'Thank.');
}
}
'''
I do not remember how to pass the value of a result to another method in the same controller
Thank for any help or suggestion.

I found that as a solution. It's working. If someone has another solution can be more elegant.
'''
function ($message) use ($request) {
$info = Student::find(1)->value('monemail');
$message->from($request->email);
$message->to($info, 'Message from me')->subject($request->get('subject'));
'''
Have a good day.

Related

Livewire Do Not Show The data Without the Page Reload

Hi I am making a private chat application in Livewire but the thing is when I insert a message don't show unless I reload the page please help me how can i resolved that ? Thank you.
I am using Livewire Full-Page Components here is the Code
The route
Route::get('/messaging',Messaging::class)->name('messages');
app\Http\Livewire\Messaging.php
class Messaging extends Component
{
public $body;
public $searchTerm;
public $selectedUser;
public function mount(){
$this->selectedUser =User::where('id','!=',Auth::user()->id)
->first();
}
public function render()
{
$searchTerm = '%'.$this->searchTerm.'%';
if($searchTerm){
$user= User::where('id', '!=', Auth::user()->id)
->where('email', 'like', $searchTerm)
->with('messages')
->get();
}
$conservation = Message::query()
->where('sender_id', Auth::user()->id)
->where('receiver_id', $this->selectedUser->id)
->orWhere('receiver_id', Auth::user()->id)
->where('sender_id', $this->selectedUser->id)
->with('sender')
->with('receiver')
->get();
return view('livewire.messaging',[
'users' => $user,
'conservation' =>$conservation
]);
}
public function viewMessages($userId){
$this->selectedUser = User::findorFail($userId);
}
public function sendMessages(){
Message::create([
'receiver_id' => $this->selectedUser->id,
'sender_id' => Auth::user()->id,
'body' => $this->body
]);
$this->reset('body');
$this->viewMessages($this->selectedUser->id);
}
}
You have to call the render function after completing the calling method
public function sendMessages(){
Message::create([
'receiver_id' => $this->selectedUser->id,
'sender_id' => Auth::user()->id,
'body' => $this->body
]);
$this->reset('body');
$this->viewMessages($this->selectedUser->id);
$this->render(); //this will load the all the conservation message
}

Best way to shorten store method in controller

I'm trying to shorten my controller code, and I want to know the conventions to use with Laravel while validating and storing.
Controller
public function store(Request $request)
{
// Validation
$user_id = Auth::user()->id;
$request->validate([
'lname' => 'required|max:255',
'fname' => 'required|max:255',
'ar_lname' => 'required|max:255',
'ar_fname' => 'required|max:255',
'tel' => 'required|digits:10|unique:infos',
'level' =>'required|max:50',
'goal' =>'required',
'img' => 'required|image|mimes:jpeg,bmp,png',
'cin' => 'required|image|mimes:jpeg,bmp,png',
]);
// Store
info::create([
'user_id' => $user_id,
'lname' => $request->lname,
'fname' => $request->fname,
'ar_fname' => $request->ar_fname,
'ar_lname' => $request->ar_lname,
'bday' => $request->bday,
'tel' => $request->tel,
'level' => $request->level,
'goal' => $request->goal,
'img' => $request->file('img')->store('images', 'public'),
'cin' => $request->file('cin')->store('cins/' . $request->lname . ' '. $request->fname ),
'registered' => true,
]);
// Redirect
return redirect()->route('user.index');
}
First of all you can isolate the validation in a dedicated class following the Laravel way by creating a custom Request with your rules.
php .\artisan make:request StoreInfoRequest
StoreInfoRequest
class StoreInfoRequest extends FormRequest
public function authorize(): bool
{
return true;
}
public function rules(): array
{
return [
'lname' => 'required|max:255',
'fname' => 'required|max:255',
'ar_lname' => 'required|max:255',
'ar_fname' => 'required|max:255',
'bday' => 'date',
'tel' => 'required|digits:10|unique:infos',
'level' => 'required|max:50',
'goal' => 'required',
'img' => 'required|image|mimes:jpeg,bmp,png',
'cin' => 'required|image|mimes:jpeg,bmp,png',
];
}
}
Then this can't be called a Laravel way but it will be very short and clean:
public function store(StoreInfoRequest $request)
{
info::create(
array_merge(
['user_id' => Auth::user()->id],
$request->safe()->except(['img', 'cin']),
['img' => $request->file('img')->store('images', 'public')],
['cin' => $request->file('cin')->store('cins/' . $request->lname . ' ' . $request->fname)],
['registered' => true],
)
);
return redirect()->route('user.index');
}
If you are using Laravel 9 you can do return to_route('user.index');
It is a good practice to create separate classes for each concerns, like for your controller it should only handle receiving and returning the output of your http request.
So you should create classes for the FF:
Class that will handle the validation
Class that you will handle the business logic
As what Medilies answered you have to create a separate file for validating all incoming data. You need to create a Request file that will handle it.
php artisan make:request StoreInfoRequest
StoreInfoRequest
class StoreInfoRequest extends FormRequest
public function authorize(): bool
{
return true;
}
public function rules(): array
{
// declare here everything even it is not required
return [
'lname' => 'required|max:255',
'fname' => 'required|max:255',
'bday' => 'date',
];
}
this will return an array of the validated columns you entered in your StoreInfoRequest $validated.
Then create a service file that will handle your business logic say InfoService. Within this file you can do the eloquent saving. By then you can have clean and thin controller like this.
public function store(StoreInfoRequest $request)
{
$this->InfoService->store($request->$validated);
return redirect()->route('user.index');
}
Don't forget to instantiate the service file in your controller's __constructor method.
public function __constructor(StoreInfoRequest $storeInfoRequest)
{
$this->storeInfoRequest = $storeInfoRequest;
}

passing value from Yii CController class to CForm (Form Builder) config array

I'm new to Yii, and I'm trying to do my initial project the "right" way. I've created a CFormModel class that needs three fields to query for some data, a CForm config to construct the form, and a CController to tie it together (all given below).
The data request needs an account, and this can come from a couple of different places. I think retrieving it should be in the controller. However, I don't know how to get it into the form's hidden "account" field from the controller, so that it makes it to the arguments assigned to the CFormModel after submission. More generally, I know how to pass from CController to view script, but not to CForm. Is the registry (Yii::app()->params[]) my best bet?
I suppose I can just leave it out of the form (and required fields) and wait to populate it in the submit action (actionSummaries). Does that break the intention of CForm? Is there a best practice? Even taking this solution, can someone address the first issue, in case it comes up again?
Any other, gentle critique is welcome.
models/SummariesForm.php
class SummariesForm extends CFormModel
{
public $account;
public $userToken;
public $year;
public function rules () {...}
public function fetchSummary () {...}
static public function getYearOptions () {...}
}
views/account/select.php
<?php
$this->pageTitle=Yii::app()->name;
?>
<div class="form">
<?php echo $form->render(); ?>
</div>
controllers/AccountController.php
class AccountController extends CController
{
public $layout = 'extranet';
public function actionSelect ()
{
$model = new SummariesForm();
// retrieve account
require_once 'AccountCookie.php';
/*
*
* Here, I insert the account directly into the
* model used to build the form, but $model isn't
* available to selectForm.php. So, it doesn't
* become part of the form, and this $model doesn't
* persist to actionSummaries().
*
*/
$model->account = AccountCookie::decrypt();
if ($model->account === false) {
throw new Exception('Unable to retrieve account.');
}
$form = new CForm('application.views.account.selectForm', $model);
$this->render('select', array(
'form' => $form,
'account' => $model->account,
));
}
public function actionSummaries ()
{
$model = new SummariesForm();
if (isset($_POST['SummariesForm'])) {
$model->attributes = $_POST['SummariesForm'];
/*
*
* Should I just omit "account" from the form altogether
* and fetch it here? Does that break the "model"?
*
*/
if ($model->validate() === true) {
try {
$summaries = $model->fetchSummary();
} catch (Exception $e) {
...
CApplication::end();
}
if (count($summaries) === 0) {
$this->render('nodata');
CApplication::end();
}
$this->render('summaries', array('model' => $model, 'summaries' => $summaries));
} else {
throw new Exception('Invalid year.');
}
}
}
}
views/account/selectForm.php
<?php
return array(
'title' => 'Select year',
'action' => Yii::app()->createUrl('Account/Summaries'),
'method' => 'post',
'elements' => array(
'account' => array(
'type' => 'hidden',
'value' => $account,
),
'userToken' => array(
'type' => 'hidden',
'value' => /* get token */,
),
'year' => array(
'type' => 'dropdownlist',
'items' => SummariesForm::getYearOptions(),
),
),
'buttons' => array(
'view' => array(
'type' => 'submit',
'label' => 'View summaries',
),
),
);
The answer is NO to do what you asked. You can see $form variable which acted almost like array when it was passed from controller to view. The solution is you add more property $account into selectForm model and treat it like other elements. I don't think leaving the new field outside the form will be properly way if you want to submit its value also.
Edited:

Can't authenticate with different table

I've changed the auth.php file in order to authenticate my users according to authors table. But I keep getting No account for you when I'm running test route.
auth.php
<?php
return array(
'driver' => 'eloquent',
'model' => 'Author',
'table' => 'authors',
'reminder' => array(
'email' => 'emails.auth.reminder', 'table' => 'password_reminders',
),
);
routes.php
Route::get('test', function() {
$credentials = array('username' => 'giannis',
'password' => Hash::make('giannis'));
if (Auth::attempt($credentials)) {
return "You are a user.";
}
return "No account for you";
});
AuthorsTableSeeder.php
<?php
class AuthorsTableSeeder extends Seeder {
public function run()
{
// Uncomment the below to wipe the table clean before populating
DB::table('authors')->delete();
$authors = array(
[
'username' => 'giannis',
'password' => Hash::make('giannis'),
'name' => 'giannis',
'lastname' => 'christofakis'],
[
'username' => 'antonis',
'password' => Hash::make('antonis'),
'name' => 'antonis',
'lastname' => 'antonopoulos']
);
// Uncomment the below to run the seeder
DB::table('authors')->insert($authors);
}
}
Addendum
I saw in another post that you have to implement the UserInterface RemindableInterface interfaces. But the result was the same.
Author.php
<?php
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableInterface;
class Author extends Eloquent implements UserInterface, RemindableInterface {
protected $guarded = array();
public static $rules = array();
public function posts() {
return $this->hasMany('Post');
}
/**
* Get the unique identifier for the user.
*
* #return mixed
*/
public function getAuthIdentifier()
{
return $this->getKey();
}
/**
* Get the password for the user.
*
* #return string
*/
public function getAuthPassword()
{
return $this->password;
}
/**
* Get the e-mail address where password reminders are sent.
*
* #return string
*/
public function getReminderEmail()
{
return "giannis#hotmail.com";
}
}
You don't need to Hash your password when you are using Auth::attempt(); so remove Hash::make from routes
Route::get('test', function() {
$credentials = array('username' => 'giannis',
'password' => 'giannis');
if (Auth::attempt($credentials)) {
return "You are a user.";
}
return "No account for you";
});
and it will work like a charm!

Different name fields user table?

I have a form with 2 fields (username, password) and a mysql table with those 2 same fields (username, password), and I authentication system working properly :)
But, I can not make it work if my table fields have different names, for example: (my_user, my_pass).
If you just change the username field on the other also works for me, that gives me problems is the password field.
My config auth.php
'driver' => 'eloquent'
Update
Already found the solution in my controller, the password name can not change.
Before (WRONG):
What I've done in first place was wrong
$userdata = array(
'my_user' => Input::get('my_user'),
'my_pass' => Input::get('my_pass')
);
it should be
$userdata = array(
'my_user' => Input::get('my_user'),
'password' => Input::get('my_pass')
);
You can define you own username and password field in the auth.php inside the config folder.
return array(
'driver' => 'eloquent',
'username' => 'my_user',
'password' => 'my_pass',
'model' => 'User',
'table' => 'users',
);
I hope this can be of some help.
I ran into this same problem. You need to extend your model:
// User.php
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableInterface;
class User extends Eloquent implements UserInterface, RemindableInterface {
protected $fillable = array('name','passwd','email','status','timezone','language','notify');
protected $hidden = array('passwd');
protected $table = "users_t";
protected $primaryKey = "uid";
public static $rules = array(
'name' => 'required',
'passwd' => 'required',
'email' => 'required'
);
public function getAuthIdentifier() {
return $this->getKey();
}
public function getAuthPassword() {
return $this->passwd;
}
public function getReminderEmail() {
return $this->email;
}
public static function validate($data) {
return Validator::make($data,static::$rules);
}
}
You need to implements this methods too:
public function getRememberToken(){
}
public function setRememberToken($value){
}
public function getRememberTokenName(){
}