CakeLog and scope : Restricting scope to only one logger - cakephp

I'd like to set a up log file so that only messages with a scope of soap get logged to that file. Conversely, I'd also like to prevent messages with a scope of soap being logged against the default logs of debug and error.
Here is my current setup in bootstrap.php.
CakeLog::config('soap', array(
'engine' => 'FileLog',
'types' => array('info','debug','error'),
'scopes' => array('soap'),
'file' => 'soap'
));
CakeLog::config('debug', array(
'engine' => 'FileLog',
'types' => array('notice', 'info', 'debug'),
'file' => 'debug',
));
CakeLog::config('error', array(
'engine' => 'FileLog',
'types' => array('warning', 'error', 'critical', 'alert', 'emergency'),
'file' => 'error',
));
Here is a snippet from one of my libs that makes soap calls.
CakeLog::debug("REQUEST:\n" . $client->__getLastRequest() . "\n", 'soap');
CakeLog::debug("RESPONSE:\n" . $client->__getLastResponse() . "\n", 'soap');
} catch (SoapFault $e) {
CakeLog::error(print_r($result,true), 'soap');
CakeLog::error('Exception: (' . $e->getCode() . ') ' . $e->getMessage(), 'soap');
if (isset($client)) {
CakeLog::error("Errored REQUEST:\n" . print_r($client->__getLastRequest(), true) . "\n", 'soap');
}
When I do this current set up, I get the debug soap messages in debug.log and soap.log, which is not desirable.

According CakeLog::config documentation
If you don't define any scopes an adapter will catch all scopes that match the handled levels.
so, debug logger write all messages with type 'types' => array('notice', 'info', 'debug'),
Now how you can avoid it? Seems you have 2 ways:
use CakeLog::write with custom error type
CakeLog::write('soap', "REQUEST:\n" . $client->__getLastRequest() . "\n");
in this case, according documentation of CakeLog::write method
integer|string $type
Type of message being written. When value is an integer or a string matching the recognized levels, then it will be treated log levels. Otherwise it's treated as scope.
scope and type will same and have 'soap' value, so, message will not logged in debug logger, but only in soap.
leave it as now, cause save all debug messages in one file and some messages in some specific logs not such bad idea.

A logger with no defined scopes will log all scopes, as is the case with the debug and error log configuration in the question.
To prevent the debug+error logs from containing soap messages, you'll need to defined explicitly what scopes they should act upon:
CakeLog::config('debug', array(
'engine' => 'FileLog',
'types' => array('notice', 'info', 'debug'),
// restrict to scope=type only
'scopes' => array('notice', 'info', 'debug'),
'file' => 'debug',
));
CakeLog::config('error', array(
'engine' => 'FileLog',
'types' => array('warning', 'error', 'critical', 'alert', 'emergency'),
// restrict to scope=type only
'scopes' => array('warning', 'error', 'critical', 'alert', 'emergency'),
'file' => 'error',
));
Cake does have a logging safety net so that if a log message has been filtered out completely (by what is effectively, bad config) it will at least be written to the default logger. So a call like this:
$this->log('special', 'foo');
will still be written to the foo log (with default config).
A debug log without all messages isn't a debug log
As answered by Vadim - it's not a bad idea to have a debug log with all log messages in it. This permits grepping a single file for information, instead of needing to look in several different files when things aren't quite going to plan in your application.

You can use CakeLog::disable('debug') and CakeLog::disable('error') to disable these two default log streams temporarily before CakeLog::write to 'soap'.
And don't forget to immediately restore by using CakeLog::enable('debug') and CakeLog::enable('error') after 'soap' log was written.
Sample:
CakeLog::debug('THIS MESSAGE WILL APPEAR IN debug.log and soap.log', 'soap');
CakeLog::disable('debug');
CakeLog::debug('THIS MESSAGE WILL NOT APPEAR IN debug.log but soap.log only', 'soap');
CakeLog::enable('debug');
CakeLog::debug('THIS MESSAGE WILL APPEAR IN debug.log and soap.log', 'soap');
CakeLog::disable

Related

CakePHP 3.x - File validators on upload always failing

I am working on an image upload. I am trying to do the image verification in the model (like it should, right?), however I can't get the validation to work.
I put the following in src/Model/Table/CommentTable:
public function validationDefault(Validator $validator)
{
//...
$validator->add('photofile', 'upload', [
'rule' => ['uploadedFile', ['maxSize' => 1048576, 'optional' => true, 'types' => ['image/*']]],
'message' => 'Not a valid file'
]);
//...
}
For testing my controller looks like (I hard-coded an existing file):
$comment = $this->Comments->newEntity([
'body' => $data['body'],
'bin_id' => $bin_id,
'user_id' => $this->Auth->user('id'),
'photofile' => 'C:/Users/Robert/Downloads/test.jpg'
]);
This file is only a couple of bytes, yet after debugging $comment is shows an error in 'photofile':
'[errors]' => [
'photofile' => [
'upload' => 'Not a valid file'
]
],
So why is the validator always failing? Am I using it correctly?
Well, it's not an uploaded file, so that's generally the expected behavior. Also a string isn't supported as a valid value at all, the value must either be a file upload array, or as of CakePHP 3.4, an object that implements \Psr\Http\Message\UploadedFileInterface.
For file upload arrays, the uploadedFile validation rule provided by CakePHP will utilize is_uploaded_file(), which will fail for files that haven't actually been uploaded, and you cannot emulate them.
As of CakePHP 3.4 you can use UploadedFileInterface objects as already mentioned. CakePHP requires \Zend\Diactoros\UploadedFile which provides an implementation that you could utilize for testing purposes, like:
$file = 'C:/Users/Robert/Downloads/test.jpg';
$comment = $this->Comments->newEntity([
'body' => $data['body'],
'bin_id' => $bin_id,
'user_id' => $this->Auth->user('id'),
'photofile' => new \Zend\Diactoros\UploadedFile(
$file,
filesize($file),
\UPLOAD_ERR_OK,
pathinfo($file, \PATHINFO_BASENAME),
'image/jpeg'
)
]);
However while this will pass validation, you won't be able to move that file using UploadedFile::moveTo(), as it uses move_uploaded_file(), which again only works with files that have actually been uploaded.
Also regex validation of MIME types only works when passed as a string (this currently isn't documented), and it must be a valid regex including delimiters, like
'types' => '#^image/.+$#'
Alternatively specify the exact types as an array, ie
'types' => ['image/jpeg', 'image/png', /* ... */]
See also
Zend Diactoros API > UploadedFile
CakePHP API > \Cake\Validation\Validation::uploadedFile()

MIME type error

With Cakephp 2.6 I have the following warning:
Can not determine the mimetype.
Error: An Internal Error Has Occurred.
Below is my Model:
'mimeType' => array(
'rule' => array('mimeType', array('image/gif', 'image/png', 'image/jpg', 'image/jpeg')),
'message' => 'Please only upload images (gif, png, jpg).',
'allowEmpty' => FALSE,
),
In php.ini (\xampp\php\php.ini) I uncommented
extension=php_fileinfo.dll
But I still have the same error message.
There is no line number in the error message even if my debug is set to 2. the only error message displaying is :
Can not determine the mimetype.Error: An Internal Error Has Occurred.
for the stack trace, the value of 'Validation::mimeType(array, array)' is
array(
'name' => '2009_Infini-jaune-2.jpg',
'type' => 'image/jpeg',
'tmp_name' => 'C:\xampp\tmp\phpEC6C.tmp',
'error' => (int) 0,
'size' => (int) 186994)
array(
(int) 0 => 'image/png',
(int) 1 => 'image/jpeg'
)`
When enabling or disabling extensions, be sure to restart the web server (or PHP if you are running PHP as a FastCGI instance).
Change the text ;extension=php_fileinfo.dll into extension=php_fileinfo.dll on php.ini
It works for me. Hope it helps you guys. I'm using xampp.
Don't forget to restart the web server after that.

Ocasional error warning when CakePHP is writing to the cache

I'm developing a CakePHP 2.2 site locally with MAMP. Every so often, I get one or more warnings similar to this, about not being able to write to one or more cache files:
Warning: SplFileInfo::openFile(/Applications/MAMP/htdocs/mywebsite/www/app/tmp/cache/persistent/myapp_cake_core_cake_console_en-au): failed to open stream: Permission denied in /Applications/MAMP/htdocs/mywebsite/www/lib/Cake/Cache/Engine/FileEngine.php on line 313
The weird thing is, /tmp is 777, tmp/cache is 777, and tmp/cache/persistent is 777 (don't worry... it won't be 777 on the server!). The file itself inside tmp/cache/persistent is 644 - but I assume Cake is creating and managing that file, and does so with the permissions it needs.
If I just refresh the page, the error goes away (and then re-appears sometime later). I'm not doing any explicit caching, so this stuff is just Cake doing whatever it automatically does.
So my question is:
a) How does this automatic caching of Cake's work? Is it trying to write to that file on every page refresh, and failing only once in a while? Or is it only trying to write to that file once in a while, but failing every time it tries?
b) If it's only failing only once in a while, can I safely just ignore it? And if it's failing every time it tries, how can I fix it?
Thanks in advance for any help!
This happens probably when a process different from Apache create files in the cache. This can be the case for instance when you run shell commands as you probably do it as a different user than apache.
By default the File cache creates files with permissions allowing only the user that has created the files to modify them, but this can be fixed by setting a mask in the Cache config in core.php:
Cache::config('_cake_core_', array(
'engine' => $engine,
'prefix' => 'cake_core_',
'path' => CACHE . 'persistent' . DS,
'serialize' => ($engine === 'File'),
'duration' => $duration,
'mask' => 0666
));
Cache::config('_cake_model_', array(
'engine' => $engine,
'prefix' => 'cake_model_',
'path' => CACHE . 'models' . DS,
'serialize' => ($engine === 'File'),
'duration' => $duration,
'mask' => 0666
));
If you want to avoid giving read/write access to the "other" group, check out my other solution here:
https://stackoverflow.com/a/18703956/385979
Simple really, assuming and you are a sudoer and your user name is martinlutherking
sudo adduser martinlutherking www-data
This way cake console commands can read cache files created by apache2, however you may need to do the inverse group add to ensure that www-data can read cache files created by martinlutherking
Just in case anybody is seeing this and wonders how it works in cakePHP 3.x:
modify /config/app.php and add 'mask' => 0666 to
/**
* Configure the cache adapters.
*/
'Cache' => [
'default' => [
'className' => 'File',
'path' => CACHE,
'url' => env('CACHE_DEFAULT_URL', null),
'mask' => 0666
],
and probably you also want to add it to the log files:
/**
* Configures logging options
*/
'Log' => [
'debug' => [
'className' => 'Cake\Log\Engine\FileLog',
'path' => LOGS,
'file' => 'debug',
'levels' => ['notice', 'info', 'debug'],
'url' => env('LOG_DEBUG_URL', null),
'mask' => 0666
],
'error' => [
'className' => 'Cake\Log\Engine\FileLog',
'path' => LOGS,
'file' => 'error',
'levels' => ['warning', 'error', 'critical', 'alert', 'emergency'],
'url' => env('LOG_ERROR_URL', null),
'mask' => 0666
],
],

unload() CakePHP Uploader Plugin does not seem to work

I'm using CakePHP 2.1.1 and Miles Johnson's Uploader Plugin v 3.5.
It's working pretty sweet although I think I have a problem when trying to unload the FileValidation behavior.
I have set up both the behaviors Uploader.Attachment and Uploader.FileValidator (see the bottom of the question).
In the afterSave callback I now need to save the Post again to add a Translated field for a different locale.
When I do save again, this seems to cause en error in the FileValidation behavior. I get the error:
failed to open stream: No such file or directory [APP/Plugin/Uploader/Model/Behavior/FileValidationBehavior.php, line 296]
Somehow the Behavior is looking again for the tmp file.
When I do not define the FileValidation behavior at all, all goes well. So I figured to disable the behavior after it has done it's job during regular save(), right before I go for my second save().
In afterSave($created) I therefore state
$this->Behaviors->unload('FileValidation');
$this->save($data);
The error disappears, but I get 4 warnings in return:
Warning (512): Could not find validation handler maxWidth for file [CORE/Cake/Model/Model.php, line 3155]
Warning (512): Could not find validation handler maxHeight for file [CORE/Cake/Model/Model.php, line 3155]
Warning (512): Could not find validation handler filesize for file [CORE/Cake/Model/Model.php, line 3155]
Warning (512): Could not find validation handler required for file [CORE/Cake/Model/Model.php, line 3155]
I also tried $this->Behaviors->disable('FileValidation') but to no avail.
Is this a bug in the Behavior (not properly unloading itself) or am I not properly handling the unload?
kind regards,
Bart
The behavior setup:
public $actsAs = array('Uploader.Attachment' => array(
'file' => array(
'name' => 'uniqueFilename', // Name of the function to use to format filenames
'baseDir' => APP, // See UploaderComponent::$baseDir
'uploadDir' => 'webroot/img/upload/', // See UploaderComponent::$uploadDir
'dbColumn' => 'uploadPath', // The database column name to save the path to
'importFrom' => '', // Path or URL to import file
'defaultPath' => '', // Default file path if no upload present
'maxNameLength' => 30, // Max file name length
'overwrite' => false, // Overwrite file with same name if it exists
'stopSave' => true, // Stop the model save() if upload fails
'transforms' => array(), // What transformations to do on images: scale, resize, etc
's3' => array(), // Array of Amazon S3 settings
'metaColumns' => array( // Mapping of meta data to database fields
'ext' => 'ext',
'type' => 'type',
'size' => 'size',
'group' => 'group',
'width' => 'width',
'height' => 'height',
'filesize' => 'size',
'name'=>'name'
)
)
),
'Uploader.FileValidation' => array(
'file' => array(
'maxWidth' => array(
'value' => 1000,
'error' => 'Image too wide. Max 1000px'
),
'maxHeight' => array(
'value' => 1000,
'error' => 'Image too high. Max 1000px'
),
'extension' => array(
'value' => array('gif', 'jpg', 'png', 'jpeg'),
'error' => 'Mimetype incorrect',
),
'filesize' => array(
'value' => 1048576,
'error' => 'Filesize too high. Max 1 MB'
)
)
)
);
Not directly related, but are you game to try another file upload plugin? This one might do the trick: http://bakery.cakephp.org/articles/srs2012/2012/03/12/ajaxmultiupload_plugin_for_cake_2_0_x_and_2_1
Not sure if this will fix yours but I found (for some reason I don't know why) this error gets thrown if you don't have debug set to 0 in your Config/core.php

cakephp - use memcache for sessions

I am quite new to cakephp and I'm having trouble getting it configured to work on my live server. It works fine on my local machine.
I think the problem is that my live server is configured to use Memcache. When I visit the live site I get:
Warning (2): session_start() [function.session-start]: open(=1&retry;_interval=15/sess_mt8tpui04vorqojg7s945e5sf5, O_RDWR) failed: No such file or directory (2) [CORE/Cake/Model/Datasource/CakeSession.php, line 615]
Warning (2): session_write_close() [function.session-write-close]: open(=1&retry;_interval=15/sess_mt8tpui04vorqojg7s945e5sf5, O_RDWR) failed: No such file or directory (2) [CORE/Cake/Controller/Controller.php, line 712]
Warning (2): session_write_close() [function.session-write-close]: Failed to write session data (files). Please verify that the current setting of session.save_path is correct (tcp://127.0.0.1:11211?persistent=1&weight;=1&timeout;=1&retry;_interval=15) [CORE/Cake/Controller/Controller.php, line 712]
So i've tried enabling cake to use memcache by adding the following to app/Config/core.php:
Cache::config('default', array(
'engine' => 'Memcache'
));
But I still get the same error.
The php.ini is configured to use memcache correctly.
Any ideas?
Thanks
Your Cache::config looks incomplete!
It should look like this and This code block will be in app/Config/bootstrap.php
Cache::config('default', array(
'engine' => 'Memcache', //[required]
'duration' => 3600, //[optional]
'probability' => 100, //[optional]
'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string
'servers' => array(
'127.0.0.1:11211' // localhost, default port 11211
), //[optional]
'persistent' => true, // [optional] set this to false for non-persistent connections
'compress' => false, // [optional] compress data in Memcache (slower, but uses less memory)
));
Also you need to set a session handler http://book.cakephp.org/2.0/en/development/sessions.html#cache-sessions
Mine looks like this, note that I have called "sessiones"
& This code block will be in app/Config/core.php
Configure::write('Session', array(
'defaults' => 'cache',
'handler' => array(
'config' => 'sessiones'
),
'cookie' => 'PHPSESSID',
'timeout' => 3600,
'cookieTimeout' => 0,
'autoRegenerate' => false,
'checkAgent' => true,
'ini' => array(
'session.cookie_secure' => false,
'session.cookie_httponly' => true,
)
));
And then set up the Cache:config for the handler "sessiones"
and This code block will be in app/Config/bootstrap.php
Cache::config('sessiones', array('engine' => 'Memcache','duration'=> 3600,/*'prefix' =>'es',*/ 'servers' => array(array('127.0.0.1:11211'), 'compress' => false));

Resources