Custom Log Method - cakephp

I am attempting to implement a log system in cakePHP. I have a issue now were the methods contents in "write" are called twice. This causes an issue because it places 2 log entries of the same type in my system.
Databaselogger.php in the Lib/Engine/ directory:
App::uses('CakeLogInterface', 'Log');
class DatabaseLogger implements CakeLogInterface {
private $types = array();
public function __construct($options = array()) {
// Allowed method calls
$this->types = $options['types'];
}
public function write($type = NULL, $message = NULL) {
// Only store to cache types that are permitted, other errors from cake are not reported
if(!empty($this->types) && in_array($type, $this->types))
{
//make database entry here
}
}
}
In my bootstrap.php :
App::uses('CakeLog', 'Log');
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',
));
// Custom configuration
CakeLog::config('mytest', array(
'engine' => 'DatabaseLogger',
'types' => array('mytest'),
'scope' => array(),
'file' => '',
));
This is how I call the method:
CakeLog::write('mytest', 'this message!');
Can anyone give some hints as to why this might be happening? Thanks!

As the namespace of the core files is
/Log/Engine/
I would assume that it should be
/Lib/Log/Engine/DatabaseLog.php (or Logger if you want to straggle from the core naming).
accordingly.
Proof you will get from the LogEngineCollection class, which contains:
App::uses($loggerName, $plugin . 'Log/Engine');
to include the engine of yours (hence the importance of the correct namespace).
Please take the time to look into the core code. Its open source after all :)

Related

cakephp redis storage besides sessions

I am trying to use redis as my caching engine and I have so far was able to add the add redis in cakephp and it writes my sessions to my redis just fine. This is what I did in the core
$engine = 'Redis';
$prefix = 'myapp_';
Cache::config('session', array(
'engine' => $engine,
'prefix' => $prefix . 'cake_session_',
'duration' => $duration
));
Configure::write('Session', array(
'defaults' => 'cache',
'timeout' => 100,
'start' => true,
'checkAgent' => false,
'handler' => array(
'config' => 'session'
)
));
Now I want to be able to write to redis from my controller some cached queries but I am not able to save that in redis. Instead it saves it to some default (I have no idea where) cache.
This is what I did in my controller
public function index()
{
Cache::write("TestKey","myquery","default");
var_dump(Cache::read("TestKey")); die;
}
The above gives me the value myquery on the browser but when I go to my redis-cli and look for keys * I do not see that key there. So obviously its saving somewhere else. I am not sure how to make it to write to redis. I have tried this Cache::write("TestKey","myquery","Redis"); but that also did not work.
Thanks for help in advance
**EDIT 1 **
I just did some debugging and it looks like its trying to add to file
object(FileEngine)[3]
protected '_File' => null
public 'settings' =>
array (size=10)
'engine' => string 'File' (length=4)
'path' => string '/Library/WebServer/Documents/phoneapp_backend/app/tmp/cache/' (length=60)
'prefix' => string 'cake_' (length=5)
'lock' => boolean true
'serialize' => boolean true
'isWindows' => boolean false
'mask' => int 436
'duration' => int 3600
'probability' => int 100
'groups' =>
array (size=0)
empty
protected '_init' => boolean true
protected '_groupPrefix' => null
How do I change it to write to redis?
Thanks
You need to configure the default cache configuration to use Redis insteado of File. In app/Config/bootstrap.php Change
Cache::config('default', array('engine' => 'File'));
So it reads:
Cache::config('default', array('engine' => 'Redis'));
You may need to add more options to the configuration for specifying the server and port where Redis is running.

Download function not working CakePHP

I read the documentation regarding file downloads, however I can't seem to get this to work.
I have read through questions here as well, and have had no luck.
My function looks as follows:
public function generate($id) {
$this->layout = 'ajax';
$this->Magazine->recursive = 2;
$DistributionLists = $this->Magazine->DistributionList->find('all',
array(
'conditions' => array(
'Magazine.id' => $id
),
'order' => array(
'DistributionList.priority ASC'
)
)
);
$this->set('magazine',$DistributionLists[0]['Magazine']['magazine_name']);
$this->set(compact('DistributionLists'));
}
public function download() {
$this->viewClass = 'Media';
$params = array(
'id' => "Magazine Distribution List.doc",
'name' => "Magazine Distribution List",
'download' => true,
'extension' => 'doc',
'path' => APP . "tmp" . DS
);
$this->set($params);
unlink(APP."tmp".DS);
$this->redirect(array('action'=>'index'));
}
public function afterFilter() {
parent::afterFilter();
if($this->action == 'generate') {
$this->redirect(array('action'=>'download'));
}
}
The reason I have an afterFilter function is because the word document that needs to be downloaded is created in the view file.
Does anyone know why this doesn't work?
You have to remove the call to the redirect method in your download method because it prevents your view from getting "rendered" due to the redirect.

