Deploying a Symfony App to Google App Engine - php

I’ve read the documentation on https://cloud.google.com/appengine/docs/php/symfony-hello-world and I managed to deploy the Hello World app, but when I try with my symfony app I have his error:
InvalidArgumentException in XmlFileLoader.php line 259: Unable to parse file "(…) DependencyInjection/../Resources/config\web.xml".
In app.yaml I set the env variables:
env_variables:
GCS_BUCKET_NAME: "pinterpandaibucket"
CACHE_DIR: "gs://pinterpandaibucket/symfony/cache"
LOG_DIR: "gs://pinterpandaibucket/symfony/log"
And I overloaded the AppKernel.php functions:
public function __construct($environment = null, $debug = null)
{
// determine the environment / debug configuration based on whether or not this is running
// in App Engine's Dev App Server, or in production
if (is_null($debug)) {
$debug = !Environment::onAppEngine();
}
if (is_null($environment)) {
$environment = $debug ? 'dev' : 'prod';
}
parent::__construct($environment, $debug);
// Symfony console requires timezone to be set manually.
if (!ini_get('date.timezone')) {
date_default_timezone_set('UTC');
}
// Enable optimistic caching for GCS.
$options = ['gs' => ['enable_optimsitic_cache' => true]];
stream_context_set_default($options);
$this->gcsBucketName = getenv('GCS_BUCKET_NAME');
...
public function getCacheDir()
{
if ($this->gcsBucketName) {
return getenv('CACHE_DIR');
}
return parent::getCacheDir();
}
public function getLogDir()
{
if ($this->gcsBucketName) {
return getenv('LOG_DIR');
}
return parent::getLogDir();
}
public function registerContainerConfiguration(LoaderInterface $loader)
{
$loader->load($this->getRootDir().'/config/config_'.$this->getEnvironment().'.yml');
}
}
?>
The functions which write to the file system are redirected to the bucket.
Could you help me to find what modifications are missing in my app.
I hope this topic will help someone else because the Google cloud documentation isn't very up to date.
Thank you in advance and sorry if I don’t speak English very well I’m a French IT student.
Augustin

I have spent many an hours on this horrible bug, and what I found was this issue happens on the Dev AppServer, but not in production. I believe it is an issue with the implementation of the xml.so php extension in that environment.
This is fixed in the symfony starter app with the method fixXmlFileLoaderBug, which gets called in web/app.php. So ensure this is being called, and you should be good to go.
If you're experiencing this bug in Production, or you continue to experience this issue even after calling this function, please let us know by filing an issue on github.

Related

Setting up Yii2 project in localy system in Window XAMPP getting error

I'm setting up Yii2 project in locally system in window XAMPP and I'm getting an error:
Declaration of common\components\Request::validateCsrfToken() should
be compatible with
yii\web\Request::validateCsrfToken($clientSuppliedToken = NULL)
But the code is working fine on Ubuntu server.
Here is my validateCsrfToken() method:
public function validateCsrfToken()
{
if($this->enableCsrfValidation && in_array(Yii::$app->getUrlManager()->parseRequest($this)[0], $this->noCsrfRoutes)){
return true;
}
return parent::validateCsrfToken();
}
This issue is because you are using strict PHP in Windows, but not in Linux. You own function common\components\Request::validateCsrfToken() should be compatible with yii\web\Request::validateCsrfToken(). This means, it needs to have the same signature.
What you can do at the moment is to change your own function to
public function validateCsrfToken($token = NULL) {
if ($this->enableCsrfValidation && in_array(Yii::$app->getUrlManager()->parseRequest($this)[0], $this->noCsrfRoutes)) {
return true;
}
return parent::validateCsrfToken($token);
}
You need to do this every time you are rewriting one of those functions (i.e. beforeAction, afterAction, beforeSave and many more...)

Laravel: multiple log providers using `configureMonologUsing()`?

