Global functions in Symphony application - php

I thought this would be easy. For troubleshooting, I wish to call my _logger() function from anywhere in my application.
function _logger(?string $msg=null, int $offset=0, bool $time=false):void
{
$d1 = debug_backtrace()[$offset+1];
$d2 = debug_backtrace()[$offset+2];
syslog(LOG_INFO, sprintf('_logger%s: %s::%s(%s) called by %s::%s on line %s%s', $time?'('.date("Y-m-d H:i:s").')':'', $d1['class'], $d1['function'], json_encode($d1['args']), $d2['class'], $d2['function'], $d2['line'], $msg?' | '.$msg:''));
}
First, I tried adding it to index.php. When added directly in the main body, I got a server error and either with error reporting, couldn't get any info about it (just curious, but anyone know why?). I then placed it into the closure function and it works for HTTP requests only.
<?php
use App\Kernel;
// Added my logger() function here resulted in unexplained server error.
require_once dirname(__DIR__).'/vendor/autoload_runtime.php';
return function (array $context) {
// Added my logger() function here works
return new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']);
};
Then I tried adding it to to Kernal.php, and it seems to work, but must be called as \App\_logger().
<?php
declare(strict_types=1);
namespace App;
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Component\HttpKernel\Kernel as BaseKernel;
class Kernel extends BaseKernel
{
use MicroKernelTrait;
}
if(!function_exists('_logger')) {
// Added my logger() function here works but must be called as \App\_logger()
}
So, then I created a new file called _logger.php which I located in src, and it works sometimes but other times the get the below error and need to clear cache to get it working again.
<?php
declare(strict_types=1);
if(!function_exists('_logger')) {
// Added my logger() function sometimes works but other times doesn't
}
Expected to find class "App_logger" in file
"/var/www/src/_logger.php" while importing services from resource
"../src/", but it was not found! Check the namespace prefix used with
the resource in /var/www/config/services.yaml (which is being
imported from "/var/www/src/Kernel.php"). (500 Internal Server Error)
So, I went back to locating it in Kernel.php, and all is kind of good, but would really know the correct way to add a global function and what are the implications of Symphony's caching when I tried my various approaches.

Design decisions aside, you can achieve this by overriding the namespace in the Kernal.php file:
<?php
declare(strict_types=1);
namespace App {
// Must use bracket notation in order to use global namespace in the same file
// See https://www.php.net/manual/en/language.namespaces.definitionmultiple.php#example-295
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Component\HttpKernel\Kernel as BaseKernel;
class Kernel extends BaseKernel
{
use MicroKernelTrait;
}
}
namespace {
// Begin the global namespace
if(!function_exists('_logger')) {
// Added my logger() function here works but must be called as
\App\_logger()
}
}
Note: this code is untested.
Sources:
Define global function from within PHP namespace
https://www.php.net/manual/en/language.namespaces.definitionmultiple.php#example-295

Related

PHP Symfony error: "did you forget to use a use statement", regardless of class/function

