PHP Cannot redeclare class - Require error - Silex Framework - php

I'm working on a project, but I have a very annoying problem. I use a PHP file rb.php that contains several important classes for the project (File rb.php of the RedBean ORM, all in one).
The problem is that I can use the file correctly with a require in a special location, but not in another location.
This is my arborescence:
When I go to index.php, everything goes well, i can do require('rb.php');
<?php
require_once 'vendor/autoload.php';
require('rb.php');
R::setup('mysql:host=localhost;
dbname=silex','root','');
require('Model_Bandmember.php');
use Silex\Application;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
$srcDir = __DIR__;
$app = new Application();
$app['debug'] = true;
$app->register(new DDesrosiers\SilexAnnotations\AnnotationServiceProvider(), array(
"annot.controllerDir" => $srcDir."\controllers"
));
$app->register(new Silex\Provider\TwigServiceProvider(), array(
'twig.path' => $srcDir.'\views',
));
$bandmember = R::dispense('bandmember');
$bandmember->name = 'Fatz Waller';
$id = R::store($bandmember);
$bandmember = R::load('bandmember',$id);
R::trash($bandmember);
echo $lifeCycle;die();
$app->run();
I have the good value of $lifeCycle. But I would like to use this file in a controller for functions add (), updates () etc .. So I try this :
<?php
namespace App\Controllers;
use DDesrosiers\SilexAnnotations\Annotations as SLX;
use Silex\Application;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
require(__DIR__.'/../rb.php');
/**
* #SLX\Controller(prefix="article")
*/
class ArticleController
{
/**
* #SLX\Route(
* #SLX\Request(method="GET", uri="/"),
* #SLX\Bind(routeName="articleIndex")
* )
*/
public function index(Application $app)
{
$articles = R::findAll('article');
return $app['twig']->render('Article/index.twig', array(
'articles' => $articles,
));
}
...
...
But i have this error :
Cannot redeclare class RedBeanPHP\RedException in C:\wamp64\www\SilexTest\rb.php on line 6737
Very well, I think that the file must already be present! But if i comment it i have this error :
Class 'App\Controllers\R' not found
This is normal because this class is in the rb.php file that I just commented on.
If I do a require, I have a class redeclare , but if I do not put it, it lacks a class.
Any help will be appreciated.

Since the rb is already included so no need to include it anywhere. To use it from the global scope , you've to use \R:
$articles = \R::findAll('article');
Because, it seems like that, the R is available in the global scope. In this case, you can use use R; at the top of your class, for example:
namespace App\Controllers;
use DDesrosiers\SilexAnnotations\Annotations as SLX;
use Silex\Application;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use R; // <-- Notice this
/**
* #SLX\Controller(prefix="article")
*/
class ArticleController
{
// Use: R::findAll('article') in any method in this class
}
You should read about namespace in PHP.

Related

Symfony 5 NormalizerInterface not found

i'm following a tutorial online on how to use Symfony
i followed all the step but for some reason when is try to use NormalizeInterface i get this error :
Cannot determine controller argument for "App\Controller\ApiPostController::index()": the $normalizer argument is type-hinted with the non-existent class or interface: "App\Controller\NormalizerInterface". Did you forget to add a use statement?
I tried multiple solutions and none of them worked
My code is
<?php
namespace App\Controller;
use App\Repository\PostRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Normalizer;
class ApiPostController extends AbstractController
{
/**
* #Route("/api/post", name="api_post_index", methods={"GET"})
*/
public function index(PostRepository $postRepository, NormalizerInterface $normalizer )
{
$posts = $postRepository->findAll();
$postsNormalises = $normalizer->normalize($posts, null, ['groups' => 'post:read']);
return $this->render('api_post/index.html.twig', [
'controller_name' => 'ApiPostController',
]);
}
}
Thank you for taking the time to read and thank you for you help in advance
Add use line:
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;

How to Fix class not found in Laravel

In Laravel I need to communicate to a 3rd party API. Thay have given me some PHP implementation (class) which I can use to connect and communicate with their API.
But when I try this as a class in a subfolder of the App folder and add this to my controller, I get a class not found error.
I have added a folder 'Qenner' (the provider of the API) in the App folder. And copied their classes in there.
In my controller I'm using these classes and add a code sample, like they send it to me.
Controller code (API-KEY is replaced with the actual key):
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Qenner\Search;
use QennerSearch\ServiceClient;
class TestController extends Controller
{
public function index() {
$search = new Search('https://search.qenner.com', 'API-KEY', true, 'nl-NL');
$response = $search->getCriteria([], ['Country'], []);
if (!$response->isError()) {
$criterionSets = $response->getCriterionSets();
$countryCriterionSet = criterionSets[0];
$countries = $countryCriterionSet->getCriteria();
$resultCount = $response->getResultCount();
}
dd($response);
}
Search.php in Qenner folder:
/**
* #file
* Contains QennerSearch\Search.
*/
namespace QennerSearch;
use QennerSearch\model\messages\CriterionTypesResponse;
use QennerSearch\model\messages\CriteriaRequest;
use QennerSearch\model\messages\CriteriaResponse;
use QennerSearch\model\messages\ErrorResponse;
use QennerSearch\model\messages\SearchRequest;
use QennerSearch\model\messages\SearchResponse;
use QennerSearch\model\messages\PriceRequest;
use QennerSearch\model\messages\PriceResponse;
use QennerSearch\model\messages\AccommodationInfoRequest;
use QennerSearch\model\messages\AccommodationInfoResponse;
use QennerSearch\model\messages\AutoCompleteRequest;
use QennerSearch\model\messages\AutoCompleteResponse;
/**
* Class Search, using ServiceClient to communicate, implementing the SearchInterface
*
* #package QennerSearch
*/
class Search extends ServiceClient implements SearchInterface {
.....
The folder has a ServiceClient.php
ServiceClient.php
/**
* #file
* Contains QennerSearch\Search.
*/
namespace QennerSearch;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
/**
* Class Search.
*
* #package QennerSearch
*/
class ServiceClient {
protected $http_client = null;
protected $engine_url = null;
protected $api_key = null;
protected $log_calls = false;
protected $locale = null;
protected $last_result_code = 0;
protected $last_error_body = null;
public function __construct($engine_url, $api_key, $log_calls = false, $locale = "nl-NL") {
$this->http_client = new Client();
$this->engine_url = $engine_url;
$this->api_key = $api_key;
$this->log_calls = $log_calls;
$this->locale = $locale;
I get this error:
Class 'QennerSearch\ServiceClient' not found
While I expected a dump of the output
Updated
After seeing your folder structure in the comments, I believe ServiceClient.php and Search.php, both are inside the folder: app\Qenner, hence inside those files:
wherever you are using: namespace QennerSearch;
you should use: namespace App\Qenner;
and then inside your controller, instead of using: use QennerSearch\ServiceClient;
use: namespace App\Qenner\ServiceClient
Namespaces are not like aliases, they need to reflect the position of the file itself if that makes sense.
Please give it a try and let me know if it works.

Can't use a namespace in a Controller

I have this Controller :
namespace FacilitaTripBundle\Controller;
use FacilitaTripBundle\Api\models\GuideDestination\GuideDestinationModel;
use FacilitaTripBundle\Api\models\Destination\DestinationModel;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Response;
/**
* #Route("/api/v1", name="api")
*/
class ApiController extends Controller
{
/**
* #Route("/destinations/get_all_minimal/", name="destination_get_minimal")
*/
public function getMinimalAction()
{
$model = new DestinationModel();
$data = $model->getAllMinimal();
$response = new Response(json_encode($data));
$response->headers->set('Content-Type', 'application/json');
return $response;
}
/**
* #Route("/guideDestination/getLastAddDestination/", name="destination_last_add_destination")
*/
public function getLastAddDestinationAction()
{
$guide_destination_model = new GuideDestinationModel();
$data = $guide_destination_model->getLastAddDestination();
$response = new Response(json_encode($data));
$response->headers->set('Content-Type', 'application/json');
return $response;
}
}
I got this error :
Attempted to load class "GuideDestinationModel" from namespace "FacilitaTripBundle\Api\models\GuideDestination".
Did you forget a "use" statement for another namespace
I define the class GuideDestinationModel in this file :
namespace FacilitaTripBundle\Api\models\GuideDestination;
class GuideDestinationModel {
}
How you got an idea why I got this error ?
What is the physical path to file containing GuideDestinationModel class?
According to PSR-0, which Symfony is using, you are supposed to put class definitions in path which corresponds to your namespace like in following example.
\Symfony\Core\Request =>
/path/to/project/lib/vendor/Symfony/Core/Request.php
I notice you have lowercase models in your FacilitaTripBundle\Api\models\GuideDestination namespace. Is your directory models also lowercase? If not this might be the issue here if you are using system which is case sensitive when it comes to path resolving (i.e. Linux)

Can not use CRUDController

I'm using sonata Mongodb AdminBundle for my back-end, in my case I need to create a new action for my user model ( sending a mail to him ), I followed the documentation literally
https://sonata-project.org/bundles/admin/master/doc/cookbook/recipe_custom_action.html
but I got a weird error :
Compile Error: Cannot use Sonata\AdminBundle\Controller\CRUDController as Controller because the name is already in use
and this is my CRUDController Code :
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Session\UserBundle\Document\User;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Sonata\AdminBundle\Controller\CRUDController as Controller;
class CrudController extends Controller
{
public function inscriptionAction()
{
$mail = 'towho#someone.com';
$pinCode = '1klm8';
$sender = 'Mymail#gmail.com';
$dm = $this->get('doctrine_mongodb')->getManager();
$userManager = $this->container->get('fos_user.user_manager');
$user = $userManager->createUser();
$user->setEmail($mail);
$user->setUsername($mail);
$user->setPlainPassword($pinCode);
$user->setEnabled(true);
$userManager->updateUser($user, true);
$message = \Swift_Message::newInstance()
->setSubject('Test de recrutement')
->setFrom($sender)
->setTo($mail)
->setCharset('utf-8')
->setContentType('text/html')
->setBody(
$this->renderView(
'ATSQuizzBundle:Default:SwiftLayout/createUser.html.twig',
array('user' => $user, 'pinCode' => $pinCode)
)
);
$this->get('mailer')->send($message);
$this->addFlash('sonata_flash_success', 'mail sent to the candidate');
return new RedirectResponse($this->admin->generateUrl('list'));
}
}
any one knows the origin of this error please ?
You have already imported the Controller class. And so you need to rename it in the second case. Override your use-block with next:
use Session\UserBundle\Document\User;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Sonata\AdminBundle\Controller\CRUDController as Controller;
As you see I deleted first occurrence of Controller class that is not used in your code. But if you have some other code in this file that can use "old" Controller I would recommend you to rename last Controller to BaseController and extend your class from BaseController.

how to import multiple namespaces properly

I am very new to PHP namespaces and I have a question:
If we import multiple namespaces with the 'use' command, shouldn't we run into issues?
I have been reading through this post http://www.sitepoint.com/php-namespaces-import-alias-resolution/, and in the section about Namespace Importing, it says that you still need to have a qualified prefix next to a function (ie: Lib2), but when looking at some Symfony 2 example files, I don't see that happening.
How is namespacing solving (in the example file below) solving name conflicts?
namespace Acme\DemoBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Acme\DemoBundle\Form\ContactType;
// these import the "#Route" and "#Template" annotations
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
class DemoController extends Controller
{
/**
* #Route("/", name="_demo")
* #Template()
*/
public function indexAction()
{
return array();
}
/**
* #Route("/hello/{name}", name="_demo_hello")
* #Template()
*/
public function helloAction($name)
{
return array('name' => $name);
}
/**
* #Route("/contact", name="_demo_contact")
* #Template()
*/
public function contactAction(Request $request)
{
$form = $this->createForm(new ContactType());
$form->handleRequest($request);
if ($form->isValid()) {
$mailer = $this->get('mailer');
// .. setup a message and send it
// http://symfony.com/doc/current/cookbook/email.html
$request->getSession()->getFlashBag()->set('notice', 'Message sent!');
return new RedirectResponse($this->generateUrl('_demo'));
}
return array('form' => $form->createView());
}
}
I think the misunderstanding comes from the post's filenames. keep in mind:
DefaultController.php with namespace Acme/AcmeBundle/Controller/ will be included with use Acme/AcmeBundle/Controller/DefaultController
DefaultController2.php with namespace Acme/AcmeBundle/Controller2/ will be included with use Acme/AcmeBundle/Controller2/DefaultController2
To have a conflict you'd need to include two files named DefaultController.php
DefaultController.php with namespace Acme/AcmeBundle/Controller
DefaultController.php with namespace Acme/AcmeBundle/Controller2
And would then need an alias as pointed out by Kevin
DefaultController.php with namespace Acme/AcmeBundle/Controller
=> use Acme/AcmeBundle/Controller/DefaultController
DefaultController.php with namespace Acme/AcmeBundle/Controller2
=> use Acme/AcmeBundle/Controller2/DefaultController as DefaultController2
Maybe the best way to explain this is to work backwards from the namespace resolution.
Say you have a line like the following:
$newFoo = new Foo();
PHP will look through the current symbol table for the class Foo. That symbol table includes the current namespace and any imported (use) namespaces (as well as built-in PHP symbols).
For example, say class Foo is declared in Foo.php:
<?php //Baz/Foo.php
namespace Baz\Foo;
class Foo{}
If you were working in Bar.php, you could reference the following:
<?php //Baz/Bar.php
namespace Baz\Bar;
use Baz\Foo;
//The following lines are equivalent
$newFoo = new Foo\Foo(); //Local namespace
$newFoo = new \Baz\Foo\Foo(); //Fully qualified namespace
You could also reference the Foo class directly in your use, rather than referencing the Foo namespace.
<?php //Baz/Bar.php
namespace Baz\Bar;
use Baz\Foo\Foo;
//The following lines are equivalent
$newFoo = new Foo(); //Local namespace
//$newFoo = new Foo\Foo(); //This will fail, as the symbol Foo is a class, not a namespace
$newFoo = new \Baz\Foo\Foo(); //Fully qualified namespace still works.
If you wanted to reference both the Namespace and the Class Foo directly, you'd need to resolve the conflict with an Alias.
<?php //Baz/Bar.php
namespace Baz\Bar;
use Baz\Foo;
use Baz\Foo\Foo as FooClass;
//The following lines are equivalent
$newFoo = new FooClass(); //Notice the new aliased symbol.
$newFoo = new Foo\Foo(); //This works now.
$newFoo = new \Baz\Foo\Foo(); //Fully qualified namespace still works.
//$newFoo = new \Baz\Foo\FooClass(); //This will fail, aliases don't work for fully qualified names.
Also, say, in addition to your Baz/Foo.php file, you have a Bar/Foo.php file as such:
<?php //Bar/Foo.php
namespace Bar\Foo;
class Foo{}
If you wanted to reference both namespaces locally, you'll need aliases to resolve the name conflict:
<?php //Baz/Bar.php
namespace Baz\Bar;
use Baz\Foo as Foo1;
use Baz\Foo\Foo as Foo1Class;
use Bar\Foo as Foo2;
use Bar\Foo\Foo as Foo2Class;
//The following lines are equivalent, referencing Baz\Foo\Foo
$newBazFoo = new Foo1Class(); //Object alias.
$newBazFoo = new Foo1\Foo(); //Namespace alias.
$newBazFoo = new \Baz\Foo\Foo(); //Fully qualified namespaces don't need any aliases.
//The following lines are equivalent, referencing Bar\Foo\Foo
$newBarFoo = new Foo2Class(); //Object alias.
$newBarFoo = new Foo2\Foo(); //Namespace alias.
$newBarFoo = new \Bar\Foo\Foo(); //Fully qualified namespaces don't need any aliases.
In addition to importing the Namespace with the use statement, you will also need to include the file containing that namespace. This can be done manually with require_once(), but is normally handled automatically by an autoloader.
See Symfony Class Loader for more details.
Hope that helps.

Categories