I am using a Plugin to log the errors and warnings in a Cakephp-Application, and it is working as it supposed, but I was thinknig ,if the Connection with my DB is not working well, then still I need to log these errors , but this time in an external file,
The Idea should be easy, I call CaeLog::write() and in these Method(wich has been reimplemented by the Plugin) I would put "try/Catch", which would help me in the case an Exception is thrown, to write the message to a logfile.
My bootstrap.php looks like this :`
App::uses('CakeLog', 'Log');
CakeLog::config('debug', array(
'engine' => 'File',
'types' => array('notice', 'info', 'debug'),
'file' => 'debug',
));
CakeLog::config('fileLog', array(
'engine' => 'File',
'types' => array('fileLog'),
'file' => 'fileLog',
'scopes' => array('fileLog')
));
CakeLog::config('default', array(
'engine' => 'DatabaseLogger.DatabaseLog',
'types' => array('warning', 'error', 'critical', 'alert', 'emergency')`
In the write methode i have this Code
function write($type, $message){
try {
//Save In Db
} catch (Exception $exc) {
//If the save in DB fails call log in fileLog(which has been defined in bootstrap.php)
CakeLog::write('fileLog', "***************************\n".$exc."\n***************************\n");
}
}
The problem now : I am getting a loop, cause of the call in the catch block, which is trying again to save in db, how could i solve this without a loop?
Related
I'm using trntv/Yii2-starter-kit. How can I extract messages to DB?
My config:
'*'=> [
'class' => 'yii\i18n\DbMessageSource',
'sourceMessageTable'=>'{{%i18n_source_message}}',
'messageTable'=>'{{%i18n_message}}',
'enableCaching' => YII_ENV_DEV,
'cachingDuration' => 3600,
'on missingTranslation' => ['\backend\modules\i18n\Module', 'missingTranslation']
]
My I18N file:
'sourcePath'=>Yii::getAlias('#base'),
'languages' => ['uz','ru'],
'translator' => 'Yii::t',
'sort' => false,
'removeUnused' => true,
'only' => [
'*.php',
],
'ignoreCategories' => ['yii'],
I tryed:
php yii message #common/config/messages/_base.php
And
php yii message
But always it writes all messages to files: vendor/yiisoft/yii2/messages. How can I export messages to DB? Has anyone help?
You need to use the following as per CONSOLE-DOCS there is a ExtendedMessageControler class. This controller extends default MessageController to provide some useful actions:
To migrate messages between different message sources run the common like below
php console/yii message/migrate #common/config/messages/php.php #common/config/messages/db.php
Which means you should have a file inside the #common/confiog/messages/ folder with the name db.php that will be used to create the message and source_message tables the contents of the file should be
<?php
return \yii\helpers\ArrayHelper::merge(
require(__DIR__ . '/_base.php'),
[
// 'db' output format is for saving messages to database.
'format' => 'db',
// Connection component to use. Optional.
'db' => 'db',
// Custom source message table. Optional.
'sourceMessageTable' => '{{%i18n_source_message}}',
// Custom name for translation message table. Optional.
'messageTable' => '{{%i18n_message}}',
]
);
and the messages source directory will be determined by the php.php file inside the #common/config/messages directory that contains the following
<?php
return \yii\helpers\ArrayHelper::merge(
require(__DIR__ . '/_base.php'),
[
// 'php' output format is for saving messages to php files.
'format' => 'php',
// Root directory containing message translations.
'messagePath' => Yii::getAlias('#common/messages'),
// boolean, whether the message file should be overwritten with the merged messages
'overwrite' => true,
]
);
You just need to run the migration command and the tables will be created and the messages will be exported to the respective tables.
for more details see the SOURCE for the actionMigrate().
How do I handle generic validation errors in a Yii2 ActiveRecord model that do not relate to a specific attribute? For example I need to completely prohibit saving a model when a related record/modal has been set to inactive.
I can of course just pick a more or less random attribute and assign the error message to it, but what if the front end form doesn't have that attribute and therefore doesn't show the error? Or even worse, if a scenario later disables validation of that attribute (by not including it in the list of active attributes)?
I can of course return false in beforeSave() or beforeValidate() but then I have no option to specify a message to the user about why the model couldn't be saved, so I really don't like that idea.
Also, I don't want to throw Exceptions, it should just be a soft error message shown to the user.
What is the intended/best approach to handle this?
have you looked into flash data they can be used for this purpose to show messages like success, errors and warnings which are or are not specific to your model attributes. It's up to you where you want o use them.
I mostly insert data or save models within transaction block and there when I am saving multiple models I use try catch block to get the errors for any models that occur and use session flash along with ArrayHelper to add errors in the flash message.
For your purpose you can use it the following way.
Set the flash message with
Yii::$app->session->setFlash('error','you are not allowed to perform this message');
and you can get it using the following inside your view
if(Yii::$app->session->hasFlash('error')){
echo Yii::$app->session->gettFlash('error');
}
a more sophisticated approach towards this is \kartik\widgets\AlertBlock
install it using composer
php composer.phar require kartik-v/yii2-widget-alert "*"
Then create a file called alerts.php in layouts folder with the following code
use kartik\widgets\AlertBlock;
AlertBlock::widget (
[
'useSessionFlash' => false ,
'type' => AlertBlock::TYPE_GROWL ,
'alertSettings' => [
'settings' => [
'type' => kartik\widgets\Growl::TYPE_SUCCESS ,
'icon' => 'glyphicon glyphicon-ok-sign' ,
'title' => 'Note' ,
'showSeparator' => true ,
'body' => Yii::$app->session->getFlash ( 'success' )
] ,
]
] );
AlertBlock::widget (
[
'useSessionFlash' => false ,
'type' => AlertBlock::TYPE_GROWL ,
'alertSettings' => [
'settings' => [
'type' => kartik\widgets\Growl::TYPE_INFO ,
'icon' => 'glyphicon glyphicon-ok-sign' ,
'title' => 'Note' ,
'showSeparator' => true ,
'body' => Yii::$app->session->getFlash ( 'info' )
] ,
]
] );
AlertBlock::widget (
[
'useSessionFlash' => false ,
'type' => AlertBlock::TYPE_GROWL ,
'alertSettings' => [
'settings' => [
'type' => kartik\widgets\Growl::TYPE_DANGER ,
'icon' => 'glyphicon glyphicon-ok-sign' ,
'title' => 'Note' ,
'showSeparator' => true ,
'body' => Yii::$app->session->getFlash ( 'error' )
] ,
]
] );
AlertBlock::widget (
[
'useSessionFlash' => false ,
'type' => AlertBlock::TYPE_GROWL ,
'alertSettings' => [
'settings' => [
'type' => kartik\widgets\Growl::TYPE_DANGER ,
'icon' => 'glyphicon glyphicon-ok-sign' ,
'title' => 'Note' ,
'showSeparator' => true ,
'body' => Yii::$app->session->getFlash ( 'danger' )
] ,
]
] );
AlertBlock::widget (
[
'useSessionFlash' => false ,
'type' => AlertBlock::TYPE_GROWL ,
'alertSettings' => [
'settings' => [
'type' => kartik\widgets\Growl::TYPE_WARNING ,
'icon' => 'glyphicon glyphicon-ok-sign' ,
'title' => 'Note' ,
'showSeparator' => true ,
'body' => Yii::$app->session->getFlash ( 'warning' )
] ,
]
] );
and then include it in your layout file after $this->beginBody() call like below
<?= Yii::$app->view->renderFile ( '#frontend/views/layouts/alerts.php' ); ?>
then you just have to set the flash message and that is it you won't even have to call getFlash(), the extension will display it automatically you have the following variables available
success
info
danger
warning
error
set using Yii::$app->session->setFlash('danger','You cannot do this');
EDIT:
Note: Whenever you are redirecting after setting the flash message remember to use return along with redirect() otherwise you may face the problem that the messages are not showing up.
return $this->redirect(['index']);
EDIT 2:
you are trying to add an error message for any particular model that is related to the model currently being saved and you want some soultion that would allow you to throw exceptions and show them in a nicely formatted error message, so the problem you are facing is setting the error message, if i would do it i would use the following approach. Lets say i have a actionTest() like below which is saving the form on submission.
public function actionTest() {
$model = new Campaign();
if ($model->load(Yii::$app->request->post())) {
//start transaction block
$transaction = Yii::$app->db->beginTransaction();
try {
if (!$model->save()) {
//throw an exception if any errors
throw new \Exception(implode("<br />",\yii\helpers\ArrayHelper::getColumn($model->errors, 0,false)));
}
//commit the transaction if there arent any erorrs to save the record
$transaction->commit();
} catch (\Exception $ex) {
//roll back the transaction if any exception
$transaction->rollBack();
//catch the error and display with session flash
Yii::$app->session->setFlash('danger',$ex->getMessage());
}
}
$this->render('test');
}
Another Option then picking a random attribute is to throw exceptions with a specific errorcode. Create a final class with Error Code constants with their messages. Then Put your save function call within a try Catch Block and Catch all specific exceptions and Return the Message to the Frontend
I'm trying to create a XML import module that will convert given file to CSV format and then use that CSV to import categories and products.
I have a working configuration page made with getContent() it basically calls a method that generates this form via $helper->generateForm(). $helper is a HelperForm() object.
protected function getConfigForm()
{
return array(
'form' => array(
'legend' => array(
'title' => $this->l('Settings'),
'icon' => 'icon-cogs',
),
'input' => array(
array(
'type' => 'file',
'label' => $this->l('XML file'),
'name' => 'XMLIMPORT_XML_FILE',
'desc' => $this->l('Select file you wish to import.'),
'required' => true
),
array(
'col' => 3,
'type' => 'text',
'prefix' => '<i class="icon icon-envelope"></i>',
'desc' => $this->l('Enter a valid email address'),
'name' => 'XMLIMPORT_LINES',
'label' => $this->l('Records per file'),
),
),
'submit' => array(
'title' => $this->l('Save'),
),
),
);
}
I need to get this data to my XML converter. How do I upload a file (around 10-20MB) to Prestashop to be then able to do other stuff with it? How to save it permanently on the server?
I tried doing this:
return array(
'XMLIMPORT_XML_FILE' => Configuration::get('XMLIMPORT_XML_FILE', null),
'XMLIMPORT_LINES' => Configuration::get('XMLIMPORT_LINES', 1000)
);
And after that this:
$form_values = $this->getConfigFormValues(); // returned array from above
foreach (array_keys($form_values) as $key)
Configuration::updateValue($key, Tools::getValue($key));
And later using my own class for XML conversion like this, hoping that it will give me file handle.
$xml_converter = new XMLToCSVConverter(Configuration::get('XMLIMPORT_XML_FILE'), 'output', 'example_products.php');
Apparently it didn't as nothing happens. The class itself is working fine outside of Prestashop module. The constructor is __construct($xml_file, $csv_filename, $template_file).
I need to pass the file I upload to that constructor. I've been struggling for days now.
#edit: I can see the contents of the file inside the HTTP call when submit is clicked. But how do I pass that file to my class?
As far as I remember 'type' => 'file', doesn't actually save any values in the database. This type is only meant to output a file field in your form.
After submitting, you should then do you custom processing with $_FILES['XMLIMPORT_XML_FILE'] : move to upload/ or whereever you want.
'XMLIMPORT_XML_FILE' => Configuration::get('XMLIMPORT_XML_FILE', null), won't return you anything. After uploading you my wish to save the uploaded file path here, but it won't show up next time in the form unless you build the output yourself.
Module configratuon is meant to save text config values. Handling files is trickier and you have to do them yourself each time.
EDIT:
To intercept the saving process, look up the submit button name and make an if statement:
public function getContent() {
if(Tools::isSubmit('submitButtonName')) {
error_log(print_r($_FILES, 1));
}
}
There's probably a function postProcess which does the same (it looks like you copied the methods from a default module).
prestashop handles the image upload with ImageManager class, this class contains more methods which are useful for handling image upload, resize etc.. so its better refer the default homeslider module for the image upload using a module. This module is handling the image upload process in postProcess method with the help of ImageManager class, this class methods will do the all the processes related to upload.
I am trying to handle errors on my website. I logs each error in my log files, but I would like to know how to customize the message that is recorded in the log file.
For now, I get this message:
2013/09/30 10:08:59 [error] [exception.CException] exception
'CException' with message 'Error test' in
myDomain.com\protected\controllers\SiteController.php:234
Can you help me?
For manual customization log messages you need to create your own LogRoute class. In your situation you need inherit class from CFileLogRoute and override method formatLogMessage (such in example):
class MyFileLogRoute extends CFileLogRoute{
protected function formatLogMessage($message,$level,$category,$time)
{
//enter code here your custom message format
return #date('Y/m/d H:i:s',$time)." [$level] [$category] $message\n";
}
}
Than configure your configuration file:
'log' => array(
'class' => 'CLogRouter',
'routes' => array(
array(
'class' => 'MyFileLogRoute',
'levels' => 'error, warning, info',
'categories' => 'application.*',
'logPath' => dirname(__FILE__).'/../../../../../logs/',
),
...
And yes, #ragingprodigy is right: you can set define('YII_DEBUG', 0) or define('YII_TRACE_LEVEL', 0) in index.php to remove stack trace from log messages
I'm just starting to use Zend Framework and was following the quick start documentation for the latest version (1.11.10). Everything was going just fine, but when I placed the form code and ran the application, the form did not render. My code is exactly like http://framework.zend.com/manual/en/learning.quickstart.create-form.html
On the view, I can dump the form just fine with var_dump($this->form);
I've tried echo $this->form(), echo $this->form->render(), but nothing appeared... What could it be?
This problem can occur when Zend can't find the template file for an element. Look at following code:
$element->setDecorators(array(
array('ViewScript',
array(
'viewScript' => 'directory/_input.phtml'
)
)
));
The file _input.phtml must be in the right folder for this Controller. Otherwise Zend can't find the template for input and can't successfully render your element and will not show anything.
Make sure you pass the form to the view from the controller.
In your action handler:
$this->view->form = $my_form;
In your view:
echo $this->form;
I suspected that this was the cause of your problem because Zend Framework doesn't complain if you try to echo a parameter that doesn't exist. (i.e. echo $this->some_fake_parameter won't do anything)
Ok so i tried your code, and it worked for me no problem.
Here is everything:
Controller
<?php
class IndexController extends Zend_Controller_Action
{
public function myTestAction()
{
$form = new Form_Guestbook();
// ... processing logics
if($this->getRequest()->isPost())
{
if($form->isValid($this->getRequest()->getPost()))
{
var_dump($form->getValues());
}
}
$this->view->assign('form', $form);
}
}
Form
<?php
class Form_Guestbook extends Zend_Form
{
public function init()
{
// Set the method for the display form to POST
$this->setMethod('post');
// Add an email element
$this->createElement('text', 'email', array(
'label' => 'Your email address:',
'required' => true,
'filters' => array('StringTrim'),
'validators' => array(
'EmailAddress',
)
));
// Add the comment element
$this->addElement('textarea', 'comment', array(
'label' => 'Please Comment:',
'required' => true,
'validators' => array(
array('validator' => 'StringLength', 'options' => array(0, 20))
)
));
// Add a captcha
$this->addElement('captcha', 'captcha', array(
'label' => 'Please enter the 5 letters displayed below:',
'required' => true,
'captcha' => array(
'captcha' => 'Figlet',
'wordLen' => 5,
'timeout' => 300
)
));
// Add the submit button
$this->addElement('submit', 'submit', array(
'ignore' => true,
'label' => 'Sign Guestbook',
));
// And finally add some CSRF protection
$this->addElement('hash', 'csrf', array(
'ignore' => true,
));
}
}
?>
View
<?php echo $this->form->render(); ?>
can be seen on: http://yaconiello.com/index/my-test
If this isnt working for you, you may be having a configuration error.
I had a problem like that (exact same form, since it is eclipse example)
My problem was due to misunderstanding. Since I thought that I have to directly access to the view script. I entered in the browser something like: hostname/application/view/script/something.php
But in zend all accesses should be through public folder. You have to access to the view like this: hostname/app_name/public/guestbook
hope that would help you