Cake 3.0 Cache Configuration for OPcache and APCu - cakephp

In cakephp 3.0 what is the right way to configure Cache based on cake built-in caching engines?
I'm using PHP 5.6 with Zend OPcache And APCu.

Zend Opcache is a built in opcode cache, it isn't something you need to configure, APCu however will need to be compiled against your webserver and enabled with APC emulation
in config/app.php you need to enter the following:
// Using a fully namespaced name.
'long' => [
'className' => 'Cake\Cache\Engine\ApcEngine',
'duration' => '+1 week',
'probability' => 100,
'path' => CACHE . 'long' . DS,
]
You can create different configs for different cache times.
Then to cache an object you simply:
$data = Cache::remember('my_cache_key', function () {
return Service::expensiveCall();
});
Or use the functions Cache::read and Cache::write

Related

CakePHP 3 Cache File Permissions

I have a CakePHP 3 app with shells that I run from crontab.
When I run the shells through crontab, it creates cache files owned by the user running the crontab, which is not the user that runs apache...
Sometimes when I run the crontab the cached models are owned by apache and the shell fails, sometimes when I visit a page the models are owned by ec2-user and the page fails...
I posted a question on github, https://github.com/cakephp/cakephp/issues/11265#issuecomment-333951638
I was told to modify the chmod option for the cache config, I tried the following but it didn't work...
/**
* Configure the cache adapters.
*/
'Cache' => [
'default' => [
'className' => 'File',
'path' => CACHE,
'url' => env('CACHE_DEFAULT_URL', null),
'chmod' => 777
],
Any ideas on how I can make the default file permissions 777 on the cake cache files?
I would suggest having the chron run as the correct user OR having the chron task change owner and keep permissions as set but if you really want to have it all as it is and just change the permissions then you can use the mask option which I assume is what they meant.
Cache Config Options
Set using the following:
'Cache' => [
'default' => [
'mask' => 0777,
// other config options
],
]
#KaffineAddict is correct but make sure you do not wrap the value of mask in quotes as this can cause the values to not give correct permissions.
'Cache' => [
'default' => [
'mask' => 0777,
// other config options
],
]

Setting Environment-specific database in CakePHP

I am using CakePHP and was trying to implement https://github.com/josegonzalez/cakephp-environments
Which seemed to be going fine except that I have no idea where to specify the env specific database info.
Does anyone know where to set these?
I personally haven't used the plugin, however from looking at the code and the docs, if you were using the suggested database configuration, then it seems that you would define the options as either environment variables, which can be done in various ways, for example
in your server configuration (Apache example)
in your cloud varibale settings (Heroku example)
manually using putenv(), $_ENV, $_SERVER
$name = 'MYSQL_DB_HOST';
$value = 'localhost';
putenv("$name=$value");
$_ENV[$name] = $value;
$_SERVER[$name] = $value;
...
or as CakePHP configuration values via the Environment::configure() calls, something like:
Environment::configure('development',
true,
array(
'MYSQL_DB_HOST' => 'localhost',
'MYSQL_USERNAME' => 'user',
// ...
),
// ...
);

How to use Zend Framework 2 with MS SQL Server on *nix?

What, if it exists, is the canonical way to use ZF2 with MS SQL Server on a non-Windows OS?
From what I can tell from the documentation, only the Sqlsrv driver is officially supported, which only works on the Windows platform.
In ZF1, we used the Pdo_Mssql adapter and specified the pdoType as dblib. I can't find any references to doing anything similar in ZF2.
Apparently there was a Pdo\Mssql driver some time ago which was removed during a major refactoring, but I don't see a currently documented way of using Pdo_Dblib.
According to the adapter documentation above, you can set the driver in the adapter config to Pdo=OtherPdoDriver, but there's no documented examples of this usage. Does that mean you can use Pdo=Pdo_Dblib or Pdo=dblib and it will work automagically?
I've found passing references to a PDO ODBC driver, which would be a usable alternative, but can't find any documentation or code references.
Install the php5-sybase. Make sure that freetds is installed. You should have a conf file under /etc/freetds called freetds.conf.
In your freetds.conf file you should setup your mssql connection like this:
[MyMsSqlServer]
host = symachine.domain.com
port = 5000
tds version = 5.0
Then, (using the ZF2 Albums Tutorial as an example here) you set up the adapter like this:
return array(
'db' => array(
'driver' => 'Pdo',
'dsn' => 'dblib:host=MyMsSqlServer;dbname=zf2tutorial',
'charset' => 'UTF-8',
'username' => 'username',
'password' => 'password',
'pdotype' => 'dblib',
),
'service_manager' => array(
'factories' => array(
'Zend\Db\Adapter\Adapter' => 'Zend\Db\Adapter\AdapterServiceFactory',
),
),
);
See if this gets you anywhere and let me know. I had a bitch of a time getting this to work, and I am more then happy to help anyone else that is having issues with this!!!
You can use a pdo connection with pdotype set to dblib (with loaded pdo_dblib extension).
sqlsrv is only available for Windows.
Here you can see how freetds and unixodbc is configured to connect to a MS SQL Server.
http://featurebug.blogspot.de/2011/01/mac-os-x-php-zend-server-ce-freetds-and.html
UPDATE:
Here is an example how to use a connection string to connect:
$db = new Zend\Db\Adapter\Adapter(
array(
'driver' => 'Pdo',
'dsn' => 'dblib:host=mssql_freetds;',
'username' => 'mssql_username',
'password' => 'mssql_password',
)
);
Yes, you can use odbc to connect. It is not currently officially supported, but you can get it working fairly easily, with minimal modifications.
The first thing you need to do, is make sure you can connect using the basic PHP PDO functions. So, do something like this:
$resource = new PDO('odbc:driver=FreeTDS;dbname=MYDB;Server=127.0.0.1;Port=8090;UID=Testuser;PWD=testpass;', 'Testuser', 'testpass', array());
$s = $resource->prepare('SELECT * FROM TEST_TABLE');
$r=$s->execute();
var_dump($r);
You'll need to change the host, port, user, pass, table name etc. for your settings, but you can use this to make sure you have those details right. Once you know what you are doing to connect, you can access it with Zend, like this:
$configArray = array(
'driver' => 'pdo_odbc',
'driver_options' => array('driver' => 'FreeTDS'),
'platform' => 'Mssql',
'dbname' => 'MYDB',
'host' => '127.0.0.1',
'port' => 8090,
'user' => 'Testuser',
'pass' => 'testpass'
);
$adapter = new Zend\Db\Adapter\Adapter($configArray);
$q = new Zend\Db\Sql\Select();
$q->from('TEST_TABLE');
$sql = $q->getSqlString($adapter->platform);
$r = $adapter->query($sql);
echo $r->getSql()."\n";
$result = $r->execute();
while(($res = $result->next()) !== false){
print_r($res);
}
However this will not actually work, for two reasons. First, the platform - Zend currently doesn't have an mssql platform; it defaults to sql92, which will not work, because it quotes identifiers in "", when mssql needs them to be quoted with []. So you'll need to copy the Zend/Db/Adapter/Platform/Sql92.php as Mssql.php, and change it to use [ and ] instead of ".
Second, because the dsn for connection to odbc requires the driver field, which zend currently doesn't support. You'll need to open up the Driver/Pdo/Connection class and modify the connect function, to add $dsn[] = "driver={$options['driver']}"; and replace $dsn[] = "host={$hostname}"; with $dsn[] = "server={$hostname}"; when $pdoDriver = odbc.
Note that the other answers are posted by people who do not actually understand how the Zend 2 library works - if you specify a value for 'dsn', then the other fields are ignored. I have NO idea where they got the idea of 'pdotype', as that is not a field that appears anywhere in the code.

$this->Auth->login() creates correct query that returns 1 row, but fails IF check (server specific issue)

We have a site that we're moving to a new server. Everything worked fine on the old server. It's just the start of a site, so it's pretty bare-bones.
When moving to our new server, trying to log-in no longer works. BUT - according to debugKit, the query generated by $this->Auth->login():
SELECT `User`.`id`, `User`.`name`, `User`.`email`, `User`.`username`, `User`.`password`, `User`.`role`, `User`.`created`, `User`.`modified`
FROM `shopping_main`.`users` AS `User`
WHERE `User`.`username` = 'another'
AND `User`.`password` = '3813dd3a5eeb39c857d56f9ae58ec7f8237e5eb3'
LIMIT 1
IS returning 1 row - yet this if block fails:
if ($this->Auth->login()) {
$this->Session->setFlash(__('You are now logged in.'));
} else {
$this->Session->setFlash(__('Invalid username or password, try again'));
}
PDO is installed on both (same version) - not sure if that matters, but we've had weird issues before w/ that.
When doing a fresh install of CakePHP 2.2 stable, everything lights up green (database connection, modrewrite...etc etc.)
I would have thought there was something wrong with our data, or code...etc, but - it's the same data, the same code, and that's verified by the fact that it DOES return 1 row.
Below is my most recent $components array in the AppController:
public $components = array(
'DebugKit.Toolbar',
'Session',
'Cookie',
'Auth' => array(
'loginRedirect' => array('controller' => 'dashboard', 'action' => 'index', 'admin'=>true),
'logoutRedirect' => array('controller' => 'users', 'action' => 'login', 'admin'=>true)
)
);
UPDATE:
According to our server guy, the server we're having the issue on is the only one with PECL intalled - when he removed it, the login worked. (We need it on the server for other things - why/what would cause that to keep our login from working?)
Answer by Original Poster (me):
According to our server guy, "There are two ways to load PDO. The first is by using easyapache to install the PDO php extension. The second is by installing the PDO via PECL. It appears that the modules in question are different."
Apparently, this server had PECL on it instead of the normal easyapache PDO. When he removed that, and restarted/reset it with the easyapache PDO, everything worked great.
So - sounds like CakePHP requires the "normal" PDO.
Mystery solved.
If you have PECL instead, you can use this workaround:
Create a file "HpMysql.php" in your Datasource folder and add this code/class: https://github.com/lorenzo/HipHop/blob/master/Model/Datasource/Database/HpMysql.php
Change your database.php 'datasource' to 'HpMysql'

CakePHP: Reporting Failed Downloads with the Media View

I'm using CakePHP's Media view to force file downloads. My code is pretty much exactly like the example provided in the cookbook, which I'll paste here for your convenience:
<?php
class ExampleController extends AppController {
public function download () {
$this->viewClass = 'Media';
// Download app/outside_webroot_dir/example.zip
$params = array(
'id' => 'example.zip',
'name' => 'example',
'download' => true,
'extension' => 'zip',
'path' => APP . 'outside_webroot_dir' . DS
);
$this->set($params);
}
}
In the database, I have a field that keeps track of how many times the file was downloaded. I'm looking for a way to make sure that this number is as accurate as possible, so if a user's download gets cancelled or times out, the number does not increment. Is there some way for CakePHP's Media view to report that the download was, indeed, successful?
Detecting when a file has finished downloading is no easy task. This is something that would be done on the client side with javascript, but browsers do not give you any hooks for that.
There is a pretty clever solution here (setting a cookie and then looking for it with javascript), but it only tells you when the download has started.

Resources