laravel 4.1 storing URL parameter, is it possible? - php

I'm still a student and still new with these frameworks
so I have two controllers in my routes:
Route::resource('homeworks', 'HomeworkController');
Route::resource('submithomeworks', 'SubmithomeworkController');
in views/Homework/show.blade.php, I have:
href="{{ URL::action('submithomeworks.create', $homeworks->id) }}"
so the URL will go from
http://localhost:8000/homeworks/1
to
http://localhost:8000/submithomeworks/create?1
so is there a way I can just store $homework->id which is just 1 in this situation to the submithomeworks table?
I tried this on the SubmithomeworksController
public function store()
{
$rules = array(
'homework_id' => 'required',
'homework_body' => 'required'
);
$submithomework = new Submithomework;
$submithomework->homework_id = Input::get('homework_id');
$submithomework->homework_body = Input::get('homework_body');
$submithomework->student_id = Auth::user()->id;
$submithomework->save();
Session::flash('message', 'Homework successfully added.');
return Redirect::to('homeworks');
}
but what do I do after that in the view? it won't store the homework_id says its still NULL

If you need to access a route parameter you can use the Route facade. For example:
Route::input('id');
You can check the Laravel Docs.

Related

How to validate data, protect routes, authorize routes/actions in Laravel 8

This will be a bit long question, I'm finishing my application, but there are few left things to be done before ending.
At first: I did few POST forms/functions. They works well, but in case I would not pass one of the $request data, it comes with SQL bug, I read that to manage that I need validation, so I made Request model with validation rules, but I dont know how to implement it into my Controller class.
This is how looks like my request model and create class inside of controller:
public function create(Request $request)
{
$id = Auth::id();
$event = new Event;
$event->name = $request->name;
$event->description = $request->description;
$event->address = $request->address;
$event->date_of_event = $request->date_of_event;
$event->displayed = 0;
$event->photo_patch = $request->photo_patch->store('images','public');
$event->club_id = $request->club_id;
$event->user_id = $id;
$event->save();
return redirect('events');
}
------------Request---------------------------
return [
'name' => 'required|max:50',
'description' => 'required|max:100',
'address' => 'required|max:63',
'date_of_event' =>'required',
'photo_patch' =>'required',
'club_id' =>'required',
];
Second thing to protect is to split views for admin and for user, Since I did authorization via Gate(admin-level) with column in db admin(boolean)
I'm thinking about doing validation like this:
public function index()
{
$id = Auth::id();
if (Gate::authorize('admin-level')){
$events = Event::get();
}
else{
$events = Event::where('user_id',$id)->get();
}
return view('backend/event/index', ['events' => $events]);
}
but then, comes error:
Non static method 'authorize' should not be called statically.
Is there any way to bypass that? Or, is there any better/easier way to authorize?
My third problem is to protect users from making changes by other users.
What do I mean by that.
Every user got acces only to his own club/events BUT if someone would put url for example other ID, he can edit every single club/event he want. How can I prevent it?
And my final question
I'm protecting my routes with middleware auth is there any better way to do it?
Route::middleware(['auth'])->group(function() {
Thank you in advance for anwsers.
Your gate should be called on the facade, which i do not believe you are doing. Please use the following gate class.
use Illuminate\Support\Facades\Gate;
Validation can be implemented by calling validate() on your request object. This will also automatically throw exceptions if failed.
$validated = $request->validate([
'name' => 'required|max:50',
'description' => 'required|max:100',
'address' => 'required|max:63',
'date_of_event' =>'required',
'photo_patch' =>'required',
'club_id' =>'required',
]);
Disallowing users from editing clubs. In general you control the access to objects, either with policies or with queries. This is an example with a policy.
public function find(Club $club) {
$this->authorize('view', $club);
}
class ClubPolicy {
public function view(User $user, Club $club)
{
return $club->user_id === $user->id;
}
}

Better Code for Authentication in Laravel

I am really new to PHP and Laravel and i am a little embarrassed for asking this Questions but none of the things i am trying to reuse code in my Controllers work.
I have this function in my PagesController for setting up the welcome-view of my Laravel Web Application:
public function welcome(Request $request)
{
$cities = City::all();
$user_id = $request->session()->pull('user_id');
$user = User::find($user_id);
if($user !== null )$request->session()->put('user_id', $user->id);
return view('welcome',[
'cities' => $cities,
'user_id' => $user_id,
'user' => $user
]);
}
the important stuff are the three lines which gets the user_id and finds the fitting User from the Database.
I'd like to define a function in my BaseController and use it in every other Controller as well.
What would be the easiest way to do this?

Laravel 5.1 - Return to edit page

i'm writing a resource controller, and i have a problem with edit method.
i inserted a validator form, and if there is a error return to edit page with messages, but RETURN doesnt work good!
public function update(Request $request, $id)
{
$rules = [
'title' => 'required',
'content' => 'required',
'image' => 'required',
];
$messages = [
'title.required' => 'Campo titolo richiesto',
'content.required' => 'Contenuto richiesto',
'image.required' => 'Campo immagine richiesto',
];
$validator = Validator::make($request->all(), $rules, $messages);
if ($validator->fails()){
return redirect('admin/article/edit' , $id)->withErrors($validator);
}else {
$s = new Article;
$visible = (isset($_POST['visible']) == '1' ? '1' : '0');
$data = array(
'title' => $request->get('title'),
'slug' => $request->get('title'),
'content' => $request->get('content'),
'image' => $request->get('image'),
'user_id' => $request->get('user_id'),
'category_id' => $request->get('category_id'),
'visible' => $visible,
);
$s->where('id', '=', $id)->update($data);
return redirect('admin/article')->with('message', 'Articolo aggiornato con successo!');
}
}
It return to:
admin/article/edit/5
NOT to
admin/article/5/edit
How can i fix this issue? thank you for your help!
PS: $id work well, return my id edited
Here is the redirect helper. As you can see below, it takes status as its' second parameter.
function redirect($to = null, $status = 302, $headers = [], $secure = null)
What you do with passing the $id as the second parameter is actually setting the $status.
You need to pass the $to parameter as the full path like below.
return redirect('admin/article/' . $id . '/edit')->withErrors($validator);
I guess that you want to generate the url with route, which can be implemented like below.
return redirect(route('admin.article.edit', compact($id)))->withErrors($validator);
So you're saying the redirect on failure doesn't redirect to the right URL? Have you tried doing return redirect('admin/article/' . $id . '/edit')->withErrors($validator);?
I haven't tested this approach, but perhaps return redirect()->back()->withErrors($validator); could also work.
One way to do this, as others have suggested, is like following:
return redirect("admin/article/{$id}/edit")->withErrors($validator);
Or if you've a "Route Name" defined, like this..
return redirect()->route('route.name',[$id])->withErrors($validator);
it all depends on how you prefer, I prefer the later one, looks clean to me.
Easiest solution:
Laravel 5.1 has a back() helper, that returns to the previous page:
return back()->withErrors($validator);
More thorough explanation:
If you want to be more verbose, a generally more robust way to redirect to a route is to first define it as a named route in your routes.php:
Route::get('admin/article/{article_id}/edit', ['as' => 'articles.edit', 'uses' => 'ArticlesController#edit']);
Route::bind('article_id', function($id, $route) {
return App\Article::whereId($id)->findOrFail();
}
If you are using Route::resource instead, then this is already done automatically for you. To find the name of the route, run the command-line php artisan route:list. Then, in your controller method, you call it like this:
return redirect()->route('articles.edit', ['article_id' => $id])->withErrors($validator);
Using that kind of call, Laravel will automatically build the correct URL for you. This is more robust because if you ever want to change that URL to something else or change what controller method it calls, you only need to change it in one place, the routes.php, and not everywhere in your code (as long as every reference to that route in your code is referring to it by name).
Here you have
return redirect('admin/article/edit' , $id)->withErrors($validator);
means the link/route is admin/article/edit/$id(5 or 2 or ...)
better check
return redirect('admin/article/' . $id . '/edit')->withErrors($validator);
The redirect go to the passed url:
return redirect('admin/article/' . $id . '/edit'); #admin/article/id/edit
return redirect('admin/article/edit', $id); #admin/article/edit/5
And you can use methods to get this url:
return redirect(action('Controller#update', compact($id)));

Saving/Updating User Profile in Laravel 5

I can't seem to save the updated profile to the database.
In my edit.blade.php:
{!! Form::model($user, ['method' => 'PATCH', 'route' => ['profile.update', $user->company_name] ]) !!}
// fields
{!! Form::submit('Update Profile', ['class' => 'btn btn-primary']) !!}
{!! Form::close() !!}
In my ProfilesController:
public function update($company_name)
{
$user = User::whereCompanyName($company_name)->firstOrFail();
$user->save(); // no validation implemented
flash('You have successfully edited your profile');
return redirect('/');
}
After hitting the update button, it shows the flash message on the homepage but the it's not saving to the database. Im coming from Rails and I feel I need to whitelist something.
The point is, you don't change your user model at all... You retrieve it, and then save it again without setting any fields.
$user = User::whereCompanyName($company_name)->firstOrFail();
// this 'fills' the user model with all fields of the Input that are fillable
$user->fill(\Input::all());
$user->save(); // no validation implemented
If you are using the above method with
$user->fill(\Input::all());
you have to add a $fillable array to your User Model like
protected $fillable = ['name', 'email', 'password']; // add the fields you need
If you explicitly want to set only one or two ( or three....) field you could just update them with
$user->email = \Input::get('email'); // email is just an example....
$user->name = \Input::get('name'); // just an example...
...
$user->save();
If you have tried the anwer Sinmok provided, you probably get the "whooops" page because you used
Input::get('field');
instead of
\Input::get('field');
On your Blade Syntax i assume you use laravel 5.
So as your controller is namespaced you have to add a \ before Input to reference the root namespace ( or put a use statement on top of your class)
Generally on your development server you should enable debugging. Then you have more detailed information about what's going wrong than just the pure.. "whoops... "
In your config/app.php file you can set
'debug' => true;
OR
you have a look at http://laravel.com/docs/5.0/configuration
And use the .env file.
If you use the .env file make sure there is an entry with something like
APP_DEBUG=true
then you can access that value in your config/app.php with
'debug' => env('APP_DEBUG'),
There should be a .env.example in your installation to give you a clue how such a file could look like.
UserController update function look like that :-
public function update(Request $request)
{
$user = Auth::user();
$data = $this->validate($request, [
'name' => 'required',
'email' => 'required',
]);
$user->name = $data['name'];
$user->email = $data['email'];
$user->save();
return redirect('/user_edit/'.Auth::user()->id)->with('success', 'User has been updated!!');
}
Looks like you've not set the submission values to the user object.
Try (Update this is for Laravel 4)
$user = User::whereCompanyName($company_name)->firstOrFail();
$user->field = Input::get("some_field"); // Name of the input field here
$user->save(); // no validation implemented
flash('You have successfully edited your profile');
return redirect('/');
EDIT
Actually, if you're using Laravel 5 it looks like it should be:
$user->field = Request::input('some_field'); // Name of the input field here
$user->save(); // no validation implementedenter code here

Laravel 4 database actions - controller or model

just started using Laravel but want to make sure I am using it correctly.
Most of my work is CMS based so read / write / update etc to a database.
An example of what I have done so far is an insertion into the DB:
On the view I have a form with a URL of 'addNewUser'.
In my routes I then do:
Route::post('addnewuser', array('uses' => 'UserController#addNewUser'));
My user controller 'addNewUser' method is (simplified):
public function addNewUser() {
$data = Input::all();
$rules = array(
'username' => 'required|alpha_dash|max:16|unique:users,username',
);
$validator = Validator::make($data, $rules, $messages);
if ($validator->fails())
{
Input::flash();
$errors = $validator->messages();
return Redirect::to('/register')->withErrors($validator)->withInput();
}
$user = new User;
$user->save();
return Redirect::to('/login')->with('successLogin', '1');
}
Is this correct? I have read somewhere that all DB interaction should be in the model?
Likewise when reading from the DB to display a foreach for example, I do the following directly in the view:
$builds = DB::table('blogs')->orderBy('id', 'desc')->get();
if ($builds) {
foreach ($builds as $build)
{
$safeURLSlug = stringHelpers::safeURLSlug($build->blogtitle);
echo "
// stuff
";
}
} else {
// no stuff
}
Should I be doing these sort of queries and showing of data directly in the view? or in a model / controller function etc?
Want to check im doing things 100% correct / the standard way of doing things before I get too involved.
I can see a few things that I personally would have done differently.
For example I usually put $rules as a class variable so it can be used in different functions related to your Users.
Have you tested your code yet? Any errors?
In your addNewUser function does it save any data? I know you have "simplified" above the code snippet but there should be $user->username = $data['username']; etc. in between creating your $user variable and running $user->save();, so if you excluded this on purpose then I don't see anything else with your model.
In your view code, $builds = DB::table('blogs')->orderBy('id', 'desc')->get(); should be done in your controller and passed to your view like so return View::make('example', array('builds' => $builds))
I'd also change
$builds = DB::table('blogs')->orderBy('id', 'desc')->get();
to
$builds = Blog::orderby('id','desc')->get(); if you have a Blog model, otherwise your code is fine.
You could move:
$rules = array(
'username' => 'required|alpha_dash|max:16|unique:users,username',
);
to User model as static variable, and instead of:
$validator = Validator::make($data, $rules, $messages);
you could use:
$validator = Validator::make($data, User::$rules, $messages);
But definitely you shouldn't get data from database in your View, this code should be in controller, for example:
$builds = DB::table('blogs')->orderBy('id', 'desc')->get();
return View::make('someview')->with('builds', $builds);
of course if you have Blog model, you should use here:
$builds = Blog::orderBy('id', 'desc')->get();
return View::make('someview')->with('builds', $builds);
It's also unclear what the following code does:
$safeURLSlug = stringHelpers::safeURLSlug($build->blogtitle);
but probably you could move it to your Blog model and use accessor to make the change:
public function getSafeSlugAttribute($value) {
return stringHelpers::safeURLSlug($this->blogtitle);
}
and now your view could look like this:
#foreach ($builds as $build)
{{{ $build->title }}} {{{ $build->safeSlug }}}
#endforeach
I suggest you take a look on Laravel Generators.
https://github.com/JeffreyWay/Laravel-4-Generators
Install and then run:
php artisan generate:scaffold customer
Laravel line command generator create a basic CRUD for you with controller, model, views and database migrations. That's good to safe time and keep your project with some default organization.

Categories