I am learning Symfony2 Framework, and to start things of I found this tutorial: Tutorial. Everything has been going well until I hit this issue:
in Tutorial Part2. In Creating the form in the controller section i discover that the getRequest() function is deprecated and bindRequest() is not found in class.
These two have held me back with the tutorial and learning progress. I there any other way of constructing this controller without using these functions or are there other functions that do exactly the same thing.
See this part of the Symfony Documentation. It shows that you should use handleRequest, like so:
// Top of page:
use Symfony\Component\HttpFoundation\Request;
...
// controller action
public function newAction(Request $request)
{
$form = $this->createFormBuilder()
// ...
->getForm();
$form->handleRequest($request);
if ($form->isValid()) {
// perform some action...
return $this->redirect($this->generateUrl('task_success'));
}
return $this->render('AcmeTaskBundle:Default:new.html.twig', array(
'form' => $form->createView(),
));
}
You may also find this link useful: Handling Form Submissions.
The Request as a Controller Argument
Getting the request object in this way might be a little confusing at first, to quote the documentation:
What if you need to read query parameters, grab a request header or
get access to an uploaded file? All of that information is stored in
Symfony's Request object. To get it in your controller, just add it as
an argument and type-hint it with the Request class:
use Symfony\Component\HttpFoundation\Request;
public function indexAction($firstName, $lastName, Request $request)
{
$page = $request->query->get('page', 1);
// ...
}
This information can be found on the Controller Documentation.
Related
From the documentation I see it is done in controller:
https://symfony.com/doc/current/security/csrf.html
public function delete(Request $request)
{
$submittedToken = $request->request->get('token');
// 'delete-item' is the same value used in the template to generate the token
if ($this->isCsrfTokenValid('delete-item', $submittedToken)) {
// ... do something, like deleting an object
}
}
But when thinking about having slim controllers, I try to get things out of controller. So I am planning to add it to the service. Am I thinking well?
So I find myself creating form request to validate the request that has been posted from a form. And sometimes it gets too complex that Laravel's Validation Rules can't help, so I make another validation in the data service (which is imported in the Controller).
I'll give an example to make it much clearer:
A writer posts and article. The data request is being processed at App\Http\Requests\Article\CreateArticleRequest. After the validation verifies it's valid, the request is being forwarded to the controller. In the controller, I send the request to the ArticleService for the business logic. So far so good.
But! what if I want to make some specific validation on my own that Laravel's validation rules can't help me. because then I'll have to load a repository for complex queries.
So the big issue here is that I "double check" the request instead of one time. So I thought about merging my 2 authorization (1 from the \Request and second from my Service). But to achieve that, I'll have to load repositories that are bound to their interface. So what's your solution?
When extending the validator factory with a new rule you can pass it a closure that inherits (see Example #3 here) any dependencies that are required.
So in your case it would be something like this:
public function boot()
{
$repository = $this->app->make(Repository::class);
Validator::extend('foo', function ($attribute, $value, $parameters, $validator) use ($repository) {
return /* your validation logic */
});
}
As for the authorization you can simply type-hint the necessary dependencies in your authorize method signature:
public function authorize(Repository $repository)
{
return /* your authorization logic */
}
I am new to Laravel and would like to know the best pracitse method to handle duplicate code.
I have nearly in all functions of my api-controllers this code at beginning:
// Validate parameters
$validator = Validator::make($request->all(), $this->validationRules);
if ($validator->fails()) {
return response()->json($validator->errors(), 422);
}
So normally I would put it in some function. But this code also used in lot of other controllers. so this function should be called also by other controllers.
What is best practise to handle that in Laravel 5? My first idea was to make some own Controller with this function and my other controllers would extend this.
Like:
class MyController extends Controller
{
protected function handleFailByPrameter($params)
{
....
}
}
class Api1Controller extends MyController
{
public function apicall1()
{
$this->handleFailByPrameter($this->validationRules());
}
}
But maybe there are some other methods to handle that kind of things?
You may create a validation function in your helper this will help you do that and then call this new function from anywhere in your laravel app(literally anywhere). Second thing you can do is create custom requests which will validate your data before it is passed to your function in the following way :
first generate a new requests class from artisan
php artisan make:request ExplicitRequestName
this will create a new file named ExplicitRequestName.php under app/Http/Requests folder open it, toggle false to true in your authorize function and then define your validation rules in following manner:
public function rules()
{
return [
'email' => 'required',
'password' => 'required',
];
}
call this requests object in your function :
public function someFunction(Requests\ExplicitRequestName $request)
{
}
Laravel 5.1 has a method attached to the Controller:
$this->validate($request, [your rules]);
It will redirect back with errors if anythings wrong, or send an error response if it's ajax.
To not defined your rules in every method, you can set in your models:
public static $rules = ['Your rules']
Then you can simply do your validation in your controllers, forexample:
$this->validate($request, Post::rules);
I think you are already on the right track. I implemented the validation and authentication for every API this way, although on laravel 4
.
I have created a fully functional CakePHP web application. Now, i wanna get it to the next level and make my app more "opened". Thus i want to create an RESTful API. In the CakePHP docs,i found this link (http://book.cakephp.org/2.0/en/development/rest.html) which describes the way to make your app RESTful. I added in the routes.php the the two lines needed,as noted at the top of the link,and now i want to test it.
I have an UsersController.php controller,where there is a function add(),which adds new users to databases. But when i try to browse under mydomain.com/users.json (even with HTTP POST),this returns me the webpage,and not a json formatted page,as i was expecting .
Now i think that i have done something wrong or i have not understood something correctly. What's actually happening,can you help me a bit around here?
Thank you in advace!
You need to parse JSON extensions. So in your routes.php file add:
Router::parseExtensions('json');
So a URL like http://example.com/news/index you can now access like http://example.com/news/index.json.
To actually return JSON though, you need to amend your controller methods. You need to set a _serialize key in your action, so your news controller could look like this:
<?php
class NewsController extends AppController {
public function index() {
$news = $this->paginate('News');
$this->set('news', $news);
$this->set('_serialize', array('news'));
}
}
That’s the basics. For POST requests, you’ll want to use the RequestHandler component. Add it to your controller:
<?php
class NewsController extends AppController {
public $components = array(
'RequestHandler',
...
);
And then you can check if an incoming request used the .json file extension:
public function add() {
if ($this->RequestHandler->extension == 'json') {
// JSON request
} else {
// do things as normal
}
}
i am new to zend and i could not find a way to implement Ajax in zend.
In general php, its pretty easy to make an ajax request and show the response in the desired part of our page. But coming to zend, i have no clue how to do it.
Suppose in my index controller's index.phtml file, i have a button, and when i click on it, i have to make an ajax request to a particular controller and action, and load the related controller action's view in my page.
But what i could not understand is how to specify the urls for the ajax request and how the routing works.
Currently, i made ajax request to load the view statically like this:
xmlhttp.open("GET","../application/views/scripts/register/register.phtml",true);
FYI, i am using regex routing in my application, so would it be better to use curl to route the requests?
First things first, you don't request the view directly. You need to request the specific controller action, eg
/register/register
Zend comes with a great action helper called AjaxContext. This helper lets you respond with a different view based on the type of request (XmlHttpRequest) and a format parameter, disabling any layouts normally present.
To set it up, place something like this in your controller's init() method
public function init()
{
$this->_helper->ajaxContext->addActionContext('register', 'html')
->initContext();
}
Then, add a view script with the ajax suffix, eg register/register.ajax.phtml.
Construct your AJAX GET request to include the format=html parameter, eg
xmlhttp.open('GET', '/register/register/format/html', true);
or
xmlhttp.open('GET', '/register/register?format=html', true);
What will be returned is the rendered contents of register.ajax.phtml, without any layouts.
Apart from what the other answers stated, there's also a URL view helper function that can be useful to call a specific action on a controller. So you could just use $this->url(array('controller' => 'your_controller', 'action' => 'your_action'), 'default', true); to get the link to "your_action" action on the "your_controller" controller (using the default route). You could also specify a specific route instead of 'default' if you have one defined.
So for your example you would use something like the following in your view phtml file (if you're using the default routing) :
xmlhttp.open("GET","<?php echo $this->url(array('controller' => 'register', 'action' => 'register'), 'default', true);?>");
For more information refer to Zend Framework - View Helpers.
You should never be requesting the view directly. That's just wrong. Request URI like this:
xmlhttp.open("GET","/register/register");
Which means "I am looking for default module, register controller and register action", or in other words RegisterController::registerAction().
It's the same as:
xmlhttp.open("GET","/default/register/register");
Which is the same, the default module can be omitted.
Zend Framework knows where to look for the view script (unless you are using some unusual directory structure).
You can just create a blank layout and use it for your ajax controller actions (or what Phil suggested, AjaxContent is probably better for this).
I'll write here an almost complete "how to" guide to implement AJAX calls in Zendframework 3.
We need:
A route declaration
A controller
Some javaScript (is out of skope, perhaps I'll show it in other place)
The route declaration:
<?php
// editing a module.config.php in your project
// typical lines:
namespace Ajax2l; // my ajax module name
use Zend\Router\Http\Segment;
// ...
'router' => [
// ... other routes
'ajax2lsajaxcall' => [
'type' => Segment::class,
'options' => [
'route' => '/ajax2l/ajaxrequest[/:action][/:garbage]',
// the :action wildcard is a place to have extra parameters
// the :garbage wildcard is a place to send random strings
// to ensure you break cache to get real process for
// all your calls, since every call will be different
'defaults' => [
'controller' => Controller\AjaxController::class,
'action' => 'ajaxrequest'
]
],
'may_terminate' => true,
'child_routes' => [
// other ajax routes if needed
]
],
// I only use one ajax route and one controller for all my sites' ajax
// calls because they fire small db actions and reflect them on small
// parts of my pages. So I think I do not need a route and a controller
// for each ajax call. Instead, I use a Library and some services to get
// sets of elementary components and to perform tasks.
The Controller
My Ajax2l module is located under "myzend_project/module" directory.
<?php
// Filename: /module/Ajax2l/src/Controller/AjaxController.php
namespace Ajax2l\Controller
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
// No more components are needed
class AjaxController extends AbstractActionController {
public function ajaxrequestAction(){
$request = $this->getRequest();
$content = $request->getContent();
$isHttpRequest = $this->ifIsValidHttpRequest();
// if you have a real ajax call you must disable the normal output
$viewmodel = new ViewModel();
$viewmodel->setTerminal($is_xmlhttprequest);
// If not an Ajax call (perhaps from untrusted eyes) serve a forgiven
// page message
if(!$isHttpRequest){
return $this->forgivenPage();
}
// Now prepare a response and responds
$requestParams = $this->preProcessRequest($content);
// call the logics to process your params
$output = $this->processRequestParams($requestParams);
// and send a response
$response = $this->getResponse();
$response->setContent($output);
return $response;
}
private function ifIsValidHttpRequest($content){
// I use a small token string to verify if posted data matches
// perhaps not the proper way but is fast and works
$token = 'my_secure_visitor_session_token_identifier';
return (strpos($content, $token) > 2) ? 1 : 0;
// the validation is simplified here it has some more
// complex logics. To ensure validation of requesting source
}
private function preProcessRequest($content){
// The logics to know what to do
// ...
// here you can identify and set properly the post params
}
function processRequestParams($requestParams){
// some logics to process your data
// ...
// some logics to create a Json output
// ...
return $jsonObject;
}
protected function forgivenPage(){
$view = new ViewModel([]);
// set a forgiven message page as output
$view->setTemplate('ajax2l/messages/forgiven.phtml');
// note: the views directory uses lowercase for module names
return $view;
}
}
Hope it helps. I lost a lot of time reading on zend ajax without results. So I hope I was the last losing his time on this topic.
Luis