I'm trying to get a different session configuration for 2 modules.
In my application ini i have a modules set up like :
resources.modules[] =
resources.frontcontroller.moduleDirectory = APPLICATION_PATH "/modules"
resources.frontcontroller.throwerrors = true
resources.layout.layout = "layout"
and for the sessions
resources.session.save_path = APPLICATION_PATH "/temp/session"
resources.session.use_cookies = true
resources.session.use_only_cookies = true
resources.session.gc_maxlifetime = 3600
resources.session.remember_me_seconds = 3600
resources.session.name = "sid"
resources.session.gc_probability = 1
backoffice.resources.session.save_path = APPLICATION_PATH "/temp/bo/session"
backoffice.resources.session.use_cookies = true
backoffice.resources.session.use_only_cookies = true
backoffice.resources.session.gc_maxlifetime = 3600
backoffice.resources.session.remember_me_seconds = 3600
backoffice.resources.session.name = "BOsid"
backoffice.resources.session.gc_probability = 1
but when i go the backoffice module i still have my default configuraton
Any idea what should be the best way to get different sessions for different modules ?
Thanks
I want to advise you another method of config customization for specific modules in ZF:
1. Create for each module config file: /modules/$moduleName/configs/module.ini
2. Add to the root Bootstrap the next code:
protected function _initBootstrap()
{
$_conf = new Zend_Config_Ini(APPLICATION_PATH . "/modules/" . $this->getModuleName() . "/configs/module.ini", APPLICATION_ENV);
$this->_options = array_merge($this->_options, $_conf->toArray());
}
I finally opted for a controller plug-in.
With some code like
class App_Controller_Plugin_Session extends Zend_Controller_Plugin_Abstract
{
public function routeShutdown(Zend_Controller_Request_Abstract $request)
{
$config = Zend_Registry::get('config')->toArray();
if( $this->getRequest()->getModuleName() == 'backoffice' ) {
$conf = $config['sessionBackoffice'];
} else {
$conf = $config['sessionDefault'];
}
Zend_Session::setOptions($conf);
Zend_Session::start();
}
}
The plugin need to be added at first in the registerPlugin stack if you some other plugin that require sessions.
If you have a better solution i'm open.
Related
I'm working with Lumen framework v5.8 (it's the same as Laravel)
I have a command for read a big XML (400Mo) and update datas in database from datas in this file, this is my code :
public function handle()
{
$reader = new XMLReader();
$reader->open(storage_path('app/mesh2019.xml'));
while ($reader->read()) {
switch ($reader->nodeType) {
case (XMLREADER::ELEMENT):
if ($reader->localName === 'DescriptorRecord') {
$node = new SimpleXMLElement($reader->readOuterXML());
$meshId = $node->DescriptorUI;
$name = (string) $node->DescriptorName->String;
$conditionId = Condition::where('mesh_id', $meshId)->first();
if ($conditionId) {
ConditionTranslation::where(['condition_id' => $conditionId->id, 'locale' => 'fr'])->update(['name' => $name]);
$this->info(memory_get_usage());
}
}
}
}
}
So, I have to find in the XML each DescriptorUI element, the value corresponds to the mesh_id attribute of my class Condition.
So, with $conditionId = Condition::where('mesh_id', $meshId)->first(); I get the Condition object.
After that, I need to update a child of Condition => ConditionTranslation. So I just get the element DescriptorName and update the name field of ConditionTranslation
At the end of the script, you can see $this->info(memory_get_usage());, and when I run the command the value increases each time until the script runs very very slowly...and never ends.
How can I optimize this script ?
Thanks !
Edit : Is there a way with Laravel for preupdate multiple object, and save just one time at the end all objects ? Like the flush() method of Symfony
There is a solution with ON DUPLICATE KEY UPDATE
public function handle()
{
$reader = new XMLReader();
$reader->open(storage_path('app/mesh2019.xml'));
$keyValues = [];
while ($reader->read()) {
switch ($reader->nodeType) {
case (XMLREADER::ELEMENT):
if ($reader->localName === 'DescriptorRecord') {
$node = new SimpleXMLElement($reader->readOuterXML());
$meshId = $node->DescriptorUI;
$name = (string) $node->DescriptorName->String;
$conditionId = Condition::where('mesh_id', $meshId)->value('id');
if ($conditionId) {
$keyValues[] = "($conditionId, '".str_replace("'","\'",$name)."')";
}
}
}
}
if (count($keyValues)) {
\DB::query('INSERT into `conditions` (id, name) VALUES '.implode(', ', $keyValues).' ON DUPLICATE KEY UPDATE name = VALUES(name)');
}
}
I try to create controller that handles ajax requests.
I found out, that I have to add this to my TS config:
ajaxCall = PAGE
ajaxCall {
typeNum = 999
config.disableAllHeaderCode = 1
config.metaCharset = UTF-8
xhtml_cleaning = 0
admPanel = 0
10 = COA
10 < tt_content.list.20.registration_userregistration
}
And my controller looks like this:
/**
* JSONController
*/
class JSONController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController {
/**
* #var string
*/
protected $defaultViewObjectName = 'TYPO3\\CMS\\Extbase\\Mvc\\View\\JsonView';
/**
* action test
*
* #return string
*/
public function testAction() {
$this->view->assign('value', "001");
}
}
This works, I get a blank page with "001" on it. But if I look at the source, there are 4 empty lines, and "001" is in the 5th line.
-empty-
-empty-
-empty-
-empty-
"001"
I have no idea why...
I don't get, why are you using some view for rendering JSON ???
public function testAction() {
$data = array('value'=>'001');
return json_encode($data);
}
Of course you should set Content-type: application/json - where do you prefer - in your TS or directly in the action before return;
Other clue: maybe it's caused by tt_content (just guesing), for JSON actions it's best to include them directly via Bootstrap, first register new FE plugin in your ext_localconf.php:
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
'VENDORNAME.' . $_EXTKEY,
'JsonDataPlugin',
array('JSON' => 'test',),
array('JSON' => 'test',)
);
And modify your TS:
myAjaxPage = PAGE
myAjaxPage {
typeNum = 999
10 = USER
10 {
userFunc = TYPO3\CMS\Extbase\Core\Bootstrap->run
extensionName = Yourextname
pluginName = JsonDataPlugin
vendorName = VENDORNAME
}
config {
disableAllHeaderCode = 1
additionalHeaders = Content-type:application/json
xhtml_cleaning = 0
admPanel = 0
debug = 0
no_cache = 1
}
}
(don't forget to change Yourextname and VENDORNAME for your own, also clear the system cache)
Finally: Check all your files and make sure that there's no empty lines before <?php and after ?> (the best option is to remove ?> from each file - and let PHP to terminate script at the end of file). Also it can be fixed in the source of TYPO3 as described in other naswer.
Okay, I got it...
I included a file with some functions named user.php
/**
* User service
*
* #var \Whmcs\Registration\Service\User
* #inject
*/
protected $user = NULL;
In this file there were empty lines after the ?> tag. These empty lines were the problem. I deleted them and now everything works fine. :)
I want to create some kind of sitemap in extbase/fluid (based on the pagetree). I have loaded the pages table into a model:
config.tx_extbase.persistence.classes.Tx_MyExt_Domain_Model_Page.mapping.tableName = pages
I have created a controller and repository, but get stuck on the part wich can load the subpages as relation into my model.
For example:
$page = $this->pageRepository->findByPid($rootPid);
Returns my rootpage. But how can I extend my model that I can use $page->getSubpages() or $page->getNestedPages()?
Do I have to create some kind of query inside my model? Or do I have to resolve this with existing functions (like the object storage) and how?
I tried a lot of things but can simply figure out how this should work.
you have to overwrite your findByPid repository-method and add
public function findByPid($pid) {
$querySettings = $this->objectManager->create('Tx_Extbase_Persistence_Typo3QuerySettings');
$querySettings->setRespectStoragePage(FALSE);
$this->setDefaultQuerySettings($querySettings);
$query = $this->createQuery();
$query->matching($query->equals('pid', $pid));
$pages = $query->execute();
return $pages;
}
to get all pages. Than you can write your own getSubpages-method like
function getSubpages($currentPid) {
$subpages = $this->pagesRepository->findByPid($currentPid);
if (count($subpages) > 0) {
$i = 0;
foreach($subpages as $subpage) {
$subpageUid = $subpage->getUid();
$subpageArray[$i]['page'] = $subpage;
$subpageArray[$i]['subpages'] = $this->getSubpages($subpageUid);
$i++;
}
} else {
$subpageArray = Array();
}
return $subpageArray;
}
i didn't test this method, but it looks like this to get alle subpages.
i wonder that i could´t find a typo3 method that return the complete Page-Tree :( So i write a little function (you can use in an extbase extension), for sure not the best or fastes way, but easy to extend or customize ;)
first you need an instance of the PageRepository
$this->t3pageRepository = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\Page\\PageRepository');
this->t3pageRepository->init();
make the init, to set some basic confs, like "WHERE deletet = 0 AND hidden = 0..."
then with this function you get an array with the page data and subpages in. I implement yust up to three levels:
function getPageTree($pid,$deep=2){
$fields = '*';
$sortField = 'sorting';
$pages = $this->t3pageRepository->getMenu($pid,$fields,$sortField);
if($deep>=1){
foreach($pages as &$page) {
$subPages1 = $this->t3pageRepository->getMenu($page['uid'],$fields,$sortField);
if(count($subPages1)>0){
if($deep>=2){
foreach($subPages1 as &$subPage1){
$subPages2 = $this->t3pageRepository->getMenu($subPage1['uid'],$fields,$sortField);
if(count($subPages2>0)){
$subPage1['subpages'] = $subPages2;
}
}
}
$page['subpages'] = $subPages1;
}
}
}
return $pages;
}
Can I change the database config per method in a controller?
$db['default']['db_debug'] = TRUE;
The default is TRUE, while I need to make it false in a certain method to catch the error and do something else (for example show 404 page).
When I tried $this->config->load('database') it fails.
Another question :
Can I check an incorrect query and catch it to some variables rather than displaying it to users other than setting the db_debug config to FALSE?
I checked the code of system/database/DB_Driver and found that:
$this->db->db_debug = FALSE;
will work in my controller to enable/disable the debug thing on the fly.
Expanding on the answer by comenk, you can extend the database class and implement various methods by which to achieve your goal.
First, you'll need to extend the core Loader class by creating a MY_Loader.php file
class MY_Loader extends CI_Loader
{
function __construct()
{
parent::__construct();
}
/**
* Load the Standard and/or Extended Database function & Driver class
*
* #access public
* #return string
*/
function database( $params = '', $return = FALSE, $active_record = NULL )
{
$ci =& get_instance();
if (class_exists('CI_DB') AND $return == FALSE AND $active_record == NULL AND isset($ci->db) AND is_object($ci->db))
{
return FALSE;
}
$my_db = config_item('subclass_prefix').'DB';
$my_db_file = APPPATH.'core/'.$my_db.EXT;
if(file_exists($my_db_file))
{
require_once($my_db_file);
}
else
{
require_once(BASEPATH.'database/DB'.EXT);
}
// Load the DB class
$db =& DB($params, $active_record);
$my_driver = config_item('subclass_prefix').'DB_'.$db->dbdriver.'_driver';
$my_driver_file = APPPATH.'core/'.$my_driver.EXT;
if(file_exists($my_driver_file))
{
require_once($my_driver_file);
$db = new $my_driver(get_object_vars($db));
}
if ($return === TRUE)
{
return $db;
}
// Initialize the db variable. Needed to prevent
// reference errors with some configurations
$ci->db = '';
$ci->db = $db;
}
}
By implementing the above this will allow you to create a MY_DB_mysqli_driver.php whereby mysqli is replaced by whatever driver you're using in your CI database.php config.
At this point you'd add comenk's answer to MY_DB_mysqli_driver.php
function debug_on() {
return $this->db_debug = TRUE;
}
function debug_off() {
return $this->db_debug = FALSE;
}
function in_error() {
return (bool) $this->_error_number();
}
Then in your model/controller,
$this->db->debug_off();
$this->db->query('SELECT * FROM `table`');
if( $this->db->in_error() ) {
show_404();
}
$this->db->debug_on();
you must add function on system/database/DB_driver.php
function debug_on()
{
$this->db_debug = TRUE;
return TRUE;
}
function debug_off()
{
$this->db_debug = FALSE;
return FALSE;
}
after that you can simply do this command to changes at run-time
$this->db->debug_off();
$this->db->reconnect();
$this->db->db_debug = 0; // 0: off, 1: on
That worx for me...
You can look at the $GLOBALS variable to locate this generic setting.
To hide bad SQL (and other errors) from users, you need to set the php error reporting level. CodeIgniter ships in basically development mode.
Go to index.php and replace this
error_reporting(E_ALL);
with this
error_reporting(0);
This is the quick way to do it. You can also implement this using a hook, so you don't have to touch CI files. You can also add logic to that hook so that it only sets it on the production server.
For debugging SQL, you can create a class that inherits from CI_Model, then create all your model classes to extend that class. In that class, you can add code for running queries that writes the queries to the log so that you can debug them easier. This won't help if the query itself is bad, but you should be able to figure that out before you get to that point.
How can I set session expiration time dynamically in codeigniter?
For example, if a user logs in and has the role of admin, the expiration time should be longer than if a user logs in who does not have an admin role.
Thanks.
You can update your session expiration time by increasing this variable in config file:
$config['sess_expiration'] = 'somevalue'.
Set $config['sess_expiration'] = 0, if you want it to never expire.
Here's a good discussion on CI forums:
Dynamically set configuration on session expire doesn’t work
$data = array(
'username' => $this->input->post('username'),
'ADMIN_is_logged_in' => true
);
$this->session->sess_expiration = '14400';// expires in 4 hours
$this->session->set_userdata($data);// set session
None of these solutions address doing this dynamically or require another variable to be added to the session. The solution I came up with for CI 3.0.4 is to extend Session.php.
Create file application/libraries/Session/MY_Session.php
Put the following into the file and modify for your logic of setting the $expiration variable. In my case I am pulling the value from a database. NOTE: If you have different expiration values per user type; there is a chance they could get garbage collected and expire unexpectedly due to different expirations with the same session. In this case I do NOT recommend this approach.
<?php
class MY_Session extends CI_Session
{
public function __construct(array $params = array())
{
parent::__construct($params);
}
/**
* Configuration
*
* Handle input parameters and configuration defaults
*
* #param array &$params Input parameters
* #return void
*/
protected function _configure(&$params)
{
$CI =& get_instance();
$phppos_session_expiration = NULL;
$CI->db->from('app_config');
$CI->db->where("key", "phppos_session_expiration");
$row = $CI->db->get()->row_array();
if (!empty($row))
{
if (is_numeric($row['value']))
{
$phppos_session_expiration = (int)$row['value'];
}
}
$expiration = $phppos_session_expiration !== NULL ? $phppos_session_expiration : config_item('sess_expiration');
if (isset($params['cookie_lifetime']))
{
$params['cookie_lifetime'] = (int) $params['cookie_lifetime'];
}
else
{
$params['cookie_lifetime'] = ( ! isset($expiration) && config_item('sess_expire_on_close'))
? 0 : (int) $expiration;
}
isset($params['cookie_name']) OR $params['cookie_name'] = config_item('sess_cookie_name');
if (empty($params['cookie_name']))
{
$params['cookie_name'] = ini_get('session.name');
}
else
{
ini_set('session.name', $params['cookie_name']);
}
isset($params['cookie_path']) OR $params['cookie_path'] = config_item('cookie_path');
isset($params['cookie_domain']) OR $params['cookie_domain'] = config_item('cookie_domain');
isset($params['cookie_secure']) OR $params['cookie_secure'] = (bool) config_item('cookie_secure');
session_set_cookie_params(
$params['cookie_lifetime'],
$params['cookie_path'],
$params['cookie_domain'],
$params['cookie_secure'],
TRUE // HttpOnly; Yes, this is intentional and not configurable for security reasons
);
if (empty($expiration))
{
$params['expiration'] = (int) ini_get('session.gc_maxlifetime');
}
else
{
$params['expiration'] = (int) $expiration;
ini_set('session.gc_maxlifetime', $expiration);
}
$params['match_ip'] = (bool) (isset($params['match_ip']) ? $params['match_ip'] : config_item('sess_match_ip'));
isset($params['save_path']) OR $params['save_path'] = config_item('sess_save_path');
$this->_config = $params;
// Security is king
ini_set('session.use_trans_sid', 0);
ini_set('session.use_strict_mode', 1);
ini_set('session.use_cookies', 1);
ini_set('session.use_only_cookies', 1);
ini_set('session.hash_function', 1);
ini_set('session.hash_bits_per_character', 4);
}
}
You can handle this with a custom controller. When a user logs in, set a session variable with the time of login. Create custom controller that contains a function in the constructor to check if the user is not admin user and if the timeout has expired. If it has, call $this->session->destroy(); Now, make all your controllers extend that controller instead of the CI base controller.
In Codeigniter 4
Go to the file App=>Config=>App.php
Find the var $sessionExpiration
The default value for this var is 7200
Change it to the value as you want your session to be alive.
The complete config for the session is given below:
public $sessionDriver = 'CodeIgniter\Session\Handlers\FileHandler';
public $sessionCookieName = 'ci_session';
public $sessionExpiration = 7200;
public $sessionSavePath = WRITEPATH . 'session';
public $sessionMatchIP = false;
public $sessionTimeToUpdate = 300;
public $sessionRegenerateDestroy = false;
Session will expire in 10 seconds
$config['sess_expiration']= 10;
Session will not expire
$config['sess_expiration']= 0;
In Codeigniter 4, I do it the other way.
Set the session expiration time to maximal value (for example month for everybody) then in your controller or libraries, if the user is not admin, check the last active time, if time is more than what you need, destroy session and require log in.
use something like this:
$user_type = $this->input->post('user_type');
if ($user_type == 'admin')
{
//set session to non-expiring
$this->session->sess_expiration = '32140800'; //~ one year
$this->session->sess_expire_on_close = 'false';
}
else
{
//set session expire time, after that user should login again
$this->session->sess_expiration = '1800'; //30 Minutes
$this->session->sess_expire_on_close = 'true';
}
//set session and go to Dashboard or Admin Page
$this->session->set_userdata(array(
'id' => $result[0]['id'],
'username' => $result[0]['username']
));
At codeigniter go to applications/config.php and find the below configuration.
$config['sess_expiration'] = 14400; //in seconds
In your login functionality just after user credentials have been verified you can check if user is admin and set different sessions accordingly. Something along these lines
<?php
/*
*Assuming user is successfully veriefied and you've verified id user is admin*/
if($isAdmin==true){
$this->session->sess_expiration = 14400; // 4 Hours
}else{
// For ordinary users
$this->session->sess_expiration = 1800; // 30 minutes
}
$this->session->sess_expire_on_close = FALSE;
I think the most better chooice is using session temp_data and always you can change is dynamically and it is not depended your 'sess_expiration' in config file:
$this->session->set_tempdata('admin_session', true, 72000);
$this->session->set_tempdata('user_session', true, 14400);
where you check admin or user login state, like 'ADMIN_is_logged_in?'
check the remained 'tempdata' lifetime by:
if($this->session->tempdata('admin_session')){
//do something }
else{
//session timeout and is time to destroy all sessions
session_destroy();
}
You can solve the session issue by replacing this:
$config['sess_use_database'] = TRUE;
$config['sess_encrypt_cookie'] = TRUE;
with this:
$config['sess_use_database'] = FALSE;
$config['sess_encrypt_cookie'] = FALSE;