Error in loading page in laravel 5.3 - laravel-5.3

I have problem in loading page i got error like below
I have route function as
Route::get('/courses', 'HomeController#getCourseList');
And my controller function is
public function getCourseList() {
$getCourse = Course::where('status', 1)->get();
return view('courselisting')->with(['courses' => $getCourse]);
}
blade code for rendering page is
<a class="read_more_btn" href="{{ url('/courses') }}">Browse all the Course</a>

Related

Twig: Render view with different parameters based on one Controller action

this might be a stupid question but maybe you can still help me out here.
What I want: I have a Twig template, that has tabs in it (using Bootstrap tab panels) and now I want to render the tab contents using one Action from one Controller but with different parameters.
So basically, this controller action should take some param "type" and then return different results based on this type. The goal is to not have 2 Controllers to render the twig view that do almost the same except extracting different information based on the param "type.
However, I cannot get it to work. It's either that both tabs render the same results since apparently the view is only rendered once OR that I get exceptions in the twig template at time of rendering.
What would be the right way to approach this problem?
Many thanks.
There are multiple ways to achieve this. You can use if/else statements in your Twig template, but you can also set the template in you controller. It's up to you what suits best.
Method 1: custom template
By default, Symfony uses 'foobar.html.twig' on your foobarAction() method, but you can override this in your method:
public function recentArticlesAction($max = 3)
{
// make a database call or other logic
// to get the "$max" most recent articles
$articles = ...;
return $this->render(
'article/recent_list.html.twig',
array('articles' => $articles)
);
}
(warning: example from How to Embed Controllers in a Template, but the article itself has nothing to do with your question)
You can set a variable (for example $templateName) and change it:
$templateName = 'recent_list.html.twig';
if ($admin) {
$templateName = 'another_template.html.twig';
}
//or using parameters from you Request
if ($type = $request->request->get('type')) {
$templateName = $type . '.html.twig';
}
return $this->render(
$templateName,
array('articles' => $articles)
);
Method 2: using Twig
Controller:
public function foobarAction(Request $request)
{
return [
'type' => $request->request->get('type');
];
}
You Twig template:
{% if type == 'foo' %}
<h1>Foo!</h1>
<p>Hi, welcome you the foo page!</p>
{% elseif type == 'bar' %}
<h1>Bar!</h1>
<p>Hi, you've reached the Bar page.</p>
{% else %}
<h1>Error!</h1>
<p>Type not found.</p>
{% endif %}
Try render manually each view:
if ($type) {
return $this->render('home/template.html.twig', array('data' => $data));
}
return $this->render('home/another.html.twig', array('another_data' => $another_data));
Many thanks for the answers here, but they did not really helped me. Next time I try to add more code examples ;)
My goal was to render from 1 action into 1 template but with different parameters and render those different contents as partials in the parent view.
Example: Given a template called "view.html.twig" that includes 2 times the template "myPartial.html.twig", but first time with param and second time without param. Based on this param different contents should be returned.
My question was now, why apparently only the first action is rendered in Symfony as both my partial views had the same content.
So this is what I did now:
1 Controller, 2 Actions, both call a 3rd action to fetch the data and return the values to the calling action. Then both actions call the render method with the values rendered from the 3rd action.
This is what it looks now:
<div class="tab-content clearfix">
<div class="tab-pane" id="1b">
{% render controller('MyBundle:MyController:list1') %}
</div>
<div class="tab-pane" id="2b">
{% render controller('MyBundle:MyController:list2', {'type' : 1}) %}
</div>
But what I wanted to achieve was to do something like this (which did not work because then both tabs would show the same content):
<div class="tab-content clearfix">
<div class="tab-pane" id="1b">
{% render controller('MyBundle:MyController:list') %}
</div>
<div class="tab-pane" id="2b">
{% render controller('MyBundle:MyController:list', {'type' : 1}) %}
</div>
Which I find confusing since in both times "render" is called, so I would expect that the Controller is called in both times so that also the partial view in the controller is rendered both times. But apparently this was not the case :( The Controller itself looks something like this:
public function list1Action()
{
$twigVars = //do something to build the twig vars without param;
return $this->render('#MyBundle/Test/partial_list.html.twig', array(
'vars' => $twigVars,
));
}
public function list2Action($param)
{
$twigVars = //do something to build the twig vars with param;
return $this->render('#MyBundle/Test/partial_list.html.twig', array(
'vars' => $twigVars,
));
}
While what I wanted was something like this:
public function listAction($param = '')
{
if ($param) {
$twigVars = //do something to return the twig vars with param;
} else {
$twigVars = //do something else to return twig vars without param;
}
return $this->render('#MyBundle/Test/partial_list.html.twig', array(
'vars' => $twigVars,
));
}

No more routes available after Twig's render() function

I’m facing a weird behavior from Symfony 2.5.5 (PHP 5.6.1), more specifically Twig. Here is a fragment of my template layout:
<nav>
{% render controller('SGLotteryGameBundle:Home:lastDraw') %}
<ol class="breadcrumb">
<li>{{ 'SuperWinner'|trans }}</li>
{% block bc %}{% endblock %}
</ol>
</nav>
This template worked fine until I added the render call. After that, Symfony reported:
An exception has been thrown during the rendering of a template
("Unable to generate a URL for the named route "sg_lottery_home" as such route does not exist.")
in /home/kevin/Prog/PHP/SG2/src/SG/Lottery/GameBundle/Resources/views/layout.html.twig at line 70.
Of course, the sg_lottery_home is defined and works well without the render block. If I comment the path generation of this route, the immediate next one fails. Routes before the tag are rendered without any issue.
Here is the SGLotteryGameBundle:Home controller:
<?php
namespace SG\Lottery\GameBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\HttpFoundation\Response;
class HomeController extends Controller
{
/**
* #Template
*/
public function indexAction()
{
return [];
}
public function lastDrawAction()
{
return new Response('Dummy');
}
}
I tried replacing {% render ... %} by {{ render(...) }}, without any change.
Important note: it only happens when I’m logged in.
Apparently, it was caused by JMSI18nRoutingBundle generating an error while retrieving the user's locale: the available locales were en and fr and the user's locale fr_FR. I have no idea how the {{ render(...) }} call interacted with that.

Checking class scope ACLs in Twig templates

I'm building a small-scale symfony project, as much for my own edification as anything else.
I have a Network class which extends Entity in a Doctrine ORM setup, and a bunch of users (also entities in a Doctrine setup). I've given some users the CREATE permission on the Network class, and that seems to be working. At least the exception is thrown when I expect it:
$securityContext = $this->get('security.context');
$objectId = new ObjectIdentity('class', 'Acme\\AcmeBundle\\Entity\\Network');
if(false === $securityContext->isGranted('CREATE', $objectId)) {
throw new AccessDeniedException("You do not have permission.");
}
But I'd like to check the permission in a twig template, something like this:
{% if is_granted('CREATE', 'Acme\\AcmeBundle\\Entity\\Network') %}
<li>
<a href="{{ path('network_new') }}">
Create a new entry
</a>
</li>
{% endif %}
My goal here is to only show the link if the user has permission to create a new network. But the is_granted() call seems to be returning true for all the users, not just the ones that I've explicitly granted CREATE to, or at least link is always appearing, even for users that have no ACL/ACE entries for the Network class.
It turns out that is_granted() expects an object as the second parameter. This is a Twig Extension that provides a classId() function to return an ObjectIdentifier object.
class ClassIdExtension extends \Twig_Extension
{
public function getFunctions()
{
return array(
'classId' => new \Twig_SimpleFunction('classId', array($this, 'classId'))
);
}
public function classId($class)
{
return new ObjectIdentity('class', $class);
}
public function getName()
{
return 'acme_classidextension';
}
}
Once it's registered as a service in Symfony, you can use it in Twig templates like so:
{% if is_granted('CREATE', classId('Acme\\AcmeBundle\\Entity\\Network')) %}
<li>
<a href="{{ path('network_new') }}">
Create a new entry
</a>
</li>
{% endif %}
And it works as expected.

Make controller only give a value to template, not render it - Symfony2

I have a twig template with the navbar and all other templates (the pages) include this template. I have a value in it which should be equal to all pages. How to set this value?
I tries something like this in a controller:
public function setNotificationsAction() {
$this->setNotifications();
return $this->render('AcmeMyBundle::navbar.html.twig', array(
'debts' => $this->notifications,
));
}
and then this in the template:
<span class="badge badge-important">
{% render(controller('AcmeMyBundle:DebtsLoansController:setNotifications')) %}
{{ debts }}
</span>
The result I want it like this:
<span class="badge badge-important">
3
</span>
but the number should be different and the controller should tell it.
I also tried to create a function which returns the value and to call it in the way like above.
I also tried this syntax
{{ render(controller('AcmeMyBundle:DebtsLoansController:setNotifications')) }}
but it isn't working, too.
I get the following mistake:
The function "controller" does not exist in AcmeMyBundle::navbar.html.twig at line 6
Do you have any idea how to achive this and not to have to edit each controller and each template :S Thanks very much in advance!
Well, I would suggest creating your own Twig extension. Something around the lines of:
<span class="badge">
{{ acme_notifications() }}
</span>
namespace Acme\DemoBundle\Twig\AcmeDemoExtension
class AcmeDemoExtension extends \Twig_Extension
{
public function getFunctions()
{
return array(
'acme_notifications' => new \Twig_Function_Method($this, 'getNotifications');
);
}
public function getNotifications()
{
$notifications = ...;
return $notifications;
}
}
Read more about creating your own Twig extension in the Symfony2 documentation.
You don't need the controller part :
{% render "AcmeBundle:MyController:MyAction" %}
Be aware however, that a render is a completely new request going through the whole Symfony lifecycle and thus can impact performance if you abuse it.
Edit : And as #Wouter J has pointed out : prior to Symfony 2.2 use above notation. After Symfony 2.2 the following has to be used :
{{ render(controller('AcmeArticleBundle:Article:recentArticles', { 'max': 3 })) }}

Loading MVC 4 default view with jQuery load()

I have built an mvc 4 website, and I built it so that the main layout page doesn't refresh if a different section is loaded with jQuery. I put the navigator and jQuery script in _Layout.cshtml:
<ul id="menu" class="menu-items">
<li><a id="Item1" href="#" onclick="loadPage(this.id)">Item1</a></li>
<li><a id="Item2" href="#" onclick="loadPage(this.id)">Item2</a></li>
<li><a id="Item3" href="#" onclick="loadPage(this.id)">Item3</a></li>
<li><a id="Item4" href="#" onclick="loadPage(this.id)">Item4</a></li>
</ul>
</body>
<script>
function loadPage(action) {
$.post("/Home/" + action, function (data) {
$(content).html(data);
});
}
</script>
Then I have my controller:
namespace MyApp.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Item1()
{
if (Request.IsAjaxRequest())
{
return PartialView();
}
return View();
}
[HttpPost]
public ActionResult Item2()
{
if (Request.IsAjaxRequest())
{
return PartialView();
}
return View();
}
Etc, etc.
Everything works fine, except that I don't know how to use just one main content view (which is index.cshtml when the website loads in the browser). I'm forced to put the same content that's in index.cshtml into item1.cshtml so that when I trigger onlick for item1, it will go back to the main content. The only route config I have is for the Default, which initially set to Index:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
What I want, is to be able to use just one main content page, but have the ajax call still get me back to the main content when I click Item1. Does anyone know what I need to do? It seems to be a little overkill to have to update both views when I want to update the main content.
Also, I think other web devs will like this code. Especially if you're building a band's website like I'm doing. It allows me to put the demo song media player in the _layout.cshtml page so that it won't refresh when the user is clicking to the other sections (i.e. if it refreshes, the media player stops). With this design, the user can navigate the whole website while the songs continue to play.
I'm rather new to javascript, so I'm sure I could have made a better onclick handler rather than using anchor tags, so if anyone want to show me a better way, please do. But my main problem is the index.cshtml vs item1.cshtml dilemma.
Correct me if I'm wrong: you want to refresh part of your page when clicking on ItemX link and the controller methods ItemX are only used via Ajax (as you're building a single page app).
In this case you could do something like this:
Cshtml
<ul id="menu" class="menu-items">
<li><a id="Item1" href="#" onclick="loadPage(this.id)">Item1</a></li>
<li><a id="Item2" href="#" onclick="loadPage(this.id)">Item2</a></li>
<li><a id="Item3" href="#" onclick="loadPage(this.id)">Item3</a></li>
<li><a id="Item4" href="#" onclick="loadPage(this.id)">Item4</a></li>
</ul>
<div id="container">
</div>
</body>
<script>
function loadPage(action) {
$.post("/Home/" + action, function (data) {
$("#container").html(data);
});
}
// Will load Item1 via Ajax on page load
loadPage('Item1');
</script>
Home Controller
[HttpPost]
public ActionResult Item1()
{
return PartialView();
}
Your PartialViews should only contain the HTML specific to the current item.
Update
If you wish to avoid the Ajax call you could do this also in your cshml
...
</ul>
<div id="container">
#Html.Partial("Item1PartialView")
</div>
</body>
...

Resources