Hi I have a common function to get a Client Name dynamicaly. Now I want to call that function to every view (Twig). I am following it like this:
//My controler
public function getSchoolNameAction(){
$session = new Session();
$dm = $this->getDocumentManager();
$commonFunction = new CommonFunctions();
return $schoolName= $commonFunction->schoolName($dm,$session);
}
//My View (search.html.twig)
{% render controller('EduAccountBundle:Ledger:getSchoolName') %}
But its showing an error that :
he controller must return a response (null given). I need to make it for every view. Please guide me how to fix this
Don't define a controller as a service, controllers should be used only to take a request and to produce a response (you're just returning a value, that isn't acceptable for Symfony logic)
Unless you want to return a rendered template (or produce a valid response, such like a json response) to put where you're calling the common action (you could do that of course), I will recommend to write a custom twig extension
Related
I have two mvc style endpoints returning templatefile names as view names, in the same classpath: /source and /target. The source_template has a variable which needs to be filled by contents of another template, say target_template.
#RestController
class SomeController {
#GetMapping("/source")
public String source(Model model) {
model.addAttribute("attr1", /*call endpoint /target and add the response of parsed template 'target_template' here */);
return "source_template";
}
#GetMapping("/target")
public String target(Model model) {
model.addAttribute("attr2", "good");
//may be continue the nested invocation n number of times
return "target_template";
}
}
given the source_template.html:
Hai, $attr1
and the target_template.html:
this has been a $attr2 day
having said, i invoke the url /source, I should get "Hai, this has been a good day".
I can just call the target() method directly, but that would not render the template. Or I should directly use the templating engine apis to link the template file, put the context object, parse the template and return the string , which defeats the whole purpose of spring mvc. Or I can use resttemplate, but that requires an absolute url, and performance would take a hit. So, is there any other way to do it ?
I want to print value 5 on the ss page.
www.xyz.com?a=5.
How to fetch url data in silverstripe? Any help is accepeted.
In your controller that your Silverstripe template is for, you can retrieve "GET" (aka. query string) by returning the result of $this->getRequest()->getVar('a') in a function on your controller.
It is good practice to use $this->getRequest()->getVar('a') over $_GET['a'] as SilverStripe will automatically sanitise the string.
When your code is not in the controller (so you can't make use of $this->getRequest()), you can request the current controller by using Controller::curr() which will make the complete call for getting a single var:
Controller::curr()->getRequest()->getVar('a')
If you want to get all "GET" variables, just call getVars() instead..
Also, you can access "POST" variables in a similar calling postVar('a') or postVars() instead. If you want to get the value from both "POST" or "GET", you can call requestVar('a') or requestVars().
Anyway, here is a basic mock-up of a controller using a function on the controller that is accessible in the template.
Controller
class TestPage_Controller extends Page_Controller
{
public function init()
{
parent::init();
}
public function MySpecialProperty()
{
return $this->getRequest()->getVar('a');
}
}
Template
<p> $MySpecialProperty </p>
I understand that using {% render() %} automatically forces a new request object to be sent, but im curious if theres a way to pass in the originating request as an argument?
{% render('some_action', {'originalRequest': app.request}) %}
This doesn't seem to do anything for the controller:
public function actionAction($originalRequest = null)
{
// $originalRequest ends up just being null
}
Im assuming its because of the way the route is setup:
some_action:
pattern: /stuff/
defaults: { _controller:SomeApp:Controller:action }
I'd imagine data like that cant obviously be apart of the URL, so some type of way to pass in data to a renderable URL, anything at all?
EDIT (Solution)
The solution was pretty simple in the long run, as Petre Pătraşc below has demonstrated, that in Twig, all I needed to do was invoke the Controller directly, and with that approach I can pass in Objects (Such as a Request object) and Arrays, instead of text values in a URL.
To perform roughly the same idea in a controller, utilizing the forward() method from the router, will allow similar effects without needing to redirect the user to another page.
If I understand correctly, you're looking for this:
{% render "MyBundle:Controller:someAction" with { 'originalRequest' : app.request } %}
use the render function as a result
{{ render(controller('MyBundle:ControllerName:example', {'originalRequest': app.request})) }}
and then in your controller
public function exampleAction(Request $originalRequest)
{
// do something
}
Since Symfony 2.4 you can access the original request via the request_stack. This avoids the need to create a new method parameter.
function exampleAction() {
$request = $this->get('request_stack')->getMasterRequest();
//do something
}
Use this carefully as it makes your sub-requests incompatible with ESIs/reverse proxies (where a sub-request is also a master request) http://symfony.com/blog/new-in-symfony-2-4-the-request-stack
I'm new to Spring MVC and trying to get a Post/Redirect/Get pattern working. We're trying to implement a survey where each page can display a variable number of questions. The way I'd like to implement this is a GET handler that prepares the next survey page and then hands that off to the view. In the same Controller, have a Post handler that processes the form's answers to the survey questions, submits that to the survey service, which returns the next page of questions, and then redirects that next surveyPage to the getNextPage GET handler.
Most of it is working, except the problem is that I don't know how to hand that 'next survey page' object from the POST handler to the getNextPage GET handler in the redirect. The redirect is working; it goes from the POST method to the GET method, but the surveyPage ModelAttribute is a new object in the GET method, and not the one that was set at the end of the POST method. As you can see, I've tried using ModelAttribute, but it doesn't work. I also tried using #SessionAttributes above the class, but then got a HttpSessionRequiredException.
We didn't know how to handle the dynamic form containing a variable # of questions with Spring MVC Forms, so we just did straight JSTL. It's funky but it works. That funkiness is what resulted in using the #RequestBody and SurveyPageBean coming back with the Post. Honestly, I don't know how the SurveyPageBean is populated. It looks like some Spring MVC magic, but it's working so I'm leaving it alone for now (another developer did this and then I picked it up, and we're both new to Spring MVC). Please don't get distracted by the unusual form handling, unless that is part of the problem with the empty surveyPage ModelAttribute not being redirected.
Here's the Controller snippet:
#Controller
#RequestMapping("/surveyPage")
public class SurveyPageController{
#RequestMapping(method=RequestMethod.GET)
public String getNextPage(#ModelAttribute("surveyPage") SurveyPage surveyPage, Model model) {
if(surveyPage.getPageId() == null) {
// call to surveyService (defined elsewhere) to start Survey and get first page
surveyPage = surveyService.startSurvey("New Survey");
}
model.addAttribute("surveyPage", surveyPage);
return "surveyPage";
}
#RequestMapping(method=RequestMethod.POST)
public String processSubmit(#RequestBody String body, SurveyPageBean submitQuestionBean, Model model, #ModelAttribute("surveyPage") SurveyPage surveyPage) {
// process form results, package them up and send to service, which
// returns the next page, if any
surveyPage = surveyService.submitPage(SurveyPageWithAnswers);
if (results.getPageId() == null) {
// The survey is done
surveyPage = surveyService.quitSurvey(surveyId);
return "redirect:done";
}
model.addAttribute("surveyPage ", surveyPage );
return "redirect:surveyPage";
}
Use Flash Attributes as shown in Warlock's Thoughts.
#RequestMapping(method = RequestMethod.POST)
public String handleFormSubmission(..., final RedirectAttributes redirectAttrs) {
...
redirectAttrs.addFlashAttribute("AttributeName", value);
return "redirect:to_some_url_handled_by_BController";
}
Your GET takes the surveyPage as a model attribute, which means it is reading it from the URL. In the POST, rather than adding the surveyPage to the model (which is lost because you are telling the client to redirect, which creates a new request and therefore a new model) you should add the surveyPage as a query parameter in your "redirect:surveyPage" You'll have to look at how the surveyPage is constructed from the query params in order to know what to put on the query string.
If, for instance, the surveyPage is constructed from a user, page number, and question count or something, I believe you could do something like "redirect:surveyPage?userId=1234&pageNumber=5678&questionCount=12 in order to pass that model attribute along.
I am looking for way to do this in 'right' symfony way.
There's a way to get the referer page from the $request variable. For example, if I was in myaction/mypage and click to myaction2/mypage2 by this getReferer() method I get 'http://myweb/myaction/mypage'.
If you are in an action method this can be done by
public function executeMyaction(sfWebRequest $request)
{
$previousUrl = $request->getReferer();
...
}
if you are somewhere else you can get the request by getting the conext
$previousUrl = $this->getContext()->getRequest()->getReferer();
For for sfWebRequest methods check the sfWebRequest API.
Note: this value could be inaccesible using proxy's