Hello I dont know how to fix this bug , I searched in google but I got no solution for this bug, i am just trying to follow this tutorial http://tutorial.symblog.co.uk/docs/validators-and-forms.html, any help will be appreciated
ClassNotFoundException: Attempted to load class "Enquiry" from namespace
"Blogger\BlogBundle\Entity" in
C:\wamp\www\symblog.dev\src\Blogger\BlogBundle\Controller\PageController.php line 22.
Do you need to "use" it from another namespace?
this is the file code:
<?php
// src/Blogger/BlogBundle/Controller/PageController.php
namespace Blogger\BlogBundle\Controller;
// Import new namespaces
use Blogger\BlogBundle\Entity\Enquiry;
use Blogger\BlogBundle\Form\EnquiryType;
class PageController extends Controller
{
public function indexAction()
{
return $this->render('BloggerBlogBundle:Page:index.html.twig');
}
public function aboutAction()
{
return $this->render('BloggerBlogBundle:Page:about.html.twig');
}
public function contactAction()
{
$enquiry = new Enquiry();
$form = $this->createForm(new EnquiryType(), $enquiry);
$request = $this->getRequest();
if ($request->getMethod() == 'POST') {
$form->bindRequest($request);
if ($form->isValid()) {
// Perform some action, such as sending an email
// Redirect - This is important to prevent users re-posting
// the form if they refresh the page
return $this->redirect($this->generateUrl('BloggerBlogBundle_contact'));
}
}
return $this->render('BloggerBlogBundle:Page:contact.html.twig', array('form' => $form->createView()
));
}
}
Make sure:
1 the name of your file is Enquiry.php
2 it is in the folder Blogger/BlogBundle/Entity
3 it is called class Enquiry
4 the namespace is namespace Blogger\BlogBundle\Entity;
Note: The reason is that this is very often due to a typo in either the name of the file, the name of the class, the use statement or the namespace.
I solved it starting PageController.php like this:
<?php
// src/Blogger/BlogBundle/Controller/PageController.php
namespace Blogger\BlogBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Blogger\BlogBundle\Entity\Enquiry;
use Blogger\BlogBundle\Form\EnquiryType;
If you find a better solution, please let me know
If you are sure that your namespaces are all right, check if your PHP file really has .php extension.
Related
I'm writing my own project and want to use some of Symfony components.
I'm implementing Sf Router to my project and I don't understand how to call controller in router.
For ex I have a class:
<?php
namespace App;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\Routing\Loader\YamlFileLoader;
use Symfony\Component\Routing\Matcher\UrlMatcher;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\HttpFoundation as Http;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;
class AppRouter
{
public function match() {
$context = new RequestContext();
$request = Http\Request::createFromGlobals();
$context->fromRequest($request);
$matcher = new UrlMatcher($this->getRoutes(), $context);
return $matcher->matchRequest($request);
}
private function getRoutes() {
$fileLocator = new FileLocator([__DIR__ . '/../config']);
$loader = new YamlFileLoader($fileLocator);
$routes = $loader->load('routes.yml');
return $routes;
}
}
and I have some defined routes in my routes.yml so if I trying to go to registred route match() method returns to me an array like below:
[
"_controller" => "Controller\\MyController::testAction"
"_route" => "test"
]
So, how now can I call the controller for matched URL? I'm read a documentation but can't understand how should I do this.
This is a much more involved question then it might look.
The easiest approach is to simply explode the _controller string, new the controller and call the action.
// Untested but I think the syntax is correct
$matched = $router->match();
$parts = explode(':',$matched['_controller']);
$controller = new $parts[0]();
$controller->$parts[2]();
Of course there is a great deal of error checking to be added.
The reason I say it can be more complicated is that there is actually a lot you more you can do. Take a look at the HTTP Component. HttpKernel::handle($request) which uses a ControllerResolver class to create a controller as well as an ArgumentResolver to handle many of the controller's arguments. Fun stuff.
Create Your Own Framework is an excellent resource.
And the fairly new Symfony Flex approach gives you a bare bones framework which is worth studying as well.
The HTTP Kernel handles the Route to Controller invokation. You can find the full documentation here
The Controller Resolver and argument resolver will help you to match pretty easily a route to a controller method. This is the easy and robust way in order to get the router up and running on a legacy project without having to invoke the fully-fledge framework.
Think about it once more: our framework is more robust and more flexible than ever and it still has less than 50 lines of code.
require_once __DIR__.'/../vendor/autoload.php';
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing;
use Symfony\Component\HttpKernel;
function render_template(Request $request)
{
extract($request->attributes->all(), EXTR_SKIP);
ob_start();
include sprintf(__DIR__.'/../src/pages/%s.php', $_route);
return new Response(ob_get_clean());
}
$request = Request::createFromGlobals();
$routes = include __DIR__.'/../src/app.php';
$context = new Routing\RequestContext();
$context->fromRequest($request);
$matcher = new Routing\Matcher\UrlMatcher($routes, $context);
$controllerResolver = new HttpKernel\Controller\ControllerResolver();
$argumentResolver = new HttpKernel\Controller\ArgumentResolver();
try {
$request->attributes->add($matcher->match($request->getPathInfo()));
$controller = $controllerResolver->getController($request);
$arguments = $argumentResolver->getArguments($request, $controller);
$response = call_user_func_array($controller, $arguments);
} catch (Routing\Exception\ResourceNotFoundException $exception) {
$response = new Response('Not Found', 404);
} catch (Exception $exception) {
$response = new Response('An error occurred', 500);
}
$response->send();
`
My solution for are next:
change a little my routes.yml parameters: no class name contain only slash
use call_user_func_array($this->controller, $this->parameters)
I am working on a fork of the SilverStripe AMP module (https://github.com/thezenmonkey/silverstripe-amp) and have to prevent anyone from navigating to the amp.html version of a SilverStripe page if the amp.html link has not been generated into the head of the page.
A little additional info: We have added 2 fields that are meant to appear on the AMP versions of every page: AmpImage and AmpContent (a rich text editor). If either of these is empty, I have the code setup to NOT generate an AMP page for the SilverStripe page in question. This would seem to be enough but an additional requirement has been added, which is the redirect functionality mentioned about so no one can actually navigate to the amp.html page.
I was thinking of doing a redirect with the AmpSiteTreeExtension file but it does not appear to allow for redirects, then I thought of having a function in Page.php that would check if the url contains amp.html, then referencing it with AmpSiteTreeExtension, but every time I try, I get an error saying the function does not exist on "Page" or it's not public.
Is there a good way to handle this kind of situation? Is it best to do it with Page.php or using some other method?
Here are the files that I am working with:
AmpSiteTreeExtension
public function MetaTags(&$tags)
{
if ($this->owner->AmpContent != "" && $this->owner->AmpImageID != "") {
if ($this->owner->class != "HomePage") {
$ampLink = $this->owner->AbsoluteLink() . "amp.html";
} else {
$ampLink = $this->owner->AbsoluteLink() . "home/" . "amp.html";
}
$tags .= "<link rel='amphtml' href='$ampLink' /> \n";
}
//add a redirect here? Referencing a function from Page.php like so: $this->owner->functionName() causes the error mentioned above
}
}
<?php
AmpController
class AmpController extends Extension
{
private static $allowed_actions = array('amp');
private static $url_handlers = array(
'amp.html' => 'amp'
);
public function amp()
{
Requirements::clear();
$class = Controller::curr()->ClassName;
$page = $this->owner->renderWith(array("$class"."_amp", "Amp"));
return $this->AmplfyHTML($page);
}
public function AmplfyHTML($content)
{
if (!$content) {
return false;
}
$content = preg_replace('/style=\\"[^\\"]*\\"/', '', $content);
$content = str_replace("<img", "<amp-img", $content);
return $content;
}
}
From what I can tell, you're trying to redirect in the MetaTags() method of the SiteTree extension... and from what I can tell, that MetaTags() method it's probably used in some Silverstripe templates like this: $MetaTags
...and there's no way you can apply redirects this way.
You should do all this redirect stuff in a controller class, and from your example that controller it's probably the AmpController class which is probalby extending the functionality of the Page_Controller class.
Now I'll assume that AmpController it's an extension of Page_Controller, so I would do it like this:
class Page_Controller extends ContentController {
public function init() {
parent::init();
// you might have some other stuff here
// make sure this is the last line in this method
$this->extend('updateInit');
}
public function yourRedirectMethod() {
// do your redirect thing here
}
}
Key here is the following:
I extend the init() method in the controller - this will allow me to
extend the page controller's init() functionality using the
updateInit() method in the extension class (AmpController in this
case).
Instead of adding the method that's doing the redirect, to the Page
class, I added it to the Page_Controller class (the
yourRedirectMethod() method).
Now here comes the AmpController class, where I implement the updateInit() method:
class AmpController extends Extension {
private static $allowed_actions = array('amp');
private static $url_handlers = array(
'amp.html' => 'amp'
);
public function amp()
{
Requirements::clear();
$class = Controller::curr()->ClassName;
$page = $this->owner->renderWith(array("$class"."_amp", "Amp"));
return $this->AmplfyHTML($page);
}
public function AmplfyHTML($content)
{
if (!$content) {
return false;
}
$content = preg_replace('/style=\\"[^\\"]*\\"/', '', $content);
$content = str_replace("<img", "<amp-img", $content);
return $content;
}
public function updateInit() {
$should_redirect = true; // of course you add your own condition here to decide wether to redirect or not
if ($should_redirect) {
$this->owner->yourRedirectFunction();
}
}
}
The only thing here, is that you'll need to update the $should_redirect variable above (I've set it to true by default for this example - but here's where you decide if you should redirect or not)... and yes, you can reference here in the AmpController class stuff from the Page class I think, like this for exmaple: $this->owner->Title
We're building a REST API in Symfony and in many Controllers we're repeating the same code for parsing and settings properties of objects/entities such as this:
$title = $request->request->get('title');
if (isset($title)) {
$titleObj = $solution->getTitle();
$titleObj->setTranslation($language, $title);
$solution->setTitle($titleObj);
}
I'm aware that Symfony forms provide this functionality, however, we've decided in the company that we want to move away from Symfony forms and want to use something simplier and more customisable instead.
Could anybody please provide any ideas or examples of libraries that might achieve property parsing and settings to an object/entity? Thank you!
It seems like a good use case for ParamConverter. Basically it allows you, by using #ParamConverter annotation to convert params which are coming into your controller into anything you want, so you might just create ParamConverter with code which is repeated in many controllers and have it in one place. Then, when using ParamConverter your controller will receive your entity/object as a parameter.
class ExampleParamConverter implements ParamConverterInterface
{
public function apply(Request $request, ParamConverter $configuration)
{
//put any code you want here
$title = $request->request->get('title');
if (isset($title)) {
$titleObj = $solution->getTitle();
$titleObj->setTranslation($language, $title);
$solution->setTitle($titleObj);
}
//now you are setting object which will be injected into controller action
$request->attributes->set($configuration->getName(), $solution);
return true;
}
public function supports(ParamConverter $configuration)
{
return true;
}
}
And in controller:
/**
* #ParamConverter("exampleParamConverter", converter="your_converter")
*/
public function action(Entity $entity)
{
//you have your object available
}
I am currently migrating an existent application to Symfony2 that has about 100 controllers with approximately 8 actions in each controller. All the current Actions are named as follow:
public function index(){}
However the default naming convention for Symfony is indexAction().
Is it possible to keep all my current actions and tell Symfony to use as it is without the "Action" word after the method name?
thank you.
Yes, this is possible. You should be able to define routes as normal, but you need to change the way the kernel finds the controller. The best way to do this is to replace/decorate/extends the service 'controller_name_converter'. This is a private service and is injected into the 'controller_resolver' service.
The source code of the class you want to replace is at 'Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser'.
Basically, the code runs like this. The 'bundle:controller:action' you specified when creating the route is saved in the cache. When a route is matched, that string is given back to the kernel, which in turn calls 'controller_resolver' which calls 'controller_name_resolver'. This class convert the string into a "namespace::method" notation.
Take a look at decorating services to get an idea of how to do it.
Here is an untested class you can work with
class ActionlessNameParser
{
protected $parser;
public function __construct(ControllerNameParser $parser)
{
$this->parser = $parser;
}
public function parse($controller)
{
if (3 === count($parts = explode(':', $controller))) {
list($bundle, $controller, $action) = $parts;
$controller = str_replace('/', '\\', $controller);
try {
// this throws an exception if there is no such bundle
$allBundles = $this->kernel->getBundle($bundle, false);
} catch (\InvalidArgumentException $e) {
return $this->parser->parse($controller);
}
foreach ($allBundles as $b) {
$try = $b->getNamespace().'\\Controller\\'.$controller.'Controller';
if (class_exists($try)) {
// You can also try testing if the action method exists.
return $try.'::'.$action;
}
}
}
return $this->parser->parse($controller);
}
public function build($controller)
{
return $this->parser->build($controller);
}
}
And replace the original service like:
actionless_name_parser:
public: false
class: My\Namespace\ActionlessNameParser
decorates: controller_name_converter
arguments: ["#actionless_name_parser.inner"]
Apparently the Action suffix is here to distinguish between internal methods and methods that are mapped to routes. (According to this question).
The best way to know for sure is to try.
// src/AppBundle/Controller/HelloController.php
namespace AppBundle\Controller;
use Symfony\Component\HttpFoundation\Response;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
class HelloController
{
/**
* #Route("/hello/{name}", name="hello")
*/
public function indexAction($name)
{
return new Response('<html><body>Hello '.$name.'!</body></html>');
}
}
Try to remove the Action from the method name and see what happens.
I know this is no doubt a simple answer, but I just cannot seem to find the answer. I'm following a course online and this is the custom Controller:
<?php
namespace Drupal\dino_roar\Controller;
use Drupal\dino_roar\Jurrasic\RoarGenerator;
use Symfony\Component\HttpFoundation\Response;
class RoarController
{
public function roar($count)
{
$test = new RoarGenerator();
return new Response('hello');
}
}
This is the object:
<?php
namespace Drupal\dino_roar\Jurrasic;
class RoarGenerator
{
public function getRoar($length)
{
return 'R' . str_repeat('O', $length) . 'AAARRR';
}
}
But, I keep getting this:
Fatal error: Class 'Drupal\dino_roar\Jurrasic\RoarGenerator' not found
Does anybody have any ideas?
Also, I know Jurassic is spelt wrong :S