Symfony2 - Creating a URL - php

I've just started using Symfony. I want to echo the $bookid when I call a URL like book/5 , but I stuck somewhere.
Here's my DefaultController.php file
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class DefaultController extends Controller {
/**
* #Route("/book/{id}", name="book")
*/
public function indexAction() {
return $this->render('default/index2.html.php');
}
}
file: /Myproject/app/Resources/views/default/index2.html.php
<?php
echo $id;
?>
When I call the book/6 , I get a blank page. What's missing? Do I need to change somewhere else, too?

You should declare that variable in your action and pass it to your view.
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class DefaultController extends Controller
{
/**
* #Route("/book/{id}", name="book")
*/
public function indexAction($id)
{
return $this->render('default/index2.html.php', array(
'id' => $id
));
}
}
Whenever you have a parameter defined in your URL, you also need to "declare" it in your action function, so symfony maps it. Then, if you want to use it in your view, you have to pass it along.

If you are just starting with Symfony, I strongly recommend reading the Symfony Book and Cookbook. They are full of examples and relatively easy to understand, even for a newbie.
Other than that, the answer from smottt is correct. You add {id} in your route definition and receive it as parameter in your controller action.
Symfony book: Routing

Related

PHP how to 'include' code in the body of a class, outside of a function

I have a Symfony2 Controller in which I want to include a file containing common functions. However, when I use the require statement I get an error saying that the require was unexpected. Also, in PHPStorm, I also get a error saying that only functions can be declared where I have my require statement.
Here is an overview of my code:
<?php
namespace AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpFoundation\Response;
use ReCaptcha\ReCaptcha;
class MyController extends Controller {
private $salt_length = 10;
private $resources;
private $request;
private $session;
private $message;
private $loggedin;
/**
* #Route("/My/home")
*/
//
// My home page
//
public function homeAction() {
// bla bla
}
require 'utilities.php'; // <<==============
}
?>
The require at the end of my class produces the compiler error.
I'd rather not create another bundle and 'use' it because I want the scope of MyController class to be in effect when the functions in the utility.php are called.
Is there another preprocessor directive that does include the content of a file in another to achieve what I'm trying to do?
Oddly, when I look up include and require the php manual and w3schools php pages seem to say that you can use include/require to do exactly what I'm trying to do here.
Thank you in advance for any help someone can give me on this.
What you might be looking for are traits:
http://php.net/manual/en/language.oop5.traits.php
Using traits allows you to load additional functionality to your class.
<?php
namespace AppBundle\Traits;
trait UtilityTrait {
public function doStuff() {
return 'stuff';
}
}
?>
<?php
namespace AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpFoundation\Response;
use ReCaptcha\ReCaptcha;
use AppBundle\Traits\UtilityTrait;
class MyController extends Controller {
use UtilityTrait;
....
}
You can put whatever code you want outside the class definition and it will run when the class is loaded. I prefer creating a class of static helper functions instead of just global functions if you want to include non-class related helper type functions that have no state.
To note:
If inside utilities.php is an actual class or classes, do the right thing and registier an autoloader instead.
Use require_once instead of require
It's messy and I don't recommended it, but:
<?php
namespace AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpFoundation\Response;
use ReCaptcha\ReCaptcha;
require_once 'utilities.php'; // <<==============
class MyController extends Controller {
....

Extending my own controller in Symfony

I am creating a webapp that has some common functions. So I figured the easiest way to do this would be to make a base controller and just extend that. So in the base controller I have (similar to):
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
class BaseController extends Controller
{
protected function dosomething($data)
{
return $data;
}
}
And then in the default controller:
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
class DefaultController extends BaseController
{
/**
* #Route("/", name="homepage")
*/
public function indexAction()
{
$data = "OK";
$thedata = $this->dosomething($data);
}
}
And then for the Admin Controller:
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
class AdminController extends BaseController
{
/**
* #Route("/", name="homepage")
*/
public function indexAction()
{
$data = "OK";
$thedata = $this->dosomething($data);
}
}
However, I am getting errors like "Compile Error: Access level to AppBundle\Controller\AdminController::dosomething() must be protected (as in class AppBundle\Controller\BaseController) or weaker", not just when I load the admin controller function, but default as well. When I stop the admin controller extending base controller, this error goes (seems to work on default but not admin).
I'm guessing somewhere I have to let Symfony know that the admin controller is safe or something?
It has nothing to do with Symfony, it's PHP.
Obviously, you're trying to redefine dosomething method in your Admin Controller, and trying to make this method private.
It's not allowed. It may be either protected or public.
It's principle of OOP. Because if you would have a class SubAdminController, then instance of it would be also instance of both AdminController and BaseController. And PHP must definitely know if the method dosomething from parent class is accessible from SubAdminController.

Symfony Route not found

I'm really new with symfony, and I have strange problem.
I have a default controller, which looks like:
Both Controllers located:
src/AppBundle/Controller/
Names:
DefaultController.php
and
CmsController.php
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
class DefaultController extends Controller
{
/**
* #Route("/")
*/
public function indexAction(Request $request)
{
die('Homepage');
}
}
And I'm trying to create new one:
<?php
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
class CmsController extends Controller
{
/**
* #Route("/cms")
*/
public function cmsAction(Request $request)
{
die('Cms Page');
}
}
Routing file looks like:
app:
resource: "#AppBundle/Controller/"
type: annotation
When I try to go for www.domainname.com - default controller shows "Homepage" - as it should.
When I try to go for www.domainname.com/cms - it gives error 404.
What can be the problem?
Probelm was simply with cache. Clearing it solved the problem.

How to use methods from one controller in another

I have installed waavi package for manipulation of translation files. I need to use methods from it's controller to mine? I tried something like this but it doesn't work
LanguageRepository::findByLocale(1);
This is what I am using in beginning of my controller
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use Waavi\Translation\Repositories\LanguageRepository;
use Waavi\Translation\Repositories\TranslationRepository;
use Illuminate\Foundation\Application;
If you have successfully done all the steps in here, you should be able to access to LanguageRepository using depedency injection(" It is recommended that you instantiate this class through Dependency Injection")
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use Waavi\Translation\Repositories\LanguageRepository;
class DefaultController extends Controller
{
private $language_repository;
function __construct(LanguageRepository $language_repository)
{
$this->language_repository = $language_repository;
}
public function index()
{
dd($this->language_repository->findByLocale("en"));
}
}
Note: you need pass language string instead of id to findByLocale method. see line 97

Symfony 2: calling an undefined method

I am using the FOS Message Bundle, but it looks like it doesn't recognize the following method:
$threads = $this->getProvider()->getInboxThreads();
I get this errormessage:
Attempted to call an undefined method named "getProvider" of class "AppBundle\Controller\MessageController"
Here is the code for the controller:
namespace AppBundle\Controller;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\DependencyInjection\ContainerAware;
use Symfony\Component\HttpFoundation\RedirectResponse;
use FOS\MessageBundle\Provider\ProviderInterface;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
class MessageController extends ContainerAware
{
/**
* #Route("/messages/", name="messages_home")
*/
public function inboxAction()
{
$threads = $this->getProvider()->getInboxThreads();
return $this->container->get('templating')->renderResponse('inbox/inbox.html.twig', array(
'threads' => $threads
));
}
}
I suspected it had something to do with my usings, but I changed it and that didn't seem to help me...
You just trying to use method getProvider() from current object. $this is pointer current object of MessageController what extends ContainerAware. If these both classes (and their parents) do not has getProvider() method, throwing is an error.
I see you just imported use FOS\MessageBundle\Provider\ProviderInterface; instance. Reading the FOSMessageBundle documentation:
Get the threads in the inbox of the authenticated user::
$provider = $container->get('fos_message.provider');
$threads = $provider->getInboxThreads();
Also you need to register provider in container earlier (read more on Setting up FOSMessageBundle and Basic Usage of FOSMessageBundle).

Categories