I have started building a new Web App using Symfony, but am having issues using classes.
PhpStorm is able to find the functions within the classes (due to the fact that it gives suggestions when you type $className->.
Also, to prove this is not the same as the other similar questions, I have over simplified it, and even so, the error still occurs.
I have the below in my DefaultController:
<?php
namespace AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use testBundle;
use AppBundle\domainionClasses\firstlevelchecks;
class DefaultController extends Controller
{
/**
* #Route("/register",name="register")
*/
public function registerAction(){
$testClass = new firstlevelchecks();
$testing = $testClass->donothing(); //the IDE knows that the function donothing() exists, in fact it suggests it.
return new Response('');
}
}
The below is the php class located in AppBundle/domainionClasses/test1.php
<?php
namespace AppBundle\domainionClasses;
class firstlevelchecks
{
function donothing(){
return null;
}
}
When loading the /register route, the below Symfony error is displayed:
Attempted to load class "firstlevelchecks" from namespace "AppBundle\domainionClasses".
Did you forget a "use" statement for another namespace?
It is attempting to load the class from the correct name space, and I have used a use statement.
Is there anything I am missing here, or is there a problem with Symfony? This is the first time I used the new version of PhpStorm, and have just downloaded the plugin, also the first time I have experienced this issue :(
Because your file is named test1.php, how can the autoloader know which file to include ?
You shoud rename it to firstlevelchecks.php (= the name and case of your class).

Importing custom class inside a controller

I created a class at Controller folder of Cake project like this:
<?php
class Hi
{
function __construct(){ }
public function hi()
{
echo "hi!";
exit;
}
}
Then in a controller, I tried to include it:
<?php
namespace App\Controller;
use App\Controller\AppController;
include_once "Hi.php";
class MyController extends AppController
{
public function sayHi()
{
$a = new Hi();
$a.hi();
}
}
Here is the error I'm having:
Fatal error: Cannot declare class Hi, because the name is already in use in path\api\src\Controller\Hi.php on line 2
What's going on?
MyController.php and Hi.php are in the same folder. I'm using PHP 7.
Including a file won't make the classes in that file part of the current namespace, as namespaces are a per-file functionality.
http://php.net/...namespaces.importing.php#language.namespaces.importing.scope
Your Hi class will be declared in the global namespace, and your new Hi() will cause PHP to look for it in the current namespace, ie it will look for App\Controller\Hi, which doesn't exist, hence the composer autoloader kicks in, and will map this via a PSR-4 namespace prefix match to src/Controller/Hi.php, which will include the file again, and that's when it happens.
http://www.php-fig.org/psr/psr-4/
Long story short, while using new \Hi() would fix this, you better not include class files manually, or declare them in paths where they do not belong. Instead declare your files and classes in a proper autoloading compatible fashion, that is for example with a proper namespace in a path that matches that namespace, like
namespace App\Utils;
class Hi {
// ...
}
in
src/Utils/Hi.php

Class not found on namespace

I'm creating an API wrapper at the moment, and I decided to create an index.php which loads the Client, just for testing/debugging purposes.
Here's my index.php
require_once("src/API/Client.php");
$client = new \API\Client();
Here's my API\Client
namespace API;
class Client
{
public function __construct()
{
$this->_requester = new Client\Request();
return $this;
}
}
The error I'm getting is that API\Client\Request is not found in the Client.php
It does exist, and can be viewed below:
namespace API\Client
class Request
{
protected $_requestUrl;
public function __construct()
{
return $this;
}
}
This is my first foray into making an application that has fully namespaced classes, so I'd appreciate your help in getting this working.
You're missing the require_once statement to include the script that contains the Request class definition.
require_once("src/API/Client.php");
require_once("src/API/Client/Request.php"); // <-- or whatever the filename is
I recommend using an autoloader which means you don't need any include statements. For example this PSR-0 autoloader.
Also, your use of the return statement in the constructors serves no purpose. Constructors can't return values.

PHP use "use" of the interface over concrete classes

Have encountered an issue I can't seem to figure out now by myself.
Using Symfony autoload module.
Here's my factory:
namespace Core\Factories;
use \Core\Gateway;
class DatabaseAccessFactory {
// Define client type
const DEF = 'mongo';
public function createObject($type) {
switch($type) {
case self::DEF:
return new MongoClientGateway();
break;
default:
return false;
}
}
}
Example of /Core/Gateway/MongoClientGateway.php
<? namespace Core\Gateway;
class MongoClientGateway implements MongoDbGateway {
public function setUp(){
}
public function query(){
}
public function save(){
}
}
So, basically I'm using "use" keyword to load gateway namespace into my current one, and then I try to instantiate a class that is under \Core\Gateway namespace, but it says class is not found. Am I missing something?
You need to specifcy the class as well
use Core\Gateway\MongoClientGateway
or access the class with the namespace you used
new Gateway\MongoClientGateway
Btw, there's no need for the first "\" in use \Core\Gateway
It's use Foo\Bar, without leading backslash.
use Foo\Bar does not mean that every Class implicitly resolves to Foo\Bar\Class now. use Foo\Bar is shorthand for use Foo\Bar as Bar, so you can reference the namespace Foo\Bar using merely Bar. use is not "importing a namespace", it's aliasing a namespace to a shorter name.
Therefore you need to write Gateway\MongoClientGateway, or use Core\Gateway\MongoClientGateway explicitly if you want to be able to write just MongoClientGateway.
you used "use" wrong.
waht "use" does, is to tell your code where class comes from.
sample code:
use \my\namespace\className
new ClassName();
this will make the className accassible without a namespace.

Symfony 2: Class not found in Controller

I've been struggling with this for some time now. It is most likely a rookie/typo problem, but I just can't find it.
I have this class ...
<?php
namespace PriceOrQuality\POQBundle\RegExConf;
use PriceOrQuality\POQBundle\RegExConf\RegExConf;
class RegExConfIrma extends RegExConf {
public function __construct() {
$this->start_page = 'https://irma.dk';
$this->startConnection();
$this->getAllLinks();
}
}
?>
that I'm trying to load from this controller.
<?php
// src/PriceOrQuality/POQBundle/Controller/CrawlerController.php;
namespace PriceOrQuality\POQBundle\Controller;
use PriceOrQuality\POQBundle\RegExConf\RegExConfIrma;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Monolog\Logger;
use Monolog\Handler\FirePHPHandler;
Class CrawlerController extends Controller {
public function testAction($page) {
if($page == 'irma') {
$regex = new RegExConfIrma();
return $this->render('PriceOrQualityBundle:Crawling:crawling_test.html.twig', array('links' => $regex->getLinks()));
}
}
}
?>
However I get this error, and I just cannot seem to find the problem.
FatalErrorException: Error: Class 'PriceOrQuality\POQBundle\RegExConf\RegExConfIrma' not found in /Users/Rune/Sites/poq/src/PriceOrQuality/POQBundle/Controller/CrawlerController.php line 16
The RegExConfIrma resides in /Users/Rune/Sites/poq/src/PriceOrQuality/POQBundle/RegExConf/RegExConfIrma
I've tried to debug:
* the namespace
* clearing cache
* changing the namespace
But nothing helps.
Any help is highly appreciated.
Thanks!
The problem was extremely rookie.
I forgot to add .php after my file extension as I use Netbeans where the logo showed is as a php file, but without the proper extension.
So for anyone else finding this post with the same problem:
Make sure you use the right namespace
Make sure you include or usethe class
Make sure of the spelling of the class
Make sure the
filename is spelled exactly the same as the class
Make sure you've
added .php after the class file

Categories