The getenv() always returns false. I am using Symfony dotenv library and loading my variables from a .env file in the root of my project.
use Symfony\Component\Dotenv\Dotenv;
use Symfony\Component\Dotenv\Exception\PathException;
if (!getenv('APP_ENV')) {
try {
(new Dotenv())->load(__DIR__ . '/../.env');
} catch (PathException $ex) {
echo $ex->getMessage();
exit(1);
}
}
var_dump(getenv('APP_ENV')); // bool(false)
But when I dump the super global I can see my variables
var_dump($_ENV); // array:1["APP_ENV" => "dev"]
So what am I missing?
I m not using symfony but i've encountered the some problem
i am using the vlucas library this is my first code that caused the problem
define('BASE_PATH',realpath(__DIR__.'/../../'));
require_once __DIR__.'/../../vendor/autoload.php';
$dotEnv = Dotenv\Dotenv::createImmutable(BASE_PATH);
$dotEnv->load();
$appName=$_ENV['APP_NAME'];
$appName2=getenv('APP_NAME');
var_dump($appName) // return "This is my website";
var_dump($appName2) // return false;
i didn't knwo the problem at first but it seems that it was because putenv() and getenv()
are not thread safe
so i changed it to this code
define('BASE_PATH',realpath(__DIR__.'/../../'));
require_once __DIR__.'/../../vendor/autoload.php';
$dotEnv = Dotenv\Dotenv::createUnsafeImmutable(BASE_PATH);// <======== :) look here
$dotEnv->load();
$appName=$_ENV['APP_NAME'];
$appName2=getenv('APP_NAME');
var_dump($appName) // return "This is my website";
var_dump($appName2) // return "This is my website";
i hope this resolves your issue
For Symfony 5.x+, in public/index.php
replace
(new Dotenv())->bootEnv(dirname(__DIR__).'/.env');
with
(new Dotenv())->usePutenv()->bootEnv(dirname(__DIR__).'/.env');
This worked for me.
By default, Symfony doesn't use putenv() (I think it's for security reasons, don't remember exactly) so you are not able to use directly getenv() if you are using Symfony's "fake" environment variables.
The best solution in my opinion is to use dependency injection instead. You can access env vars in your Symfony configuration. For example with a yaml configuration file:
framework:
secret: '%env(APP_SECRET)%'
If you want to be able to use getenv() anyway, that I don't recommand for multiple reasons, you can do this :
Before Symfony 5.1 : In your config/bootstrap.php file -> new Dotenv(true)
Symfony 5.1 and later : public/index.php, add the following before Dotenv instantation-> Dotenv::usePutenv();
EDIT :
Using the putenv PHP function is not thread safe, that's why this setting defaults to false.
Didn't notice in the first place your using the Dotenv component as a standalone library, so you can ignore my advice concerning the dependency injection.
The reason is that using getenv() and putenv() is strongly discouraged due to the fact that these functions are not thread safe, however it is still possible to instruct PHP dotenv to use these functions. Instead of calling Dotenv::createImmutable, one can call Dotenv::createUnsafeImmutable, which will add the PutenvAdapter behind the scenes. Your environment variables will now be available using the getenv method, as well as the super-globals:
$s3_bucket = getenv('S3_BUCKET');
$s3_bucket = $_ENV['S3_BUCKET'];
$s3_bucket = $_SERVER['S3_BUCKET'];
Related
I get results from a jQuery Survey in JSON within my Typo3 Extension. Now I want to send these results with the Typo3 Mail API to my Inbox. According to the documentations following shoud do the work
$mail = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Mail\MailMessage::class);
$mail->from(new \Symfony\Component\Mime\Address('john.doe#example.org', 'John Doe'));
$mail->to(
new \Symfony\Component\Mime\Address('receiver#example.com', 'Max Mustermann'),
new \Symfony\Component\Mime\Address('other#example.net')
);
$mail->subject('Your subject');
$mail->text('Here is the message itself');
$mail->html('<p>Here is the message itself</p>');
$mail->attachFromPath('/path/to/my-document.pdf');
$mail->send();
so my code looks like this:
namespace TYPO3\CMS\Core\Mail;
if (!file_exists( dirname(__DIR__, 2).'/vendor/autoload.php' )) {
throw new \RuntimeException(
'Could not find vendor/autoload.php, make sure you ran composer.'
);
} else {
require dirname(__DIR__, 2).'/vendor/autoload.php';
}
use Symfony\Component\Mime\Address;
use Symfony\Component\Mime\Email;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\MailUtility;
$mail = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Mail\MailMessage::class);
$mail->from(new \Symfony\Component\Mime\Address('john.doe#example.org', 'John Doe'));
$mail->to(
new \Symfony\Component\Mime\Address('receiver#example.com', 'Max Mustermann'),
new \Symfony\Component\Mime\Address('other#example.net')
);
$mail->subject('Your subject');
$mail->text('Here is the message itself');
$mail->html('<p>Here is the message itself</p>');
$mail->attachFromPath('/path/to/my-document.pdf');
$mail->send();
I just getting errors. Does anyone know how i can achieve this?
Following error i get
Notice: Undefined index: TYPO3_CONF_VARS in /var/www/html/local_packages/ext_sitepackage/public/typo3/sysext/core/Classes/Mail/Mailer.php on line 170
Apparently this is the same question as you already posted here.
This will never work like this. You need to either build a fully fledged TYPO3 extension or a standalone application using symfony/mailer directly.
Your script is missing $GLOBALS['TYPO3_CONF_VARS']['MAIL'].
You stumble over the fact that you're programming past the conventions and requirements of TYPO3, but then you're surprised that the framework's functions don't work...
Create a middleware in your sitepackage, and register it correctly. Check for a special route and let the rest run. If handling, use the code there.
You need to run the mailing code in a (full) bootstrapped Typo3 context:
in a middleware
extbase plugin registered with pageNum directly
Your pasted code looks weired in a lot of ways. Just putting a file in a extension folder do not mean that is correctly a typo3 extension.
Maybe you want to start and have a proper extension setup first, with the corresponding readings:
ext_emconf.php / composer.json as a minimum
code files in 'Classes/' subfolders
then decide with which way you want to handle the "ajax" call and send the email, there are several possibilities (as already mentioned above) .. than read and implement that solution the proper and correct way.
Just having a php file directly referenced/called and just bootstpping the composer autoloader do not and never will be bootstrapping Typo3 with all needed configuration bootstrapping (gathering confings from extensions, Local/AdditionalConfiguration, siteconfig and and and).
And generally a package/extension should have a namespace something like following (as a convention):
<extensionname.....
an thus registered as psr-4 autoloading in your extension composer.json ..
Starting to implement the peaces to simulate a Typo3 bootstpraping in that file is not good and will make a lot of headache ... it's easier to have a proper sitepacke/extension structure.
I have a PHP library on packagist.org, which uses some constants, changing from project to project.
I'm trying to use constants like that:
Constants stores in conf.php in composer libriary
After composer init username/mylib command, I making a copy from /vendor/username/mylib/conf.php to local /conf.php and use it for current project config
for project1, in /conf.php
define("HOST", "host1.com");
project2, in /conf.php
define("HOST", "host2.com");
But it looks like a wrong way.
What is right way to use constants with composer libraries ?
I prefer to do this a slightly different way
in my libabry i would have
/vendor/vendorname/pkg/config/system.php
/vendor/vendorname/pkg/config/local.sample.php
and provide instructions to copy
/vendor/vendorname/pkg/config/local.sample.php
to
/config/local.php
then in my code I would have something like
$sysconffile = static::$vendorbasedir . '/config/system.php';
if (file_exists($sysconffile)) {
$sysconf = require $sysconffile;
} else {
throw new \RuntimeException('Sys Conf Missing!');
}
$localconf = [];
$localconfile = static::$appbasedir . '/config/local.php';
if (file_exists($localconfile)) {
$localconf = require $localconfile;
}
UPDATE:
I also prefer static classes with data over defines, as a define is very loose in documentation, type hinting and over-writable ..
So once i have both config's, I usually do
static::$config = array_replace_recursive($sysconf, $localconf);
i'm want to creating a design pattern and use the "Blade templating engine".
Can I use the Blade templating engine outside of Laravel and use it in my new pattern ?
For the record:
I tested many libraries to run blade outside Laravel (that i don't use) and most are poor hacks of the original library that simply copied and pasted the code and removed some dependencies yet it retains a lot of dependencies of Laravel.
So I created (for a project) an alternative for blade that its free (MIT license, i.e. close source/private code is OK) in a single file and without a single dependency of an external library. You could download the class and start using it, or you could install via composer.
https://github.com/EFTEC/BladeOne
https://packagist.org/packages/eftec/bladeone
It's 100% compatible without the Laravel's own features (extensions).
How it works:
<?php
include "lib/BladeOne/BladeOne.php";
use eftec\bladeone;
$views = __DIR__ . '/views'; // folder where is located the templates
$compiledFolder = __DIR__ . '/compiled';
$blade=new bladeone\BladeOne($views,$compiledFolder);
echo $blade->run("Test.hello", ["name" => "hola mundo"]);
?>
Another alternative is to use twig but I tested it and I don't like it. I like the syntax of Laravel that its close to ASP.NET MVC Razor.
Edit: To this date (July 2018), it's practically the only template system that supports the new features of Blade 5.6 without Laravel. ;-)
You certainly can, there are lots of standalone blade options on packagist, as long as you are comfortable with composer then there should be no issue, this one looks pretty interesting due to having a really high percentage of stars compared to downloads.
Be warned though i have not tried it myself, like you i was looking for a standalone option for my own project and came across it, i will be giving it a real good workout though at sometime in the near future,
Matt Stauffer has created a whole repository showing you how you can use various Illuminate components directly outside of Laravel. I would recommend following his example and looking at his source code.
https://github.com/mattstauffer/Torch
Here is the index.php of using Laravel Views outside of Laravel
https://github.com/mattstauffer/Torch/blob/master/components/view/index.php
You can write a custom wrapper around it so that you can call it like Laravel
use Illuminate\Container\Container;
use Illuminate\Events\Dispatcher;
use Illuminate\Filesystem\Filesystem;
use Illuminate\View\Compilers\BladeCompiler;
use Illuminate\View\Engines\CompilerEngine;
use Illuminate\View\Engines\EngineResolver;
use Illuminate\View\Engines\PhpEngine;
use Illuminate\View\Factory;
use Illuminate\View\FileViewFinder;
function view($viewName, $templateData)
{
// Configuration
// Note that you can set several directories where your templates are located
$pathsToTemplates = [__DIR__ . '/templates'];
$pathToCompiledTemplates = __DIR__ . '/compiled';
// Dependencies
$filesystem = new Filesystem;
$eventDispatcher = new Dispatcher(new Container);
// Create View Factory capable of rendering PHP and Blade templates
$viewResolver = new EngineResolver;
$bladeCompiler = new BladeCompiler($filesystem, $pathToCompiledTemplates);
$viewResolver->register('blade', function () use ($bladeCompiler) {
return new CompilerEngine($bladeCompiler);
});
$viewResolver->register('php', function () {
return new PhpEngine;
});
$viewFinder = new FileViewFinder($filesystem, $pathsToTemplates);
$viewFactory = new Factory($viewResolver, $viewFinder, $eventDispatcher);
// Render template
return $viewFactory->make($viewName, $templateData)->render();
}
You can then call this using the following
view('view.name', ['title' => 'Title', 'text' => 'This is text']);
Yes you can use it where ever you like. Just install one of the the many packages available on composer for it.
If you're interested in integrating it with codeigniter I have a blog post here outlining the process.
Following the above steps should make it obvious how to include it into any framework.
I use error_log for my logging, but I'm realizing that there must be a more idiomatic way to log application progress. is there an info_log ? or equivalent ?
You can use error_log to append to a specified file.
error_log($myMessage, 3, 'my/file/path/log.txt');
Note that you need to have the 3 (message type) in order to append to the given file.
You can create a function early on in your script to wrap this functionality:
function log_message($message) {
error_log($message, 3, 'my/file/path/log.txt');
}
The equivalent is syslog() with the LOG_INFO constant:
syslog(LOG_INFO, 'Message');
If you want to use a file (not a good idea because there is no log rotation and it can fail because of concurrency), you can do:
file_put_contents($filename, 'INFO Message', FILE_APPEND);
I would recommend you to use Monolog:
https://github.com/Seldaek/monolog
You can add the dependency by composer:
composer require monolog/monolog
Then you can initialize a file streaming log, for an app called your-app-name, into the file path/to/your.log, as follow:
<?php
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
// create a log channel
$log = new Logger('your-app-name');
$log->pushHandler(new StreamHandler('path/to/your.log', Logger::WARNING));
Monolog is very powerful, you can implement many types of handlers, formatters, and processors. It worth having a look:
https://github.com/Seldaek/monolog/blob/master/doc/02-handlers-formatters-processors.md
And finally call it like:
// add records to the log
$log->warning('Foo');
$log->error('Bar');
In order to make it global, I recommend you to add it to your dependency injector, if you have one, or use a singleton with static calls.
Let me know if you want more details about this.
Using Amazon MWS code config.ini.php to set up classes for MarketplaceWebServices.
This used autoload defintions to create variables using new.
As we are using different authorization credentials for different Amazon sites I have needed to change the details beteen sites.
The use of UNSET()
unset($service);
before
$service = new MarketplaceWebService_Client(
$AWS_ACCESS_KEY_ID,
$AWS_SECRET_ACCESS_KEY,
$config,
APPLICATION_NAME,
APPLICATION_VERSION
);
results in $service not being an object on being called the second time.
Which brings me to the question "Is UNSET() compatible with autoload ?"
unset() has nothing to do with autoloading, and will not interfer with it. Once the class is loaded using an autoloader, unset()ing an instance will not cause it to not be available any longer.
If that were the case, you'd get an error about MarketplaceWebService_Client not being an avaliable class.
Is UNSET() compatible with autoload ?
Yes. (Simple question, simple answer.)
Running the following demonstrates that unset should work OK with autoload.
The test class didn't use __contruct().
So it looks like something in MarketplaceWebService_Client MWS is upsetting the apple cart.
$shipping_calc = new shipping_calc();
echo "ORIG \$shipping_calc=" . print_r($shipping_calc, true);
unset($shipping_calc);
echo "UNSET() \$shipping_calc=" . print_r($shipping_calc, true);
$shipping_calc = new shipping_calc();
echo "NEW \$shipping_calc=" . print_r($shipping_calc, true);