Change $actsAs variable from controller

All I want to do is change a value ('path') in the $actsAs array of my Upload model from the controller prior to a save.
The only way I've come up with that works is to unload the behavior and then load it with all of it's settings.
This seems like overkill to just change the path. Is there an easier/better way?
$this->loadModel('Upload');
$this->Upload->Behaviors->unload('Upload.Upload');
$this->Upload->Behaviors->load('Upload.Upload', array(
'photo' => array(
'thumbnailSizes' => array(
'xvga' => '1024x768',
'vga' => '640x480',
'thumb' => '80x80',
),
'thumbnailMethod' => 'php',
'thumbnailQuality' => '80',
'pathMethod'=>'random',
'path' => '{ROOT}webroot{DS}uploads{DS}test{DS}{field}{DS}',
'maxSize' => '5242880', //5MB
'mimetypes' => array('image/jpeg', 'image/png', 'image/gif', 'image/bmp'),
'extensions' => array('jpg', 'gif', 'png', 'bmp'),
),
));
if($this->Upload->save($this->request->data)) {
//...
From looking at the source I think the uploadSettings() method is what you're looking for:
$this->Upload->uploadSettings('photo', 'path', 'YOUR_PATH');
The BehaviorCollection should merge the configuration when you load it over an existing behavior, so you shouldn't need to re-include all the other configuration. In fact, you shouldn't need to unload it either.
$this->Upload->Behaviors->load('Upload.Upload', array(
'photo' => array(
'path' => '{ROOT}webroot{DS}uploads{DS}test{DS}{field}{DS}'
)
));
Since the merging uses array_merge instead of array_merge_recursive this will not work for you. I included it here because it's probably the preferred method, though the behavior you're using uses a configuration array that Cake won't handle the way you want it to.
Alternatively, you can simply modify the $actsAs variable when the model is constructed, which will cause it to set up correctly.
public function __construct($id = false, $table = null, $ds = null) {
// 2 lines for readability
$this->actsAs['Upload.Upload']['photo']['path'] =
'{ROOT}webroot{DS}uploads{DS}test{DS}{field}{DS}';
return parent::__construct($id, $table, $ds);
}

Cakephp Error using Miles J Uploader plugin

I am currently trying to use Miles J plugin located here http://milesj.me/code/cakephp/uploader Although I have made great progress learning CakePhp, I am currently having a problem using the plugin and I would appreciate any help provided.
I have followed all the necessary steps to use the plugin. It has been downloaded put on Plugin folder, I bootstrapped with CakePlugin::loadAll().
So far so good.
Next I have proceed to set up the table as indicated by the plugin developer.
Ok, now back to my own code. I have the following set up:
images_controller.php , image.php and their views.
My goal now is to use the plugin inside those files as such:
App::import('Vendor', 'Uploader.Uploader');
Class ImagesController extends AppController {
var $components = array('Auth');
var $helpers = array('Design');
var $uses = array('Image', 'Uploader.Upload');
function manage(){
//here I show a simple upload form that uses the action saveimage
}
function saveimage(){
$this->Uploader = new Uploader();
if(!empty($this->data)){
$this->Upload->save($this->data);
}
}
}
Now, my model is set as follows
Class Image extends AppModel {
public $useTable = 'uploads';
public $actsAs = array(
'Uploader.FileValidation' => array(
'file' => array(
'extension' => array(
'value' => array('gif', 'jpg', 'jpeg'),
'error' => 'Only gif, jpg and jpeg images are allowed!'
),
'minWidth' => 500,
'minHeight' => 500,
'required' => true
),
'import' => array(
'required' => false
)
),
'Uploader.Attachment' => array(
'file' => array(
'name' => 'uploaderFilename',
'uploadDir' => '/files/uploads/',
'dbColumn' => 'path',
'maxNameLength' => 30,
'overwrite' => true,
'stopSave' => false,
'transforms' => array(
// Save additional images in the databases after transforming
array(
'method' => 'resize',
'width' => 100,
'height' => 100,
'dbColumn' => 'path_alt'
)
),
'metaColumns' => array(
'size' => 'filesize', // The size value will be saved to the filesize column
'type' => 'type' // And the same for the mimetype
)
),
'import' => array(
'uploadDir' => '/files/uploads/',
'name' => 'uploaderFilename',
'dbColumn' => 'path',
'overwrite' => true,
'stopSave' => false,
'transforms' => array(
array(
'method' => 'scale',
'percent' => .5,
'dbColumn' => 'path' // Overwrite the original image
)
)
)
)
);
}
}
On my model for testing purposes I have not changed anything but just copied and pasted the very same array as shown in the the Test/Model folder inside the plugin, which is meant to show the functionality of the plugin.
The following confusion, errors or lack of understanding is taking place:
My file is not being uploaded to the webroot/files/uploads folder
My data is being inserted in the database, but not in a complete manner by leaving empty as shown:
id | caption | path | path_alt | created |
4 | | | |2012:02:..|
Above, I expect the path to be saved, but it doesn't.
I have to admit my confusion comes mainly from my inexperience using plugins, so I am aware I might be doing something wrong regarding my models or my configuration.
Any prompt help would be appreciated greatly as I have tried to work this out on my own without any success.
A few things:
1 - In your controller you do not need to import the Uploader class. You also don't need to use the Uploader.Upload model (it's merely an example test case). All you need to do in the controller is call $this->Image->save() which will upload the file and save the path as a row into the database (if you defined the Attachment in Image).
2 - In your view, create the file input. Pay attention to the input name.
echo $this->Form->input('FILE_INPUT_NAME', array('type' => 'file'));
3 - In your Image model, setup the AttachmentBehavior and its options for that specific input field:
'Uploader.Attachment' => array(
'FILE_INPUT_NAME' => array(
'uploadDir' => '/files/uploads/',
'dbColumn' => 'path'
),
'ANOTHER_INPUT' => array()
);
Be sure that the column "path" exists in your images table. And thats it.
For more information on what each option does, check out the following: http://milesj.me/code/cakephp/uploader#uploading-files-through-the-model

