I've tried to deploy my laravel based projec to gae, but I'm getting a blank screen and this in the error logs
PHP Fatal error: Uncaught exception 'ErrorException' with message 'file_get_contents(/base/data/home/apps/s~random-gae-name/1.380824294377640683/vendor/laravel/framework/src/Illuminate/Exception/resources/plain.html): failed to open stream: No such file or directory' in /base/data/home/apps/s~random-gae-name/1.380824294377640683/vendor/laravel/framework/src/Illuminate/Exception/PlainDisplayer.php:21
Stack trace:
#0 [internal function]: Illuminate\Exception\Handler->handleError(2, 'file_get_conten...', '/base/data/home...', 21, Array)
#1 /base/data/home/apps/s~random-gae-name/1.380824294377640683/vendor/laravel/framework/src/Illuminate/Exception/PlainDisplayer.php(21): file_get_contents('/base/data/home...')
#2 /base/data/home/apps/s~random-gae-name/1.380824294377640683/bootstrap/compiled.php(9292): Illuminate\Exception\PlainDisplayer->display(Object(ErrorException))
#3 /base/data/home/apps/s~random-gae-name/1.380824294377640683/bootstrap/compiled.php(9244): Illuminate\Exception\Handler->displayException(Object( in /base/data/home/apps/s~random-gae-name/1.380824294377640683/vendor/laravel/framework/src/Illuminate/Exception/PlainDisplayer.php on line 21
I don't know what this means.
My php.ini
; enable function that are disabled by default in the App Engine PHP runtime
google_app_engine.enable_functions = "php_sapi_name, php_uname, getmypid"
; Cloud storage buckets that Laravel needs to include files from. By default
; in production the first bucket declared here will be used for app storage.
google_app_engine.allow_include_gs_buckets = "x"
allow_url_include=1
and my yaml file
application: x
module: default
version: 1
runtime: php
api_version: 1
handlers:
- url: /.*
script: public/index.php
- url: /(.*\.(ico|gif|png|jpg|css|js|html|txt|pdf|mp3|eps|svg|ttf|woff|eot))
static_files: public/\1
upload: (.*\.(ico|gif|png|jpg|css|js|html|txt|pdf|mp3|eps|svg|ttf|woff|eot))
It seems that you need to change the storage path to your bucket. App Engine apps can't write to the local file system, so you have to override Laravel's Application class method bindInstallPaths to allow the use of Google Cloud Storage as app/storage/ directory.
Use an inherited class of Illuminate\Foundation\Application and then override bindInstallPaths method.
// MyApplicationClass.php file
class MyApplicationClass extends Illuminate\Foundation\Application
{
public function bindInstallPaths(array $paths)
{
if (isset($_SERVER['APPLICATION_ID']) && !empty($_SERVER['APPLICATION_ID'])) {
if (realpath($paths['app'])) {
$this->instance('path', realpath($paths['app']));
}
elseif (file_exists($paths['app'])) {
$this->instance('path', $paths['app']);
}
else {
$this->instance('path', FALSE);
}
foreach (array_except($paths, array('app')) as $key => $value)
{
if (realpath($value)) {
$this->instance("path.{$key}", realpath($value));
}
elseif (file_exists($value)) {
$this->instance("path.{$key}", $value);
}
else {
$this->instance("path.{$key}", FALSE);
}
}
} else {
parent::{__FUNCTION__}($paths);
}
}
}
Then use this class in bootstrap/start.php instead of original one.
$app = (isset($_SERVER['APPLICATION_ID']) && !empty($_SERVER['APPLICATION_ID']))
? new MyApplicationClass
: new Illuminate\Foundation\Application;
And finally, you have to change the storage path in your paths.php file
// paths.php file
$storage_path = (isset($_SERVER['APPLICATION_ID']) && !empty($_SERVER['APPLICATION_ID']))
? "gs://" . $your_bucket_name . "/storage"
: __DIR__.'/../app/storage';
mkdir($storage_path);
return array (
...
'storage' => $storage_path,
);
I hope it works fine for you.
Related
This is a problem that drove me crazy for over one week. I installed php-di via composer and added my own project to the composer.json file:
{
"name": "mypackage/platform",
"description": "MyPackage Platform",
"type": "project",
"require": {
"php-di/php-di": "^6.0"
},
"autoload": {
"psr-4": {
"MyPackage\\": "src/"
}
}
}
Then I created mine /public/index.php:
<?php
require_once dirname(__DIR__) . '/vendor/autoload.php';
use DI\ContainerBuilder;
use function DI\create;
use MyPackage\Base\Service;
$containerBuilder = new ContainerBuilder();
$containerBuilder->useAutowiring(false);
$containerBuilder->useAnnotations(false);
$containerBuilder->addDefinitions([
Service::class => create(Service::class)
]);
$container = $containerBuilder->build();
$service = $container->get('Service');
$service->showMessage();
And this is /src/Base/Service.php content:
<?php
namespace MyPackage\Base;
class Service
{
public function __construct()
{
}
public function showMessage()
{
echo "<BR>Inside Service";
}
}
When I troy to load index.php, Apache says:
[Thu Dec 05 18:57:47 2019] [error] PHP Fatal error: Uncaught DI\\NotFoundException: No entry or class found for 'Service' in /var/www/html/vendor/php-di/php-di/src/Container.php:135
Stack trace:
#0 /var/www/html/public/index.php(22): DI\\Container->get('Service')
#1 {main}
thrown in /var/www/html/vendor/php-di/php-di/src/Container.php on line 135
Whats is wrong with my approach?
$container->get('Service') asks the container for the entry 'Service'. This is a string. There is no namespace.
In your configuration, you configured the service under the Service::class key: Service::class returns the full class name, which is MyPackage\Base\Service.
So the error is: you have the service under MyPackage\Base\Service, and you try to fetch it via the key Service.
Symfony 4 app with Braintree JS drop-in UI
I have created a service called Braintree to start testing.
namespace App\Services;
use Braintree\ClientToken;
class Braintree
{
// environment variables:
const ENVIRONMENT = 'BRAINTREE_ENVIRONMENT';
const MERCHANT_ID = 'BRAINTREE_MERCHANT_ID';
const PUBLIC_KEY = 'BRAINTREE_PUBLIC_KEY';
const PRIVATE_KEY = 'BRAINTREE_PRIVATE_KEY';
/** #var \Braintree_Gateway */
private $gateway;
function __construct() {
$gateway = new \Braintree_Gateway([
'environment' => getenv(self::ENVIRONMENT),
'merchantId' => getenv(self::MERCHANT_ID),
'publicKey' => getenv(self::PUBLIC_KEY),
'privateKey' => getenv(self::PRIVATE_KEY)
]);
}
public function generate() {
return ClientToken::generate();
}
I am getting the following error:
HTTP 500 Internal Server Error
Braintree\Configuration::merchantId needs to be set (or accessToken needs to be passed to Braintree\Gateway).
The BT config has been properly entered into the .env file. Why is it not setting the MERCHANT_ID?
Edit:
Add config
Braintree_Gateway:
class: Braintree_Gateway
arguments:
-
'environment': '%env(BRAINTREE_ENVIRONMENT)%'
'merchantId': '%env(BRAINTREE_MERCHANT_ID)%'
'publicKey': '%env(BRAINTREE_PUBLIC_KEY)%'
'privateKey': '%env(BRAINTREE_PRIVATE_KEY)%'
Edit 2:
The stack trace:
Braintree\Exception\
Configuration
in vendor\braintree\braintree_php\lib\Braintree\Configuration.php (line 261)
public function assertHasAccessTokenOrKeys() { if (empty($this->_accessToken)) { if (empty($this->_merchantId)) { throw new Exception\Configuration('Braintree\\Configuration::merchantId needs to be set (or accessToken needs to be passed to Braintree\\Gateway).'); } else if (empty($this->_environment)) { throw new Exception\Configuration('Braintree\\Configuration::environment needs to be set.'); } else if (empty($this->_publicKey)) { throw new Exception\Configuration('Braintree\\Configuration::publicKey needs to be set.'); } else if (empty($this->_privateKey)) {
Configuration->assertHasAccessTokenOrKeys()
in vendor\braintree\braintree_php\lib\Braintree\ClientTokenGateway.php (line 34)
ClientTokenGateway->__construct(object(Gateway))
in vendor\braintree\braintree_php\lib\Braintree\Gateway.php (line 59)
Gateway->clientToken()
in vendor\braintree\braintree_php\lib\Braintree\ClientToken.php (line 18)
ClientToken::generate()
in src\Services\Braintree.php (line 25)
Braintree->generate()
in src\Controller\ProfileController.php (line 50)
ProfileController->booking_new(object(EntityManager), object(Request), object(Braintree))
in vendor\symfony\http-kernel\HttpKernel.php (line 149)
Edit 3:
namespace App\Services;
use Braintree_Gateway;
class Braintree extends Braintree_Gateway
{
//Configure Braintree Environment
public function __construct(Braintree_Gateway $gateway)
{
$this->$gateway = new Braintree_Gateway([
'environment' => 'sandbox',
'merchantId' => 'n5z3tjxh8zd6272k',
'publicKey' => 'v4rjdzqk3gykw4kv',
'privateKey' => '4ab8b962e81ee8c43bf6fa837cecfb97'
]);
}
//Generate a client token
public function generate() {
return $clientToken = $this->clientToken()->generate();
}
}
Error is now:
Catchable Fatal Error: Object of class Braintree\Gateway could not be converted to string
Am I getting closer to generating the client token??
The .env-file does not actually populate the system environment. Instead it works as a fallback when the environment is not set. Your call to getenv() only takes into account the system environment. For your file to take effect you have to use the Service container.
#config/services.yaml
services:
_defaults:
autowire: true
autoconfigure: true
#... all the existing services
Braintree_Gateway:
class: Braintree_Gateway
arguments:
-
'environment': '%env(BRAINTREE_ENVIRONMENT)%'
'merchantId': '%env(BRAINTREE_MERCHANT_ID)%'
'publicKey': '%env(BRAINTREE_PUBLIC_KEY)%'
'privateKey': '%env(BRAINTREE_PRIVATE_KEY)%'
The special parameter %env()% will check your system environment for the variable first and if that is not set it will go through the .env files to see if there is a fallback defined. You can also read up on this in the docs: https://symfony.com/doc/current/configuration/external_parameters.html#environment-variables
This will give the service Braintree_Gateway, that you built manually inside your service. Just like with any other service you can inject it into your service instead and autowiring will pass in an already generated Braintree Gateway:
namespace App\Services;
use Braintree\ClientToken;
class Braintree
{
private $gateway;
public function __construct(\Braintree_Gateway $gateway)
{
$this->gateway = $gateway;
}
# ... methods using the gateway
}
I haven't quite got my head around namespaces in PHP yet. Nor do I use composer or autoloaders. I understand them, but often have difficulty including them into my own projects.
So I would like to include a package in a Wordpress plugin I am developing, specifically this one https://github.com/elliotboney/thinkific-php
I can include the main file OK, but get the error below when calling a function within that file. I am not sure if its to do with the fact its using namespaces, or just because its trying to include files in the Api sub folder which wont be the correct path once I include the main file into my own code.
Does anyone know how I can include this package to use it it within my own project?
require_once('Thinkific/Thinkific.php');
$think = new \Thinkific\Thinkific([
'apikey' => 'xxxxxxxxx',
'subdomain' => 'yyyyyyyyy',
'debug' => true
]);
$users = $think->users();
$users = $users->getAll();
But this is the error, which shows that the class files and so classes in the Api sub-folder are not loaded.
Fatal error: Uncaught Error: Class '\Thinkific\Api\Users' not found in Fatal error: Uncaught Error: Class '\Thinkific\Api\Users' not found in /mysite/public_html/wp-content/plugins/thinkific/Thinkific/Thinkific.php:51 Stack trace: #0 /mysite/public_html/wp-content/plugins/thinkific/Thinkific/Thinkific.php(36): Thinkific\Thinkific->getApi('\\Thinkific\\Api\\...') #1 /mysite/public_html/wp-content/plugins/thinkific/thinkific.php(50): Thinkific\Thinkific->__call('users', Array) #2 /mysite/public_html/wp-content/plugins/thinkific/thinkific.php(29): Thinkific::thinkific_get_users() #3 /mysite/public_html/wp-includes/class-wp-hook.php(298): thinkific_woocommerce_order_status_completed(Object(WP)) #4 /mysite/public_html/wp-includes/class-wp-hook.php(323): WP_Hook->apply_filters('', Array) #5 /mysite/public_html/wp-includes/plugin.php(515): WP_Hook->do_action(Array) #6 /mysite/public_html/wp-includes/class-wp.php(746): do_action_ref_array('wp in /mysite/public_html/wp-content/plugins/thinkific/Thinkific/Thinkific.php on line 51
Try something like this:
lib.php:
<?php
// Application library 1
namespace App\Lib1;
const MYCONST = 'Hello,';
// Application library 1
namespace App\Lib2;
const MYCONST = 'How are you?';
function MyFunction() {
return __FUNCTION__;
}
class MyClass {
static function WhoAmI() {
return __METHOD__;
}
}
?>
myapp.php:
<?php
require_once('lib.php');
echo App\Lib1\MYCONST . "\n";
echo App\Lib2\MYCONST . "\n\n";
echo App\Lib2\MyFunction() . "\n";
echo App\Lib2\MyClass::WhoAmI() . "\n";
?>
The library which you are using is dependent on composer, the place where you doing composer install there it will generate a vendor/autoload.php, you just need to generate vendor/autoload.php here this file will take care of your autoloading of classes.
require_once 'vendor/autoload.php';
$think = new \Thinkific\Thinkific([
'apikey' => 'xxxxxxxxx',
'subdomain' => 'yyyyyyyyy',
'debug' => true
]);
$users = $think->users();
$users = $users->getAll();
So I have an App\bindings.php file that I have added to my composer.json file as so:
"autoload": {
"files": [
"app/bindings.php"
]
},
In this file I am trying to set up bindings for my repositories like so:
<?php
function getRepoBinding($id)
{
$repo = "{$id}Repository";
$clientName = strtoupper(config('client.name'));
$implementation = config('app.repo_implementation', 'Eloquent');
$clientOverride = "App\Overrides\\{$clientName}\Repositories\\{$implementation}\\{$repo}";
$repo = class_exists($clientOverride) ? $clientOverride : "App\Repositories\\{$implementation}\\{$repo}";
return $repo;
}
// Repository Interface Bindings
dd(getRepoBinding('Contribution'));
App::bind('ContributionIneterface', getRepoBinding('Contribution'));
However, i run a composer dump-auto and try to run my application and I get the following error:
Fatal error: Uncaught Error: Call to a member function make() on null in /home/vagrant/Code/famsapi/vendor/laravel/framework/src/Illuminate/Foundation/helpers.php:54
Stack trace: #0 /home/vagrant/Code/famsapi/vendor/laravel/framework/src/Illuminate/Foundation/helpers.php(158): app('config')
#1 /home/vagrant/Code/famsapi/app/bindings.php(9): config('client.name')
#2 /home/vagrant/Code/famsapi/app/bindings.php(16): App\getRepoBinding('Contribution')
#3 /home/vagrant/Code/famsapi/vendor/composer/autoload_real.php(55): require('/home/vagrant/C...')
#4 /home/vagrant/Code/famsapi/vendor/composer/autoload_real.php(45): composerRequire03fe235c8b3156f0c5fcebbc0d696734('90f93262f3a0ac8...', '/home/vagrant/C...')
#5 /home/vagrant/Code/famsapi/vendor/autoload.php(7): ComposerAutoloaderInit03fe235c8b3156f0c5fcebbc0d696734::getLoader()
#6 /home/vagrant/Code/famsapi/bootstrap/autoload.php(17): require('/home/vagrant/C...')
#7 /home/vagrant/Code/famsapi/public/index.php(22): require('/home/vagrant/C...')
#8 {main} thrown in /home/vagrant/Code/famsapi/vendor/laravel/framework/src/Illuminate/Foundation/helpers.php on line 54
It seems like it is having with the global config helper method...but im not sure how to fix that. Better yet, if you have an idea of how I can do this another way I am all ears.
It is because you are loading that file before the application starts.
Use it inside your AppServiceProvider
I'm using Zend Framework 2 and trying to create console command for filling db config
php public/index.php env install stable --dbu=root --dbp=root --dbn=panel100
PHP Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[28000] [1045] Access denied for user 'username'#'localhost' (using password: YES)' in /home/seyfer/www/site.loc/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOConnection.php:43
Stack trace:
#0 /home/seyfer/www/site.loc/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOConnection.php(43): PDO->__construct('mysql:host=loca...', 'username', 'password', Array)
#1 /home/seyfer/www/site.loc/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOMySql/Driver.php(45): Doctrine\DBAL\Driver\PDOConnection->__construct('mysql:host=loca...', 'username', 'password', Array)
#2 /home/seyfer/www/site.loc/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php(360): Doctrine\DBAL\Driver\PDOMySql\Driver->connect(Array, 'username', 'password', Array)
#3 /home/seyfer/www/site.loc/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php(429): Doctrine\DBAL\Connection->connect()
#4 /home/seyfer/www/site.loc/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php(3 in /home/seyfer/www/site.loc/vendor/zendframework/zend-servicemanager/src/ServiceManager.php on line 946
So no I have chicken and egg problem. Command fails because there is no DB config, but command should create this config.
How to not initialize services when call this command?
My controller code is
use Zend\Mvc\Controller\AbstractActionController;
use ZendMover\Copier;
class EnvController extends AbstractActionController
{
public function installAction()
{
$env = $this->getRequest()->getParam('env');
$dbu = $this->getRequest()->getParam('dbu');
$dbp = $this->getRequest()->getParam('dbp');
$dbn = $this->getRequest()->getParam('dbn');
try {
$environment = new Environment($env, new Copier());
$result = $environment->installEnv($env, $dbu, $dbp, $dbn);
return $result ? "Success\n" : '';
} catch (\Exception $e) {
echo $e->getMessage() . "\n";
}
}
}
I was solved it with Symfony Console component.
But how to solve it using Zend Console?