I recently set up memcache for a website. However, getting memcache to work for designers and devs is always a pain. I want to switch to file caching. Can any of the other YII memory caching options beat Memcahce or at least perform more or less equivalently?
I'm considering using: http://www.yiiframework.com/doc/api/1.1/CFileCache
As mentioned, it somewhat depends if you need distributed caching and if you need the cache to be exactly the same on all environments. If you are already using a database and opening a data connection on most cases, you could use CDbCache.
I have a web application that is deployed on a few different environments and by different types of users, so I set a server environment variable to choose the cache system. Redis is the default for production (performance would be fairly similar to memcache but without the volatility) and CDbCache is the default for other environments, with the ability to choose APC if they have it or File if all else fails. In your config, you can set up something like:
if ($cache == 'redis') {
$cache_config = array(
'class' => 'packages.redis.ARedisCache');
} elseif ($cache == 'apc') {
$cache_config = array(
'class' => 'system.caching.CApcCache');
} elseif ($cache == 'file') {
$cache_config = array(
'class' => 'system.caching.CFileCache');
} else {
$cache_config = array(
'class'=>'system.caching.CDbCache',
'connectionID'=>'db'
);
}
Related
I am building a WebDAV server using sabre/dav, I want to create a WebDAV server file storage location in Wasabi which is compatible with AmazonS3, I did some research and found something that looks like AWS.php but I don't know how to use it. If anyone knows how to do this specifically, please respond.
What we tried:
・Download s3dav (https://github.com/audionamix/s3dav) and install the file.
・Server.php was written as follows
<?php
use Sabre\DAV;
use Aws\S3\S3Client;
// The autoloader
require 'vendor/autoload.php';
$raw_credentials = array(
'credentials' => array(
'key' => '<insert-access-key>',
'secret' => '<insert-secret-key>'
),
//'profile' => 'wasabi',
'endpoint' => 'https://s3.wasabisys.com',
'region' => 'us-east-1',
'version' => 'latest',
'use_path_style_endpoint' => true,
'use_path_style' => true,
'use_ssl' => true,
'port' => 443,
'hostname' => 's3.wasabisys.com',
'bucket' => '<bucket-name>',
);
// establish an S3 Client.
$s3 = S3Client::factory($raw_credentials);
// Now we're creating a whole bunch of objects
//$rootDirectory = new DAV\FS\Directory('public');
$rootDirectory = new DAV\FS\S3Directory("/",'<bucket-name>',$s3);
// The server object is responsible for making sense out of the WebDAV protocol
$server = new DAV\Server($rootDirectory);
// If your server is not on your webroot, make sure the following line has the
// correct information
$server->setBaseUri('/server.php/');
// The lock manager is reponsible for making sure users don't overwrite
// each others changes.
$lockBackend = new DAV\Locks\Backend\File('data/locks');
$lockPlugin = new DAV\Locks\Plugin($lockBackend);
$server->addPlugin($lockPlugin);
// This ensures that we get a pretty index in the browser, but it is
// optional.
$server->addPlugin(new DAV\Browser\Plugin());
// All we need to do now, is to fire up the server
$server->exec();
Result:
The file name list is displayed, but it is displayed as 0 bytes.
Uploading is working, but other operations are not working (file size is correct on Wasabi).
”4.4.0 Exception Cannot traverse an already closed generator" is displayed.
I am uses Dotenveditor to save the env parameters but after redirecting i faced error as
This site can’t be reachedThe connection was reset.
Try:
Checking the connection
Checking the proxy and the firewall
ERR_CONNECTION_RESET
what is mistake in my code? rest part of controller works properly.
if (isset($request->APP_DEBUG)) {
$env_update = DotenvEditor::setKeys(['APP_DEBUG' => 'true']);
} else {
$env_update = DotenvEditor::setKeys(['APP_DEBUG' => 'false']);
}
if (isset($request->COOKIE_CONSENT_ENABLED)) {
$env_update = DotenvEditor::setKeys(['COOKIE_CONSENT_ENABLED' => 'true']);
} else {
$env_update = DotenvEditor::setKeys(['COOKIE_CONSENT_ENABLED' => 'false']);
}
$env_update = DotenvEditor::setKeys([
'APP_NAME' => preg_replace('/\s+/', '', $request->title),
'APP_URL' => preg_replace('/\s+/', '', $request->APP_URL),
]);
$env_update->save();
Try to update your .env file using notepad++ as administrator. I Think it is much easier and user friendly. When you make the necessary changes save the file. Afterwords, I think you must reboot to the Virtual Machine (if you are using one) or restart the service in order the change takes effect to the application.
Talking about Laravel-Dotenv-Editor please try to visit Dotenv editor in order to find more information.
Example of a .env file:
I am trying to implement controller integration testing in CakePHP 3.6 using its testing tools. I assumed that this would be handled by making a 'real' (as in CURL) HTTP request against the running webserver, but it looks like it isn't. Below is the test case code I'm using.
The problems I'm running into:
The test case is somehow managing to access the controler action,
even when the webserver is not running at all (Apache down and no
dev webserver running).
When running this test, the controller does not have access to
$_SERVER (see below) and any of the $postData defined in the test case appears empty on the controller side.
When I place exit; in the controller code, the whole test case
stops, which suggests that the controller code is run directly, not
via a HTTP request.
Question: How can I make a 'real' HTTP requests when testing controllers, apart from resorting to using CURL and handling the requests manually?
Clearly, I am either not understanding how the controller testing is done, or I'm doing something wrong.
Test case I'm using:
/tests/TestCase/Controller/JobsControllerTest.php
<?php
namespace App\Test\TestCase\Controller;
use Cake\ORM\TableRegistry;
use Cake\TestSuite\IntegrationTestCase;
/**
* App\Controller\JobsController Test Case
*/
class JobsControllerTest extends IntegrationTestCase
{
/**
* Test add method
*
* #return void
*/
public function testAdd()
{
$this->useHttpServer(true);
$this->configRequest([
'headers' => [
'Content-Type' => 'application/json',
'X-Api-Key' => '8f083c8f083c8f083c8f083c'
]
]);
$postData = [
'user_id' => 3,
'job_status' => 'New'
];
$this->post('/jobs/add', $postData);
$this->assertResponseSuccess();
$jobs = TableRegistry::get('Jobs');
$query = $jobs->find()->where(['user_id' => $postData['user_id']]);
$this->assertEquals(1, $query->count());
}
}
The dump of $_SERVER global from the controller that I'm testing:
Array
(
[LS_COLORS] => rs=0:di=01;34 [...]
[LANG] => en_US.UTF-8
[HOME] => /home/tomasz
[TERM] => screen
[PATH] => /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin
[MAIL] => /var/mail/root
[LOGNAME] => root
[USER] => root
[USERNAME] => root
[SHELL] => /bin/bash
[SUDO_COMMAND] => vendor/bin/phpunit --verbose
[SUDO_USER] => tomasz
[SUDO_UID] => 1000
[SUDO_GID] => 1000
[PHP_SELF] => vendor/bin/phpunit
[SCRIPT_NAME] => vendor/bin/phpunit
[SCRIPT_FILENAME] => vendor/bin/phpunit
[PATH_TRANSLATED] => vendor/bin/phpunit
[DOCUMENT_ROOT] =>
[REQUEST_TIME_FLOAT] => 1546631688.0758
[REQUEST_TIME] => 1546631688
[argv] => Array
(
[0] => vendor/bin/phpunit
[1] => --verbose
)
[argc] => 2
)
CakePHP integration tests do not issue actual HTTP requests, they simulate them, it's very fast, allows for certain mocking, inspecting session contents, accessing exception details, etc., all sorts of things that wouldn't really be possible (at least not easily) when using real HTTP requests. If you really need to issue actual requests, then you should look into using other utilities, like for example Codeception (specifically acceptance tests).
When using CakePHP, it is advised that you do not access PHP superglobals directly, but that you retrieve the data from the abstracted APIs provided by CakePHP! Breaking your integration tests is one of the reasons for this. The simulated request will receive a request object that has been prepared with the data from your test case, that is where you need to look it up.
For example if you want to access POST data in your app, maybe in your controller, then you do it like this:
$user_id = $this->request->getData('user_id');
See also
Cookbook > Testing > Controller Integration Testing
Cookbook > Request & Response Objects
I want to let user manage database connection settings from website itself. I've thought that I would save db setting in a txt file and before every connection these would be read from this file first. Is it even possible?
I tried to use this in the main config file, but it does not work:
$myfile = Yii::app()->file->set('assets/settings.txt', true);
$array = explode("\r\n", $myfile->getContents());
$dblink = $array[0];
...
'db' => array(
'connectionString' => $dblink,
...
I'm getting an error that I'm exceeding the number of requests allowed per session (30) when using this query (using Include instead of Customize):
ApplicationServer appServer = QuerySingleResultAndSetEtag(session => session
.Include<ApplicationServer>(x => x.CustomVariableGroupIds)
.Include<ApplicationServer>(x => x.ApplicationIdsForAllAppWithGroups)
.Include<ApplicationServer>(x => x.CustomVariableGroupIdsForAllAppWithGroups)
.Include<ApplicationServer>(x => x.CustomVariableGroupIdsForGroupsWithinApps)
.Include<ApplicationServer>(x => x.InstallationEnvironmentId)
.Load <ApplicationServer>(id))
as ApplicationServer;
Note, the error occurs on this line, which is called for each AppWithGroup within an application:
appGroup.Application = QuerySingleResultAndSetEtag(session =>
session.Load<Application>(appGroup.ApplicationId)) as Application;
However, this query (using Customize) doesn't create extra requests:
ApplicationServer appServer = QuerySingleResultAndSetEtag(session =>
session.Query<ApplicationServer>()
.Customize(x => x.Include<ApplicationServer>(y => y.CustomVariableGroupIds))
.Customize(x => x.Include<ApplicationServer>(y => y.ApplicationIdsForAllAppWithGroups))
.Customize(x => x.Include<ApplicationServer>(y => y.CustomVariableGroupIdsForAllAppWithGroups))
.Customize(x => x.Include<ApplicationServer>(y => y.CustomVariableGroupIdsForGroupsWithinApps))
.Customize(x => x.Include<ApplicationServer>(y => y.InstallationEnvironmentId))
.Where(server => server.Id == id).FirstOrDefault())
as ApplicationServer;
However, the above query causes an error:
Attempt to query by id only is blocked, you should use call
session.Load("applications/2017"); instead of
session.Query().Where(x=>x.Id == "applications/2017");
You can turn this error off by specifying
documentStore.Conventions.AllowQueriesOnId = true;, but that is not
recommend and provided for backward compatibility reasons only.
I had to set AllowQueriesOnId = true because it was the only way I could get this to work.
What am I doing wrong in the first query to cause the includes not to work?
By the way, another post had the same issue where he had to use Customize. I'd like to do this correctly though.
I'm not sure why the load isn't doing this for you, What version of raven are you on? I just tested this in Raven 2.5 build 2700 and the include is bringing back the information for me in a single request.
Anyway, with the load not working quite like i would expect, i would switch to a set of lazy queries to get what you want in 2 server round trips. http://ravendb.net/docs/2.5/client-api/querying/lazy-operations.
Another option that might work out better for you, (depending on what you are really doing with all of that data) is a transformer. http://ravendb.net/docs/2.5/client-api/querying/results-transformation/result-transformers?version=2.5
Hope that helps.