I am trying to use post_system or post_controller hook to catch and log all insert and update queries in a database table. But, what happens is that the $queries = $CI->db->queries; statement doesn't seem to catch any insert or update statement at all. It only catches SELECT statements even when new data is inserted or old data is updated in respective views/controllers.
Here is my relevant code:
hooks.php
<?php
if (!defined('BASEPATH'))
exit('No direct script access allowed');
// also tried with post_controller hook
$hook['post_system'] = array(
'class' => 'Db_query_log',
'function' => 'log_db_queries',
'filename' => 'db_log.php',
'filepath' => 'hooks'
);
hooks/db_log.php
<?php
class Db_query_log {
function __construct() {
//nothing special
}
function log_db_queries() {
$CI = & get_instance();
$queries = $CI->db->queries;
foreach ($queries as $key => $query) {
echo $query . "<br>";
// all statements displayed are SELECT statements even for UPDATE and INSERT operations performed by controllers where data is actually changed
}
}
}
What could be the culprit here? Am I missing something or this hook simply ignores INSERT/UPDATE operations?
Any help would be appreciated, thanks!
Use post_controller instead of post_system :
$hook['post_controller'] = array(
'class' => 'Db_query_log',
'function' => 'log_db_queries',
'filename' => 'db_log.php',
'filepath' => 'hooks'
);
To achieve this open any helper file and put this code at the bottom
function log_que($sql) {
$filepath = APPPATH . 'logs/Query-log-' . date('Y-m-d') . '.php';
$handle = fopen($filepath, "a+");
fwrite($handle, $sql." \n Execution Time: ".date("Y-m-d H:i:s")."\n\n");
fclose($handle);
}
after this go to system/database/DB_driver.php and find function named "query"
and put this below code on top inside the function.
log_que($sql);'
then all the queries will save in a file inside the application/logs folder.
you can put if condition if you want to save only specific queries. LIKE
if(preg_match('/INSERT/',$sql)) {
fwrite($handle, $sql." \n Execution Time: ".date("Y-m-d H:i:s")."\n\n");
}
Related
I would like to create a file based on template Twig (and one parameter).
My file generated correctly with replace variable with my data. But if I change data my controller symfony generated always the same file with the same content.
My varDumper content (the text/plain character represent file) is good. It's change always with change variable content. But the writing file always generate the same content...
PHP seems do not caching with fwrite ou file_put_contents function but my content never change. I also disable caching for twigEngine but same result.
Can you help me to writing file with good last content.
All code is in a controller symfony. I keep comment code for your understanding all my test :
public function createEntityAction()
{
$rootDir = $this->getParameter('kernel.root_dir');
$templateDir = $rootDir . '/../src/CmsBundle/Resources/views/Entity/templateFile/';
$filename = 'test.php';
$pathFile = $templateDir . $filename;
$twigEngine = $this->get('twig');
$twigEngine->setCache(false);
$twigEngine->disableAutoReload();
// $loader = new Twig_Loader_Filesystem($templateDir);
// $twig = new Twig_Environment($loader, [
// 'cache' => '/path/to/compilation_cache',
// 'cache' => false,
// ]);
$baseTemplate = $twigEngine->loadTemplate('#Cms/Entity/templateFile/baseEntity.html.twig');
$script = $baseTemplate->render(['slug' => 'product-333']);
\Symfony\Component\VarDumper\VarDumper::dump($script);
if (file_exists($pathFile))
{
clearstatcache(true);
$ret = unlink($pathFile);
\Symfony\Component\VarDumper\VarDumper::dump($ret);
}
$file = fopen($pathFile, 'w+');
fwrite($file, $script);
fclose($file);
// file_put_contents($pathFile, $script);
return $this->render('#Cms/Entity/create.html.twig', []);
}
The final file content is always the same if I change the "slug" variable.
It looks to me like you're missing a variable in your controller. There should be something like this createEntityAction($slug), then this line should be $baseTemplate->render(['slug' => $slug); Right now it is doing exactly what you are telling it, you have a hard coded string for the slug...
If you post your controller definition it would help (annotations or yaml)
I need to trim every $this->input->get('q', true); in my projects. is there a way to do this instead of adding trim() every time?
Naim Malek told me to use helper, but I don't quite understand how it would work in this case..
You can use hooks for trimming every 'q' get parameter.
First enable hooks in application/config/config.php
$config['enable_hooks'] = TRUE;
Then create a file with custom name (example: Trim_hooks.php) in application/hooks and write below code in hook config file(application/config/hooks.php) file.
$hook['post_controller_constructor'] = array(
'class' => 'Trim_hook',
'function' => 'run',
'filename' => 'Trim_hooks.php',
'filepath' => 'hooks',
);
At the end create Trim_hooks.php file in application/hooks:
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Trim_hook
{
function run()
{
if (isset($_GET['q']))
{
$_GET['q'] = trim($_GET['q']);
}
}
}
Every time you have q parameter in GET, it's trimming after run controllers constructoror.
The custom route doesn't work correctly and always routes to user.htm
index.php
$routes = [
"/" => "index.htm",
"/user/id=#id" => "user.htm","/user/#id" => "user.htm",
];
foreach ($routes as $path => $file) {
$f3->route("GET ".$path,
function($f3){
global $file,$path;
echo View::instance()->render($file);
}
);
}
try this:
$routes = [
"/" => "index.htm",
"/user/id=#id" => "user.htm",
"/user/#id" => "user.htm",
];
foreach ($routes as $path => $file)
{
$f3->route("GET " . $path,
function ($f3) use ($file)
{
echo View::instance()->render($file);
}
);
}
The answer from Bryan Velastegui is the correct one. But here's why your code didn't work:
$f3->route() maps each route URI to a function (called the "route handler"), without executing it.
the foreach loop stores successively the following values into the $file variable: index.html, user.htm and user.htm (again). Therefore, at the end of the loop, $file holds user.htm.
once you call $f3->run(), the framework executes the route handler matching the current route, which itself refers to the global $file variable, holding user.htm.
Generally, you shouldn't be using the global keyword. That will just create unexpected issues, just as the one you've faced. Also that doesn't help for code maintainability.
I advise you to read the docs about the use keyword to understand how Bryan Velastegui's code is working.
Thanks in advance for any and all advice.
I have one file (content file) where an array is created like so:
$config['plugins']['BannerRotate'] = array(
'container' => 'abroadView',
'arrows' => true,
'auto' => true,
'speed' => '15000',
'width' => '300px',
'height' => '220px',
'tags' => 'slider'
);
Which in turn is picked up by the so-called 'template system' and the layout is rendered with the page (and that array) as the argument (pretty standard).
That array is then used by the template system to generate a new object like so:
if(isset($GLOBALS['config']['plugins'])){
foreach($GLOBALS['config']['plugins'] as $plugin => $ary){
$$plugin = new Ispweb_Plugindaemon(CURRENTSRV,getcwd().'/',
$GLOBALS['config']['plugins'][$plugin],$plugin);
// this statement is simply the result of the eval statement below
}
}
So then, since the name of the plugin in this case is BannerRotate, the object is $BannerRotate (variable variable). I'm doing this so I can have multiple plugin objects per page. This object is then used to call the jQuery plugin using member function $BannerRotate->getJS(). These member function calls are located WITHIN the templating system (IMPORTANT).
If I call a member function inside the same file as the initial array [OUTSIDE THE TEMPLATING SYSTEM] (the file that I'm buffering in order to create the object in the first place), everything dies. This doesn't make sense to me because if I var_dump($BannerRotate), I get a full object. However, say in that content file I do $BannerRotate->printNoscript(), everything disappears and the object is never created. I then get a fatal error that I'm calling a member function of a non-object. THAT IS THE PROBLEM.
Here is what I'm doing within the templating system to buffer the content file (and create the object(s)):
ob_start();
include $core_page_content; // the content file (where initial array is)
if(isset($GLOBALS['config']['plugins'])){
foreach($GLOBALS['config']['plugins'] as $plugin => $ary){
$ins[] = $plugin;
}
}
$t = ob_get_contents();
ob_end_clean();
foreach($ins as $in){
$a = CURRENTSRV; // a,b,c,d are just making the eval statement more clean
$b = getcwd().'/';
$c = array();
foreach($GLOBALS['config']['plugins'][$in] as $key => $value){
$c[$key] = $value;
}
$d = $in;
eval("\$$in = new Ispweb_Plugindaemon(\"$a\",\"$b\",\$c,\"$d\");");
echo $$in;
}
include $core_page_content;
$page_content = ob_get_contents();
ob_end_clean();
Does anyone know why I can access the object UNLESS I make a call to one of its member functions while inside the same file?
What can I do?
P.S. I know the setup is not ideal. There's nothing I can do about that.
Thanks!
TL;DR I'm creating an object in file A, with a variable from file B. I buffer file B to get the parameters to feed to file A, create the object, print it into another buffer and include file B in that buffer as well. If file B has a function call to the presumably created object, I get a fatal error: call to member function of non-object.
Additional Notes:
File B:
$config['plugins']['BannerRotate'] = array(
'container' => 'abroadView',
'arrows' => true
);
// page content (XHTML)
File A:
ob_start();
$core_page_content = 'file_b';
include $core_page_content;
if(isset($config['plugins'])){
foreach($config['plugins'] as $plugin => $ary){
$ins[] = $plugin;
}
ob_end_clean();
foreach($ins as $in){
$$in = new Ispweb_Plugindaemon(CURRENTSRV,getcwd().'/',$config['plugins'][$in],$in);
}
include $core_page_content;
$page_content = ob_get_contents();
ob_end_clean();
// later on in the file
include 'top.htm';
include $page_content;
include 'bot.htm';
The problem was variable scope.
Ok here is a method I use for initializing models in my controller actions:
protected $_tables = array();
protected function _getTable($table)
{
if (false === array_key_exists($table, $this->_tables)) {
include APPLICATION_PATH . '/modules/'
. $this->_request->getModuleName() . '/models/' . $table . '.php';
$this->_tables[$table] = new $table();
echo 'test ';
}
return $this->_tables[$table];
}
Then when I call the _getTable() method two times (for example once in init() method and once in the controller action) it prints:
test test test test test test
On top of the page. Shouldn't it just return the object from the _tables array() because of the array_key_exists() check? In other words shouldn't the part inside the array_key_exists() function get executed only once when the method is called multiple times?
UPDATE:
So the problem is this - for some reason the layout gets printed twice (so it's layout printed and inside the layout where there is layout()->content; ?> it prints the layout again). I have no idea why it does this as it worked well on the previous server and also on localhost.
In the snippet you show:
protected $this->_tables = array();
This is not valid syntax, it should be:
protected $_tables = array();
Also, why not just use include_once and let PHP handle this for you? Alternatively, you could use the Zend_Loader. Don't reinvent the wheel.
What you are really looking for is the loading of module based resources. Instead of re-inventing the wheel, why not just use the (module) resource autoloaders of ZF? See the documentation at:
http://framework.zend.com/manual/en/zend.loader.autoloader-resource.html
When you use Zend_Application (I'm assuming you don't), you get these automatically. If you don't you could do something like
$loaders = array();
$frontController = Zend_Controller_Front::getInstance();
foreach($frontController->getControllerDirectory() as $module => $directory) {
$resourceLoader = new Zend_Application_Module_Autoloader(array(
'namespace' => ucfirst($module) . '_',
'basePath' => dirname($directory),
));
$resourceLoader->addResourceTypes(array(
'table' => array(
'path' => 'models/',
'namespace' => 'Table'
));
$loaders[$module] = $resourceLoader;
}
//build array of loaders
$loader = Zend_Loader_Autoloader::getInstance();
$loader->setAutoloaders($loaders);
//set them in the autoloader
This approach is a bit naive, but it should give you nice autoloading.