Zend 2 Rotate logging - php

I use the Zend Log for logging information to my logfile. I am looking forward for a way to automatically write in monthly logfiles like logfile201601.log, logile201602.log etc.
Is there a way to to achieve that ? Any hints or a tutorial ? Didn't found anything like that on my current research.
My current configuration:
'factories' => array(
'Zend\Db\Adapter\Adapter' => 'Zend\Db\Adapter\AdapterServiceFactory',
'Zend\Log' => function ($sm) {
$logger = new Zend\Log\Logger(array(
'writers' => array(
'stream' => array(
'name' => 'stream',
'options' => array(
'stream' => './data/log/logfile2016.log',
'formatter' => array(
'name' => 'simple',
'options' => array(
'dateTimeFormat' => 'Y-m-d H:i:s'
)
)
)
)
)
));
return $logger;
},
);

Because Zend will automatically create the log file, you can just dynamically create your log file with the date() function:
// ...
'stream' => './data/log/logfile'.date("Ym").'.log',
// ...
Note that the log directory must be writable.

Related

Invalid arguments for console cron route in Zend Framework 2

I'm trying to make a cron app in my zf2 project but it gave me always the following message :
Reason for failure: Invalid arguments or no arguments provided
My code is this:
module.config.php
'controllers' => array(
'invokables' => array(
'Sync\Controller\Cron' => 'Sync\Controller\CronController',
'Sync\Controller\Index' => 'Sync\Controller\IndexController'
),
),
'console' => array(
'router' => array(
'routes' => array(
'user-reset-password' => array(
'options' => array(
'route' => 'user resetpassword [--verbose|-v] <userEmail>',
'defaults' => array(
'controller' => 'Sync\Controller\Index',
'action' => 'password'
)
)
),
'cron' => array(
'options' => array(
'route' => 'cron [full|center]',
'defaults' => array(
'controller' => 'Sync\Controller\Cron',
'action' => 'full'
)
)
)
)
)
)
CronController.php
class CronController extends AbstractActionController
{
public function fullAction()
{
$request = $this->getRequest();
if (!$request instanceof ConsoleRequest) {
throw new \RuntimeException('You can only use this action from a console!');
}
return("hi");
}
public function centerAction()
{
}
}
Given that a matching php binary is in the path you can then call from your application folder:
php public/index.php cron full
or just
php public/index.php cron (since the route defaults to the fullAction)

Zend Framework 2.3 Translation ignoring manual setLocale() - Possible gettext issue

I'm new to ZF2, and have tried setting up a locale switcher. The code seems to work, but no matter how I've tried, I can't get the switch to happen. I have localised DB calls, which all work fine, but the default gettext/Zend Translate never changes from the default locale.
My code is as follows:
module.config.php
<?php
return array(
'website' => 'o',
'accepted_locales' => array(
'en_GB' => array(
'country' => 'gb',
'language' => 'en',
'display_name' => 'English',
),
'no_NO' => array(
'country' => 'no',
'language' => 'no',
'display_name' => 'Norsk',
),
),
'default_locale' => 'en_GB',
'controllers' => array(
'invokables' => array(
'Foo\Controller\Bar' => 'Foo\Controller\BarController',
),
),
'router' => array(
'routes' => array(
'oranisation' => array(
'type' => 'segment',
'options' => array(
'route' => '/[:controller][/:action][/:id]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
),
'defaults' => array(
'__NAMESPACE__' => 'Foo\Controller',
'controller' => 'Bar',
'action' => 'index',
),
),
),
),
),
'translator' => array(
'translation_file_patterns' => array(
array(
'type' => 'gettext',
'base_dir' => __DIR__ . '/../language',
'pattern' => '%s.mo',
),
),
),
'view_manager' => array(
'template_path_stack' => array(
'Organisation' => __DIR__ . '/../view',
),
),
'view_manager' => array(
'display_not_found_reason' => true,
'display_exceptions' => true,
'doctype' => 'HTML5',
'template_map' => array(
'layout/layout' => __DIR__ . '/../view/layout/layout.phtml',
[...]
),
'template_path_stack' => array(
__DIR__ . '/../view',
),
),
);
Custom Abstract Controller - method called for all actions on all controllers in the project
/**
* Determines most appropriate locale by checking browser locale, then using a default if
* browser is unsupported.
*
* #return String
*/
protected function getBestLocale()
{
$locales = $this->getServiceLocator()->get('Config')['accepted_locales'];
if ( isset($_GET['locale']) && in_array($_GET['locale'], array_keys($locales)) ) {
// If locale has been set manually, and is valid, configure the translator
$locale = $_GET['locale'];
} else {
if ( in_array($this->getRequest()->getCookie()->locale, array_keys($locales)) ) {
// If the locale is already set, ensure it's valid, and confirm the current locale
$locale = $this->getRequest()->getCookie()->locale;
} elseif ( in_array(locale_accept_from_http($this->getRequest()->getHeader()), array_keys($locales)) ) {
// If still not set, we will set from the client header
$locale = locale_accept_from_http($this->getRequest()->getHeader());
} else {
// Default
$locale = $this->getServiceLocator()->get('Config')['default_locale'];
}
}
$cookie = new SetCookie('locale', $locale, time()+60*60*24*30, null, 'localhost');
$this->getResponse()->getHeaders()->addHeader($cookie);
Locale::setDefault($locale);
$this->getServiceLocator()->get('Translator')->setLocale($locale);
return $locale;
}
I have translation files (.po/.mo set up for en_GB and no_NO) and I'm calling the following in my views:
<?php echo $this->translate('File list'); ?>
I ALWAYS get the untranslated strings.
There seem to be various ways of implementing this, and the variety is quite confusing - so to be specific, I'm using ZF 2.3.0. What am I missing please? Thanks in advance.
Zend supported locales list : http://framework.zend.com/manual/1.12/en/zend.locale.appendix.html
Zend not support no_NO . May be better use nn_NO or nb_NO or something else .
OK, it's a bit of a hack, but I got it working - the translator didn't seem to be populating correctly, so $this->translate('...') wasn't using the translate object I was configuring for some reason, and by adding the lines:
$translator = $this->getServiceLocator()->get('translator');
$view->setVariable('translator', $translator);
I can now use:
<?php echo $this->translator->translate('...'); ?>
Which has the desired effect. If anybody has a good way of re-attaching these translator variables, I'd still appreciate it, because this still seems like an extremely hack-ish solution.

