Using only a simple file I can get elephant.io to work, but If I'm trying to integrate it inside an class, it won't work.
The reason why it won't work is that it says I can't use use elephant ... inside a class or function.
How would I integrate elephant.io in an already existing class ?
To be more specific , I'm trying to integrate elephant.io into codeigniter framework.
function tester() {
use ElephantIO\Client,
ElephantIO\Engine\SocketIO\Version1X;
require __DIR__ . '/vendor/autoload.php';
$client = new Client(new Version1X('http://www.textbasedmafiagame.com:8080'));
$client->initialize();
$client->emit('broadcast2', ['foo' => 'utførte et biltyveri']);
$client->close();
}
and get no response or outcome, but i do get:
use not allowed inside a function
and
Parse error: syntax error, unexpected 'use'
As the error states, the use keyword must be declared in the outermost scope of a file (the global scope) or inside namespace declarations.
Try something along these lines
<?php
use ElephantIO\Client, ElephantIO\Engine\SocketIO\Version1X;
require __DIR__ . '/vendor/autoload.php';
class foo{
public function tester() {
$client = new Client(new Version1X('http://www.textbasedmafiagame.com:8080'));
$client->initialize();
$client->emit('broadcast2', ['foo' => 'utførte et biltyveri']);
$ client->close();
}
}
Related
The autoloader works when I use it in index.php, but when I create an object within index.php and this object has to create other objects (which are all in the same namespace), it throws the error Uncaught Error: Class 'xxx' not found in (...).
My composer.json looks like this:
{
"autoload": {
"psr-4": {
"pizzaCase\\": "src",
"Connection\\": "src/Connection/",
"Elements\\": "src/Elements/"
}
},
"require": {
"cboden/ratchet": "^0.4"
}
}
My index.php looks like this:
<?php
require_once __DIR__. '/vendor/autoload.php';
require_once __DIR__."/src/config.php";
use Connection\Database;
use Elements\Form;
use Elements\FormElement;
use Elements\FormElementRadio;
// Database::init();
$form = new Form();
$data["options"] = "soemthing, something else";
$form->addElement("", "pizza", "", "Choose pizza", "radio", $data);
?>
In the addElement method I then create an object which is also within the src/Elements/ namespace, but it throws the error mentioned above.
The body of my addElement method looks like this:
<?php
namespace Elements;
class Form
{
public static $leftSize = 3;
protected $elements = [];
public function addElement($table, $name, $value, $label=false, $type = false, $data = false)
{
$type = ucfirst($type);
$class = "FormElement{$type}";
//FAILS HERE
if(class_exists($class))
{
//CLASS EXISTS, CREATE OBJECT FROM RESPECTIVE CLASS
$form = new $class($table, $name, $value, $label, $type, $data);
$this->elements[$name] = $form;
}
}
}
What am I doing wrong (or missing)? How come the autoloader can autoload it from index.php, but the object I create cannot create other objects without autoloader failing?
The difference is not to do with where the code is being run; the difference is that the failing code is trying to choose which class to load dynamically.
In PHP, namespaces are essentially a compile-time feature: before any of your code is run, the compiler looks at all references to class names which don't start with \, and prefixes them with the current namespace, or according to rules you've specified with use statements. When the code runs, the current namespace, and use statements, aren't visible at all.
When you specify a class name dynamically, the compiler just sees a string, not a class name, so leaves it alone. Then when the code runs, the class name looked up is assumed to be fully specified, not relative to the current namespace or use statements.
So the solution is simple - specify the full namespace when creating the dynamic class name:
$class = "Elements\FormElement{$type}";
You can also use the magic constant __NAMESPACE__ to have the compiler substitute the current namespace name for you (obviously, this still won't account for any use statements):
$class = __NAMESPACE__ . "\FormElement{$type}";
Alternatively, if you have a specific set of classes you are choosing between, you can use the ::class syntax to generate a string at compile time, based on the current namespace and any use statements in effect:
$mapTypeToClassName = [
'Radio' => FormElementRadio::class, // expands to 'Elements\FormElementRadio'
'Select' => FormElementSelect::class,
// etc
];
$class = $mapTypeToClassName[$type];
It could be because you’re having multiple namespaces for the src directory.
Usually you would just create a namespace for src like this
“psr-4": {
"PizzaCase\\": "src"
}
And then just use PizzaCase\Elements and PizzaCase\Connections as namespaces
Recently I decided to use Symfony 5.4 container in one of the projects to provide some comprehensive DI. It works well as usual, until I tried to use some env vars in services.yaml::parameters section.
Docs state that to bind to an env var I should
# services.yaml
parameters:
my_var: '%env(SOME_ENV_VAR)%'
and it will be resolved from an env var on first call. Okay. I did it this way and here what I get:
echo $container->getParameter('my_var');
// env_b057c2b619f37f36_SOME_ENV_VAR_222ed306d0932595cbdeada438ccbb2a
I do see SOME_ENV_VAR in both $_SERVER and $_ENV. I also tried Dotenv component to be sure I'm not missing something, but vainly. Any env var turns into this sort of env_{hash}_{VAR_NAME}_{hash} pattern.
I'm not using complete Symfony installation, just some spare components. What I'm missing? Should I manually populate each env var on container build stage?
Container is instantiated as follows:
// $_ENV and $_SERVER already contain `SOME_ENV_VAR` here
require_once __DIR__ . '/vendor/autoload.php';
// `use` statements go here
$containerBuilder = new ContainerBuilder();
$loader = new YamlFileLoader(
$containerBuilder,
new FileLocator(implode(DIRECTORY_SEPARATOR, [__DIR__, 'config']))
);
$loader->load('services.yaml');
$containerBuilder->compile();
$container = $containerBuilder;
$my_var = $container->getParameter('SOME_ENV_VAR');
echo $my_var;
Based on your updated snippet, you need to use:
$container->compile(true); // false is the default
The argument is called resolveEnvPlaceholders. I remember it catching me some time ago.
Still find it a bit puzzling that you have $_ENV set but I'll take your word for it.
This is an old test case I dug up that still works:
use Symfony\Component\DependencyInjection\ContainerBuilder;
class Service
{
public function __construct(string $dsn)
{
echo $dsn . "\n";
}
}
$container = new ContainerBuilder();
$container->autowire(Service::class,Service::class)->setPublic(true)
->setArguments([
'%env(DSN)%'
]);
$container->setParameter('my_var','%env(DSN)%');
putenv('DSN=dsn_value');
$container->compile(true);
$service = $container->get(Service::class);
echo $container->getParameter('my_var') . "\n";
The signature for ContainerBuilder::compile() is:
public function compile(bool $resolveEnvPlaceholders = false)
If you do not pass it true, it won't resolve the environment variables' placeholders.
Additionally, there is an issue with your example.
You are calling:
$my_var = $container->getParameter('SOME_ENV_VAR');
But SOME_ENV_VAR is not a container parameter, but an environment variable. The correct call would be:
$my_var = $container->getParameter('my_var');
The whole thing would be:
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
require_once __DIR__ . '/vendor/autoload.php';
$containerBuilder = new ContainerBuilder();
$loader = new YamlFileLoader(
$containerBuilder,
new FileLocator(implode(DIRECTORY_SEPARATOR, [__DIR__, 'config']))
);
$loader->load(__DIR__ . '/services.yaml');
$containerBuilder->compile(true);
$container = $containerBuilder;
$my_var = $container->getParameter('my_var');
echo $my_var;
I'm using Monolog to create my app's logging system. In the core app file, after I create a new Monolog object, I need to select the log level that I want to print in the log file. I want to use a global constant LOG_LEVEL which could be 'DEBUG', 'INFO', etc. I need the Monolog class to treat its value as a class constant.
// content of config.php
// Here I declare the constants in a separate file called 'config.php'
define("LOG_FILE", "patch/to/my/log.log");
define("LOG_LEVEL", "ERROR");
// content of app.php
require 'config.php';
require 'vendor/autoload.php';
$container['logger'] = function($c) {
$logger = new \Monolog\Logger('logger');
error_log('log level ' . LOG_LEVEL); // prints 'log level ERROR'
$fileHandler = new \Monolog\Handler\StreamHandler(LOG_FILE, $logger::LOG_LEVEL); // here I get the error 'Undefined class constant LOG_LEVEL'
//the normal syntax would be '$logger::ERROR' in this case and that works fine
$logger->pushHandler($fileHandler);
return $logger;
};
I need the 'LOG_LEVEL' constant to be used as 'ERROR' by the monolog class, not as 'LOG_LEVEL'. What am I doing wrong here, been searching an answer for hours now without any luck.
You are now doing $logger::LOG_LEVEL, which is taking the 'LOG_LEVEL' out of the class whichever $logger is (in this case a \Monolog\Logger). That doesn't have a static variable named LOG_LEVEL, thus you get the undefined.
You have just have 'LOG_LEVEL' defined, out of any class, so:
$fileHandler = new \Monolog\Handler\StreamHandler(LOG_FILE, LOG_LEVEL);
Fancy solution:
You could do a static class and include that in your main page:
Class CONFIG {
public static $LOG_LEVEL = 'default Value';
}
// Then you can use this anywhere:
CONFIG::$LOG_LEVEL
$fileHandler = new \Monolog\Handler\StreamHandler(LOG_FILE, CONFIG::$LOG_LEVEL);
The advantage of this is having only one file for configs, not scattered across all kinds of files, which'll become very annoying very fast.
Make a static class and include that...
class GLOBALCONF{
public static $VALUE= 'Something in here';
}
// Use it where you want
GLOBALCONF::$VALUE
You're making this more complicated than it needs to be. Monolog has a function to convert an error level as as string to its own internal value. Just change your code to this:
$fileHandler = new \Monolog\Handler\StreamHandler(LOG_FILE, $logger::toMonologLevel(LOG_LEVEL));
You can also use Logger::getLevels() like the following:
$log_level = $logger->getLevels()[LOG_LEVEL];
$fileHandler = new ...StreamHandler(LOG_FILE, $log_level);
I'm just trying a very simple test
<?php
require 'vendor/autoload.php';
class Blog
{
public function post ()
{
return 'ok';
}
}
$builder = new \Aura\Di\ContainerBuilder();
$blog = $builder->newInstance('Blog');
echo $blog->post();
This results to:
Fatal error: Uncaught Error: Call to undefined method Aura\Di\Container::post()
Am I missing something?
Yes , you are missing to read the docs. You have created builder. Next you need to get the di via new instance. This is what you assigned to blog variable.
Please consider reading getting started http://auraphp.com/packages/3.x/Di/getting-started.html#1-1-1-2
// autoload and rest of code
$builder = new \Aura\Di\ContainerBuilder();
$di = $builder->newInstance();
Now you create instance of object
$blog = $di->newInstance('Blog');
echo $blog->post();
Please read the docs.
I have a view.blade.php that calls a wrapper.php that return some value for an iframe in the view.
I'm able to return that value, but I have to do some work with other methods in my laravel classes.
It's possible to instatiate the classes inside the wrapper php and call methods, or call static class methods?
Project structure:
- project
-- app
--- Http
---- Classes
----- RepositoryUtil.php
...
-- public
--- Wrapper.php
...
-- resources
--- views
---- partials
----- view.blade.php
Code inside view.blade.php:
<iframe id="reader" src="/libs/pdfjs/web/viewer.html?file=http://project.dev/Wrapper.php?id={{$encrypted}}">
</iframe>
Code inside Wrapper.php:
<?php
// tried: use App\Http\Classes\RepositoryUtil
// tried: \App\Http\Classes\RepositoryUtil::getValue();
// tried: {{RepositoryUtil::getValue()}}
$myValue = RepositoryUtil::getValue(); #not work
var_dump($myValue);
?>
Code inside RepositoryUtil.php
<?php
class RepositoryUtil{
public static function getValue(){
dd("getValue!");
return "value";
}
}
?>
The error:
( ! ) Fatal error: Class 'RepositoryUtil' not found in /home/vagrant/Code/project/public/Wrapper.php on line 14
EDIT:
I can call static class method adding include_once("../App/Http/Classes/RepositoryUtil.php"); at the top of Wrapper.php but when I call the "laravel methods" like $decrypted = Crypt::decrypt($encrypted); it return the error:
( ! ) Fatal error: Class 'Crypt' not found in /home/vagrant/Code/project/App/Http/Classes/RepositoryUtil.php on line 13
Thanks
After many and many attemps and research, I figure that out!
Post my Wrapper.php code:
<?php
require __DIR__.'/../bootstrap/autoload.php';
$app = require_once __DIR__.'/../bootstrap/app.php';
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
$response = $kernel->handle(
$request = Illuminate\Http\Request::capture()
);
$value = RepositoryUtil::getValue();
// Your other staff here...
?>
The problem was that after calling external php, Laravel wasn't booted!
I tried to boot with require __DIR__.'/../bootstrap/autoload.php';, $app = require_once __DIR__.'/../bootstrap/app.php'; and calling $app->boot(), and it worked.
But there were other problems: Facades were not loaded, but I can see into "alias" array when log $app variable.
You have to boot kernel to get Facades back.
Using Laravel 5.1.