I'm using configureMonologUsing() to add in two custom loggers. Doing the standard SOLID principal, I have two providers: ConsoleLoggerProvider and MailLogProvider.
Both of these have a register similar to:
public function register()
{
app()->configureMonologUsing(function(\Monolog\Logger $monolog) {
$monolog->pushHandler(new HandlerClass());
});
}
However, I have noticed over logger will overwrite another logger... How do I stack these?
I've tried to use boot() as well, and that didn't work. I couldn't find any other way to add to the Monolog stack.
Preferable, I want to stack onto Laravel's built-in logger as well.
I (finally) found the answer my question:
Within my providers, instead of using configureMonologUsing(), I used Log::getMonolog()->pushHandler([..])
That works! All loggers, including built-in Laravel file logger, are firing. Finally!
(I've honestly been looking for days for a way to add onto the Monolog stack; I apparently wasn't searching by the right terms)
According to the Laravel documentation:
You should place a call to the configureMonologUsing method in your bootstrap/app.php file right before the $app variable is returned by the file.
In that case, thus should work for you: create two handler classes and add them to monolog this way (in your bootstrap/app.php):
$app->configureMonologUsing(function ($monolog) {
$monolog->pushHandler(new EmailLogHandler);
$monolog->pushHandler(new ConsoleLogHandler);
});
return $app;
Following Laravel 5.2 docs, in bootstrap/app.php, I added the following code right before return $app;:
$app->configureMonologUsing(function($monolog) {//IMPORTANT: I think the order of pushHandler matters, and the ones defined last here will be the first to be called, which affects anything where bubble=false
if (config('services.slack.send_errors_to_slack')) {
$bubble = false; //I think that if I set the 'bubble' argument to false and handle the most severe logging levels first (which counterintuitively means lower in this function), less severe logging levels don't bother reporting the same message.
$useShortAttachment = false;
$includeContextAndExtra = true; //This is important because otherwise 404 errors wouldn't report the URL, give how 'report' function is coded within App\Exceptions\Handler.php.
$handlerForWarningsToNotifyPhone = new \Monolog\Handler\SlackHandler(config('services.slack.token'), config('services.slack.channel_warnings'), 'Monolog', true, null, \Monolog\Logger::WARNING, $bubble, $useShortAttachment, $includeContextAndExtra);
$monolog->pushHandler($handlerForWarningsToNotifyPhone);
$handlerForErrorsToNotifyPhone = new \Monolog\Handler\SlackHandler(config('services.slack.token'), config('services.slack.channel_errors'), 'Monolog', true, null, \Monolog\Logger::ERROR, $bubble, $useShortAttachment, $includeContextAndExtra);
$monolog->pushHandler($handlerForErrorsToNotifyPhone);
}
if (config('app.send_logs_to_loggy')) {
$logglyHandler = new \Monolog\Handler\LogglyHandler(config('services.loggly.token'), config('app.send_logs_to_loggy')); //See \Monolog\Logger::INFO. Log level 200 is "info".
$logglyHandler->setTag(config('services.loggly.tag'));
$monolog->pushHandler($logglyHandler);
}
if (config('app.log_to_local_disk')) {
$localHandler = new \Monolog\Handler\StreamHandler(storage_path("/logs/laravel.log"));
$monolog->pushHandler($localHandler);
}
});
It's just an example that may help you.
Be sure to edit your config files accordingly (e.g. so that app.log_to_local_disk, services.slack.send_errors_to_slack, etc are available).
http://stackoverflow.com/a/36259944/470749 was helpful.
Here is how I able to configure on Laravel Lumen v5.4
in app.php:
$publisher = new \Gelf\Publisher(new \Gelf\Transport\HttpTransport(env('GRAYLOG_HOST'), env('GRAYLOG_PORT'), env('GRAYLOG_PATH')));
//WhatFailureGroupHandler does not break app execution
//if some exceptions happen happens while logging
$failureHandler = new \Monolog\Handler\WhatFailureGroupHandler([
new \Monolog\Handler\GelfHandler($publisher)
]);
\Log::pushHandler($failureHandler);
\Log::getMonolog() as on accepted answer threw error.
Also tried to configure using $app->configureMonologUsing() which threw A facade root has not been set. error. But at the end, I found out that was because we need to return logger:
$app->configureMonologUsing(function ($monolog) {
$publisher = new \Gelf\Publisher(new \Gelf\Transport\HttpTransport(env('GRAYLOG_HOST'), env('GRAYLOG_PORT'), env('GRAYLOG_PATH')));
$failureHandler = new \Monolog\Handler\WhatFailureGroupHandler([new \Monolog\Handler\GelfHandler($publisher)]);
$monolog->pushHandler($failureHandler);
//fixes error: A facade root has not been set
return $monolog;
});
All the examples of $app->configureMonologUsing() usage I have seen do not have a return statement, even in the other answers, which did not work for me.