cakephp dynamic db connection

I have an application where each subscriber gets their own 'app' folder within their own url eg.
www.domain.com/1234 subscriber1
www.domain.com/2345 subscriber2
now the db connection is configured in a class in config/database.php. I want to be able to change the database used based on the url (eg. /1234 = db_1234).
How would I achieve this?
Thanks
BTW I am using CakePHP 2.0
My previous solution was a load of rubbish. So I thought about attacking the problem from a different angle. My DATABASE_CONFIG class (/app/Config/database.php) now looks like this:
class DATABASE_CONFIG {
public $default = array(
'datasource' => 'Database/Mysql',
'persistent' => false,
'host' => '127.0.0.1',
'login' => 'xxxx',
'password' => 'xxxx',
'database' => 'xxxx',
'prefix' => '',
'encoding' => 'utf8',
);
public $site_one = array(
'datasource' => 'Database/Mysql',
'host' => '127.0.0.1',
// ...
);
public $site_two = array(
'datasource' => 'Database/Mysql',
'host' => '127.0.0.1',
// ...
);
public function __construct()
{
if (strpos(env('HTTP_HOST'), 'site_one') !== false) {
// use site_one database config
$this->default = $this->site_one;
// elseif site_two
} elseif (strpos(env('HTTP_HOST'), 'site_two') !== false) {
// use site_two database config
$this->default = $this->site_two;
}
}
}
When Cake loads, the construct is now called automatically, and this sets the 'default' database connection dependent on the host.
Ah I got it now,
I thought DATABASE_CONFIG was called statically so didn't think to use the construct.
www.domain.com/12345678
function __construct() {
// get folder
if(substr(php_sapi_name(), 0, 3) == "cli") {
$j = explode("/", $_SERVER['PWD']);
$this->default['database'] = "sa_".$j[count($j)-1];
} else {
$j = explode("/", $_SERVER['REQUEST_URI']);
$this->default['database'] = "sa_".$j[1];
}
}
but commandline bake must be done in folder eg. 12345678/

Resources