Multiple loggers

I'd like to create multiple loggers where different areas of my app will log to different files. For example, all the classes associated with getting the users data would log to a user.log, all functionality of making purchases going to a purchase.log. I am using the configuration array method for setting up the logger & appenders. In my index.php:
require_once('log4php/Logger.php');
require_once('classB.php');
require_once('classA.php');
Logger::configure(array(
'rootLogger' => array('appenders' => array('default')),
'classALogger' => array('appenders' => array('classAAppender')),
'appenders' => array(
'default' => array(
'class' => 'LoggerAppenderEcho',
'layout' => array(
'class' => 'LoggerLayoutSimple'
)
),'classAAppender' => array(
'class' => 'LoggerAppenderFile',
'additivity' => false,
'layout' => array(
'class' => 'LoggerLayoutSimple'
),
'params' => array(
'file' => 'log/classA.log',
'append' => true
)
)
),
));
$logger = Logger::getLogger("main");
$logger->info('message from index' . '<br>');
$classA = new ClassA();
$classA->test();
Class A is as follows:
class ClassA
{
public function test()
{
$logger = Logger::getLogger("classALogger");
$logger->error('from ClassA');
}
}
I am able to log to the default or root logger but am not able to log to, in this example, classALogger. Any suggestions?

Yii framework new column in database not showing in output of $model->getAttributes() method call?