Using MongoDb in the PHP Phalcon framework

I am currently experimenting with the Phalcon Framework, and running into some complications when I attempt to save content into the Mongo Database. I can correctly setup the MySQL database without issues. Whenever I send the simple request through I get a 500 Internal server error (checking devTools). I have setup everything accordingly as the documentation specifies.
This is my simple index.php bootstrap Mongo initialisation along with the collection manager:
// Setting Mongo Connection
$di->set('mongo', function() {
$mongo = new Mongo();
return $mongo->selectDb("phalcon");
}, true);
// Setting up the collection Manager
$di->set('collectionManager', function(){
return new Phalcon\Mvc\Collection\Manager();
}, true);
This is my controller handling the request:
public function createAction() {
$user = new User();
$user->firstname = "Test ACC";
$user->lastname = "tester";
$user->password = "password";
$user->email = "testing#example.com";
if($user->create() == false) {
echo 'Failed to insert into the database' . "\n";
foreach($user->getMessages as $message) {
echo $message . "\n";
}
} else {
echo 'Happy Days, it worked';
}
}
And finally my simple User class:
class User extends \Phalcon\Mvc\Collection {
public $firstname;
public $lastname;
public $email;
public $password;
public $created_at = date('Y-m-d H:i:s');
}
Much appreciated for everyones input/suggestions.
i think it's because your installation of Mongo is not valid.
try printing phpinfo() and check if mongo is loaded at all, if not - install it, add to ini files (if you use cli, don't forget to add to cli ini too) and reach the moment, when mongo is fully loaded.
try mongo w/o phalcon. any simple connection/insertation. you can see here: Fatal Error - 'Mongo' class not found that there are problems with apache module version for some people. Try reinstalling different mongo version.
if you can print this out:
echo Phalcon\Version::get();
there should be no problems with phalcon instalation
to validate mongo installation, try any of examples from php.net:
http://www.php.net/manual/en/mongo.tutorial.php
A little bit late, but for anyone else facing this issue, it would be a good idea to try and connect to mongo (run "mongo" in your terminal) to ensure that mongo is setup correctly in your dev environment.
Also, I usually find in this sort of situation, that adding a collection to a database in mongo and then testing the CRUD process with a simple read helps move things along. If all is well at this stage, then you know your app is able to connect and you can proceed to writes, and so on.
This looks useful.

Using simplesamlphp 1.10 with cakePHP 2.3 not working

I'm trying to implement the SimpleSAMLphp authentication tool in cakePHP.
I wrote a SamlAuthenticate component in app\Controller\Component\Auth which looks like this:
class SamlAuthenticate extends Component {
[...]
public function authenticate(CakeRequest $request, CakeResponse $response) {
$source = null;
$as = null;
if ($this->Session->check('Saml.source')) {
$source = $this->Session->read('Saml.source');
}
if ($source) {
require_once($this->settings['path'] . DS . 'lib' . DS . '_autoload.php');
$as = new SimpleSAML_Auth_Simple($source);
if(!$as->isAuthenticated()) {
$as->login();
} else {
return $as->getAttributes();
}
}
return false;
}
}
But I'm always getting an loop between the identity provider and my cake application.
I was wondering, if my server is the problem or I did something wrong with the configuration of the identity provider, so I wrote a simple test script and it worked without a problem:
require_once('/../simplesamlphp/lib/_autoload.php');
$as = new SimpleSAML_Auth_Simple('facebook');
$as->requireAuth();
echo $as->isAuthenticated();
So, something in cakePHP breaks the authentication process. The SimpleSAMLAuthToken is set correctly (I can see that through the SimpleSAMLphp admin panel), but $as->isAuthenticated() always returns false.
I also tried https://github.com/bvidulich/CakePHP-simpleSAMLphp-Plugin with the same result.
maybe you are in a session conflict.
Take a look on the LostState info of the simpleSAMLphp documentation.
A fast workaround to see if that is your problem:
Configure the simplesamlphp to save the session on memcache. You will need to install a memcache server, the memcache php driver (remember to restart your apache after install ir) and then edit the config/config.php file of simpleSAMLphp and set
'store.type' => 'memcache',
Check that the simpleSAMLphp can write a session using the cookie extension of firefox. (Take a look on the session/cookie params of the config/config.php file.

SOAP Client Error: "Error Fetching Http Headers"

I am trying to use a SOAP Client-Server in my computer and it doesn't look like it is going to work, I am getting this error Error Fetching Http Headers when I try to run my SOAP Client.
I have been looking and the solution that I have encountred is to increase the default_socket_timeout from 60 to 120 seconds and it doesn't work for me, also I have seen another solution that is putting the vhost in my apache KeepAlive Off and that didn't work.
The WSDL is working fine because I try to use it in another computer and it work.
I am running PHP Version 5.3.5-1ubuntu7.4 in Linux Mint using Zend Framework, I hope some of you can help me fix this thank you.
I'm sorry but I don't know what you are using to set up your SOAP service.....
If you can give more information about your SOAP service (poss Zend_Soap given the Zend Framework tag) etc that would be great.
Also, as a quick alternative, you say you've looked at the WSDL on another computer, perhaps try the application in an alternative environment to ensure it's not an environment issue.
May be a simple issue with your client-server code.
UPDATE: Ok so I realised the example I mentioned yesterday wasn't fully implemented so I've hacked something together quickly that you can try to see if it works in your environment.
The code is a mix of something I found here (an example of Zend_Soap_Server) and something from another SO question here (an example of a basic SOAP service test).
I've tested it at my end using ZF 1.11 and the example I'm outlining uses the default Application path you get with a new ZF project (e.g models are in directory application/models so the model shown is headed up Application_Model_Classname).
If it works, you can tweak accordingly....if it doesn't work we can try something else.
Start by creating a new SOAP controller and set the class up like this:
<?php
class SoapController extends Zend_Controller_Action
{
public function init()
{
ini_set("soap.wsdl_cache_enabled", "0"); //disable WSDL caching
$this->_helper->layout()->disableLayout(); //disable the layout
$this->_helper->viewRenderer->setNoRender(); //disable the view
}
public function indexAction ()
{
if (isset($_GET['wsdl'])) {
//return the WSDL
$this->handleWSDL();
} else {
//handle SOAP request
$this->handleSOAP();
}
}
private function handleWSDL ()
{
$strategy = new Zend_Soap_Wsdl_Strategy_AnyType();
$autodiscover = new Zend_Soap_AutoDiscover();
$autodiscover->setComplexTypeStrategy($strategy);
$autodiscover->setClass('Application_Model_SoapService');
$autodiscover->handle();
}
private function handleSOAP ()
{
$server = new Zend_Soap_Server(null,
array('uri' => "http://YOURDOMAIN/soap?wsdl"));
$server->setClass("Application_Model_SoapService");
$server->handle();
}
public function testAction()
{
$client = new Zend_Soap_Client("http://YOURDOMAIN/soap?wsdl");
try {
echo $client->testMethod('test');
} catch (Exception $e) {
echo $e;
}
}
}
In the class above, the WSDL is automatically generated using Zend_Soap_Autodiscover with a SoapService.php file at application/models/SoapService.php used as the template. Note the DocBock comments above each method in your target class are integral to this process.
Next create the SoapService.php file in the default models folder:
<?php
class Application_Model_SoapService
{
/**
* testMethod
*
* #param string $string
* #return string $testSuccess
*/
public function testMethod(string $string)
{
$testSuccess = 'Test successful, the message was: ' . $string;
return $testSuccess;
}
}
If all is working as it should be you can visit:
http://YOURDOMAIN/soap?wsdl
to see the WSDL and visit:
http://YOURDOMAIN/soap/test
to get a success message with the string you specified in the client request within the testAction() code in the SoapController class as part of the message.
Let me know if it's working or not and we can go from there.
I'll be able to have another look on Monday.

Categories