I've just started to learn about laravel and I want to use this framework with It's advantages. I'm asking this question to learn the right way to this with laravel.
It is printing the post from posts table which has the same id with $id.
<?php
class PostsController extends BaseController{
public function singlePost($id)
{
$thePost = Posts::find($id);
return View::make('singlePost')->with('thePost', $thePost);
}
}
Normally I do check if there is a post that's id equal to $id and if that is, return view so forth. Isn't there better way to do this with laravel like you can do with route filters.
Shortly,
How to know if there is post with that id?
How to throw exception if there is not?
...
Route Model Binding might be an option however a more universal solution is findOrFail
findOrFail will either return the model or throw a ModelNotFoundException which will display as a 404 page.
$thePost = Posts::findOrFail($id);
return View::make('singlePost')->with('thePost', $thePost);
To just check for existence you can use find and then compare with null:
$thePost = Posts::find($id);
if($thePost != null){
// post exists
}
Or simpler, just a truthy value:
$thePost = Posts::find($id);
if($thePost){
// post exists
}
See "Route Model Binding" in the documentation.
Route::model('post', 'Post', function() {
// do something if Post is not found
throw new NotFoundHttpException;
});
Route::get('post/{post}', function(Post $post) {
return View::make('singlePost')->with('thePost', $post);
});
You could also just replace find() with findOrFail() in your code, which would throw an exception of a post wasn't found with that ID.
Related
I am trying to delete a file after I delete the product from the database, but it shows me an error, and I cannot find a solution.
Call to a member function delete() on null
public function supprod($id,Request $request)
{
$produits=Produit::find($id);
$produits->delete(); // <-- error on this line
$filename=(string)$document->nom;
Storage::disk('fichier')->delete($filename);
return redirect()->back();
}
Image of the problem
this is check the record this function $produits=Produit::find($id);
This use $produits=Produit::where('id',$id)->first();
You should really let Laravel do the work for you.
Change your action to:
public function supprod(Produit $id, Request $request) {
$filename=(string)$id->nom;
Storage::disk('fichier')->delete($filename);
$id->delete();
return redirect()->back();
}
This will make the framework find the appropriate model or throw a 404 error if it does not exist.
More information in the implicit model binding section of the documentation
We have a DB with 100 users.. for example
And here is the route
Route::get('/users/{user}/edit', 'UserController#edit');
Here is the method
public function edit(User $user)
{
$hi = 'Hello';
return $hi;
}
Ok.. if I do something like this
http://localhost/users/99/edit | WORKS
http://localhost/users/100/edit | WORKS
http://localhost/users/101/edit | PROBLEM
How to solve when the user change the value from URL with an inexistent record..?
In this case I would pass the user id as a parameter rather than explicit binding:
Route::get('/users/{userId}/edit', 'UserController#edit');
When a model is not found you will get a ModelNotFoundException exception thrown, you can catch it and treat this case
Controller:
use Illuminate/Database/Eloquent/ModelNotFoundException;
[...]
public function edit($userId)
{
try{
$user = User::find($userId);
//do some stuff
} catch (ModelNotFoundException $e){
//treat error (log the activity, redirect to a certain page)
//or display a 404 page
//dealer's choice
}
}
In your case the user can't be found, which is a 404:
public function edit(User $user)
{
$user = false; // dummy/example
if ($user) {
return $your_results;
} else {
return view('errors.404');
// assuming you have a folder called 'errors' inside your 'views' folder
// and the file name is `404.blade.php`
// and are using blade files.
}
}
If the user can be found, show whatever you need to, else, show a 404 blade view.
A little late, but it is an useful question.
To suppress the error message you can set the debug mode in the (dot)ENV file to false APP_DEBUG=true. Due to the route model binding, the other solutions above won't help you, because if the model is not found, you won't get into the controller. Unless you don't get the model but only the id or slug etc. and then make a query against the database within the function.
When I submit a form in Laravel, the following controller method handles it:
public function update($id)
{
//handle input
return View::make('generic.success', ["message" => 'Data submitted successfully!']);
}
This works fine. However, instead of returning a view like above I'd like to return a redirect, because when I return the view directly, reloading the page resubmits the form.
So I tried to do this:
public function update($id)
{
//handle input
return Redirect::to('/success', ['message' => 'Data submitted successfully!']);
}
In my routes file I defined the success route:
Route::get('success', 'NotificationsController#success');
And set up a notification controller to display the view:
class NotificationsController extends BaseController {
public function success($message)
{
return View::make('generic.success', ["message" => $message]);
}
When I run the above code, I get the following error from Laravel:
InvalidArgumentException
The HTTP status code "1" is not valid.
I have no idea what this is supposed to tell me, and neither does Google apparently.
Can someone shed some light on this issue?
P.S.
Incidentally, being new to Laravel, I've noticed so far that Laravel's error reporting is very user-unfriendly, in that instead of telling me I have an issue with my router, or controller, or permissions, it displays these generic errors with no humane explanation of their cause. Is there a better way to troubleshoot problems in Laravel than relying on this?
For example, in the above incident, the error report points to this line of code...
public function setStatusCode($code, $text = null)
{
$this->statusCode = $code = (int) $code;
if ($this->isInvalid()) {
throw new \InvalidArgumentException(sprintf('The HTTP status code "%s" is not valid.', $code));
}
...which is completely useless, as all it does is show me the code that printed the error itself.
The second parameter of the redirector's to() method is the HTTP status code that will be returned by the response, not data that will be passed along. Passing data when redirecting to GET routes can be done either via the query string or the session. The recommended solution here is to pass data via the current session using the with() method which passes that data for the next request. So in your case this would be the approach needed:
public function update($id)
{
return Redirect::to('/success')->with('message', 'Data submitted successfully!');
}
Then in your success method you can have this:
public function success($message)
{
return View::make('generic.success', ["message" => Session::get('message')]);
}
When in doubt always try checking the documentation first. The solution to this is explicitly stated in the Laravel Response Redirects Documentation.
Thanks a lot -Bogdan I found in the documentation that you post answer to my problem. In my case the solution was redirect to an action in a controller, like this...
return
\Redirect::action(
'PqrController#solicitud',
array($id)
)
->with(
'message',
'¡El estado de la solicitud ha sido actualizado correctamente!'
)
;
I redirect to a method in a controller, with one parameter array($id) and I put too in the session a message using ->with('message','Mensaje')
I have two controllers. I find problem in passing posted values from one controller to another. Here is a quick view,
This is the function 1
public function setRole(request $request){
this->forward(Path,array(role=>$role));
this->redirect(path of second controller);
}
This is the function 2.
public function getRole(request $request){
$role = $request->get('role');//when printing this $role, I am able to get the value of $role.
$sql = "select * from table where id=$role"; // I cannot get the value in this qry ,also, i cannot pass the value to a twig file
return render...(filename,array('roleid'=>$role));
}
Problem is I could'n access the variable "roleid" in my twig file of second controller. Always it goes empty.
Is there anything i have missed here?
You have missed the Documentation :
public function indexAction($name) {
$response = $this->forward('AcmeHelloBundle:Hello:fancy', array(
'role' => $role
));
// ... further modify the response or return it directly.
// But do not redirect afterwards!
// Just return the response that the forwarded controller returns
return $response;
}
In case anyone else finds this from Googling. From Symfony 3.3 you can use the session interface to pass things from one controller to another.
As the documentation says: To retrieve the session, add the SessionInterface type-hint to your argument and Symfony will provide you with a session.
use Symfony\Component\HttpFoundation\Session\SessionInterface;
public function indexAction(SessionInterface $session)
{
// store an attribute for reuse during a later user request
$session->set('foo', 'bar');
// get the attribute set by another controller in another request
$foobar = $session->get('foobar');
// use a default value if the attribute doesn't exist
$filters = $session->get('filters', array());
}
In a Laravel controller I have a couple of methods that all begin by fetching a database record, then after checking if data has been found either continue by rendering a view, or, in case of no data, go to a 404 page.
Here's an example:
<?php
function get_show_user($id)
{
$user = static::get_user($user_id);
if (!$user) {
return Response::error('404', static::$some_common_error404_message);
}
return View::make('users.show_readonly_user_data')->with('user', $user);
}
function get_edit_user($id)
{
$user = static::get_user($user_id);
if (!$user) {
return Response::error('404', static::$some_common_error404_message);
}
return View::make('users.display_edit_user_form')->with('user', $user);
}
I'm repeating the entire if (!$user) statement in these methods, even if they all do the same thing.
I'd rather like to do something like this:
function get_show_user($id)
{
$user = Users::find($id);
static::go404_if_null($user);
return View::make('users.show_readonly_user_data')->with('user', $user);
}
function get_edit_user($id)
{
$user = Users::find($id);
static::go404_if_null($user);
return View::make('users.display_edit_user_form')->with('user', $user);
}
What would be the best way to implement such a DRY feature?
Obviously a simple return Response::error('404') would not work in the common existence checker method, since it would only return from that method.
It seems that an Event::fire('404') is not ideal either since it does not terminate the method it has been triggered in.
Perhaps using an exception would be required here, but I'm unsure about this, or how it should be done in Laravel. Where should I catch a 404 Exception of a controller?
I think the best way to approach this would be a before filter on your controller.
public static $require_user = array(
'edit_user',
'show_user',
);
public function before()
{
$route = Request::route();
if ( in_array( $route->controller_action, static::$require_user ) )
{
$this->user = User::find( $route->parameters[0] );
if ( is_null($this->user) ) return Response::error('404');
}
}
Before filters get called after your controller is constructed but before the method is called. If a before filter returns anything other than null, the method is not called and thus execution is stopped.
Here we obtain the current route being executed so we can check which method is going to be called against our array $require_user. This lets us use methods that don't require a user id, such as login.
Then we retrieve the user instance, getting the id from what would have been passed to the method. You should probably add more error handling here.
Lastly, we check if the user returned was null, meaning not found. If that is the case we return a 404 response, stopping execution of the method.
I hope this helps!