Yii version 1.1.8
I have added a column to a table in a mysql database,
but the new column is not showing in output of $model->getAttributes() method call
I deleted all files in protected/runtime folder, but still no column
config: 'schemaCachingDuration' => 0, // in seconds. <1 means off
I can add data to the new column directly in the database.
Are there any other things that I can do to debug this?
index.php
<?php
// change the following paths if necessary
$yii=dirname(__FILE__).'/../../framework/yii.php';
$config=dirname(__FILE__).'/protected/config/main.php';
// remove the following line when in production mode
//debug
defined('YII_DEBUG') or define('YII_DEBUG',true );
//show profiler
defined('YII_DEBUG_SHOW_PROFILER') or define('YII_DEBUG_SHOW_PROFILER',true);
//enable profiling
defined('YII_DEBUG_PROFILING') or define('YII_DEBUG_PROFILING',true);
//trace level
defined('YII_TRACE_LEVEL') or define('YII_TRACE_LEVEL',0);
//execution time
defined('YII_DEBUG_DISPLAY_TIME') or define('YII_DEBUG_DISPLAY_TIME',false);
require_once($yii);
Yii::createWebApplication($config)->run();
main.php
<?php
return CMap::mergeArray(array(
'timeZone'=>'UTC',
'basePath' => dirname(__FILE__) . DIRECTORY_SEPARATOR . '..',
'catchAllRequest' => null, // null if online, array('site/offline') if offline,
'sourceLanguage' => 'en_ca',
'theme' => 'td',
'charset' => 'UTF-8',
'preload' => array('log'),
'import' => array(
'application.models.*',
'application.components.*',
'application.extensions.*'
),
'modules' => array(
),
// application components
'components' => array(
'format' => array(
),
'user' => array(
// enable cookie-based authentication
'allowAutoLogin' => true,
'autoRenewCookie' => true,
),
'widgetFactory' => array(
'enableSkin' => true,
),
'urlManager' => array(
),
),
'db' => array(
'class' => 'CDbConnection',
'connectionString' => 'mysql:host=localhost;dbname=mydb',
'emulatePrepare' => true,
'initSQLs'=>array("set time_zone='+00:00'"),
'username' => 'root',
'password' => '',
'charset' => 'utf8',
'tablePrefix' => 'tbl_',
'enableParamLogging' => true, //show parameter values in log
// 'schemaCachingDuration' => 0, // in seconds. <1 means off
'enableProfiling' => YII_DEBUG_PROFILING, //show sql profile info in log
'nullConversion' => true,
//'initSQLs'=>array('set time_zone="+00:00"')
),
'errorHandler' => array(
),
'log' => array(
'class' => 'CLogRouter',
'routes' => array(
array(
'class' => 'CFileLogRoute',
'levels' => 'error, warning',
'filter' => 'CLogFilter',
'enabled' => !YII_DEBUG
),
array(
'class' => 'CPhpMailerLogRoute',
'levels' => 'error',
'emails' => 'neilmcguigan+tderror#gmail.com',
'filter' => 'CLogFilter',
'enabled' => false,
),
array(
'class' => 'CWebLogRoute', // show log messages on web pages
'enabled' => YII_DEBUG,
'filter' => 'CLogFilter',
//'showInFireBug' => false
),
array(
'class' => 'CProfileLogRoute',
'enabled' => YII_DEBUG,
'showInFireBug' => false
)
),
),
'request' => array(
),
'securityManager'=>array(
)
),
// application-level parameters that can be accessed
// using Yii::app()->params['paramName']
'params' => array(
),
), require(dirname( __FILE__ ) . '/override.php'));
Having just went through this problem -- I found out the new field names need to be in the attributeLabels function in the model
public function attributeLabels()
{
return array(
'id' => 'ID',
'newfield' => 'New Field',
...
Be careful with using the "better still update overwrite your whole model" suggestion if you are like me and have a lot of custom code in your models. As Sankalp Singha suggests, Just copy the "diff" (green part) from using gii and add the part from attributeLabels to your code.
After you have added a new column in your table then just go to Gii and then click on model generator. In that put the name of your table again and then click preview. There would be an option of diff click on that and then copy the highlighted green code and copy paste it in your original modal or better still update overwrite your whole modal. Then check if you are able to get the values inside and are able to get the attributes. This should work.

Combining HeadScript javascript with widmogrod/zf2-assetic-module and js in multiple modules

Running into a bit of a hurdle, and I can't find any supporting documentation. My use case is fairly simple. The Application module has javascript that should go into the head, and one of my other modules, Foo also has script that should go into the head. I assumed that this Assetic module could solve that. Here's what I inferred:
Application Config
/**
* Assetic
*/
'assetic_configuration' => array(
'buildOnRequest' => true,
'cacheEnabled' => false,
'webPath' => realpath('public/assets'),
'basePath' => 'assets',
'default' => array(
'assets' => array(
'#base_css',
'#head_js',
),
'options' => array(
'mixin' => true,
),
),
'modules' => array(
'application' => array(
# module root path for yout css and js files
'root_path' => __DIR__ . '/../assets',
# collection of assets
'collections' => array(
'base_css' => array(
'assets' => array(
'css/*.css',
),
'filters' => array(),
'options' => array(),
),
'head_js' => array(
'assets' => array(
'js/*.js',
),
'filters' => array(),
),
'base_images' => array(
'assets'=> array(
'images/*.png',
),
'options' => array(
'move_raw' => true,
)
),
),
),
),
),
and then in my Foo module...
Foo Module config
/**
* Assetic
*/
'assetic_configuration' => array(
'default' => array(
'assets' => array(
'#base_css',
'#head_js',
),
'options' => array(
'mixin' => true,
),
),
'modules' => array(
'foo' => array(
# module root path for yout css and js files
'root_path' => __DIR__ . '/../assets',
# collection of assets
'collections' => array(
'base_css' => array(
'assets' => array(
'css/*.css'
),
'filters' => array(),
'options' => array(),
),
'head_js' => array(
'assets' => array(
'js/*.js' // relative to 'root_path'
),
'filters' => array(),
'options' => array(),
),
'base_images' => array(
'assets'=> array(
'images/*.png'
),
'options' => array(
'move_raw' => true,
)
),
),
),
),
),
With this config, unfortunately, only the Foo module's javascript makes its way into head_js.js. I'm feeling like that meme with Milton in it, going "I was told there would be asset combining!" :)
Any help you could offer, is appreciated.
Thanks!
Ok - I've figured it out. Hopefully this helps someone else one day. The configuration keys I noted above weren't inaccurate -- but -- they weren't crafted properly when a secret undocumented feature is considered; had to crack the source open to learn that including the word 'head' in an asset bundle actually autoloads it in the head. It's a nice feature in the end, but really a head scratcher when you're not aware of it.

Categories