I'm trying to customize the logging functionality of codeigniter. I found this forum thread which describes exactly what I need:
http://codeigniter.com/forums/viewthread/139997/
But I want to do that without altering core files/classes.
I"m trying to alter the log_message function. I've already extended the CI_Log class and that is working well, but now I'm trying to alter log_message() which resides in system/core/Common.php. It isn't actually a class so I can't extend it, it just appears to be a collection of useful functions. I tried redeclaring log_message() and placing it in application/core/Common.php, but that doesn't appear to work. Any ideas how I can go about this?
I believe that the function you actually want to alter is write_log(), correct me if I'm wrong. You can do this by extending the function within application\libraries\MY_Log.php.
I have the following script in my MY_Log.php which emails me any time an error is thrown:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/* Extends the logging class to send an email when an error is triggered */
class MY_Log extends CI_Log {
function __construct()
{
parent::__construct();
}
function write_log($level = 'error', $msg, $php_error = FALSE, $additional, $additional2)
{
if ($this->_enabled === FALSE)
{
return FALSE;
}
$level = strtoupper($level);
if ( ! isset($this->_levels[$level]) OR ($this->_levels[$level] > $this->_threshold))
{
return FALSE;
}
$filepath = $this->_log_path.'log-'.date('Y-m-d').'.php';
$message = '';
if ( ! file_exists($filepath))
{
$message .= "<"."?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); ?".">\n\n";
}
if ( ! $fp = #fopen($filepath, FOPEN_WRITE_CREATE))
{
return FALSE;
}
$message .= $level.' '.(($level == 'INFO') ? ' -' : '-').' '.date($this->_date_fmt). ' --> '.$msg."\n";
flock($fp, LOCK_EX);
fwrite($fp, $message);
flock($fp, LOCK_UN);
fclose($fp);
#chmod($filepath, FILE_WRITE_MODE);
return TRUE;
}
}
If you're not looking to extend the write function, you will need to extend one of the other log functions.
A helper function could work here. You'd have to use it instead of log_message().
Here's what I did:
in application/helpers I created 'new_log_helper.php' (helpers have to end in _helper.php)
I wanted this to add log entries into the database and to track by process (that way I know where to look in the code).
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
* Custom Logging Interface
*
* Add log entries to a log table on the db and track process name
*
* #access public
* #return void
*/
if ( ! function_exists('new_log')) {
function new_log($level = 'error', $message, $process, $php_error = FALSE)
{
if (config_item('log_threshold') == 0) {
return;
}
$CI =& get_instance();
$CI->load->model('new_log','logger', TRUE);
$CI->logger->add_event($process, $level, $message);
log_message($level, $process.': '.$message, $php_error);
}
}
Then when you need it use it like this:
$this->load->helper('new_log');
...
new_log('debug','Something happened','Stack overflow answer');
Anyway I know your issue was years ago but I was looking so maybe someone else is too.
Related
So basically the Benchmark class is very simple and it is quit clear how it works. It "remembers" the time when it was launched and when we want to know how long do the program is executing it just subtract marked time from current time.
Lets look into the code:
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class CI_Benchmark {
public $marker = array();
public function mark($name)
{
$this->marker[$name] = microtime(TRUE);
}
public function elapsed_time($point1 = '', $point2 = '', $decimals = 4)
{
if ($point1 === '')
{
return '{elapsed_time}';
}
if ( ! isset($this->marker[$point1]))
{
return '';
}
if ( ! isset($this->marker[$point2]))
{
$this->marker[$point2] = microtime(TRUE);
}
return number_format($this->marker[$point2] - $this->marker[$point1], $decimals);
}
public function memory_usage()
{
return '{memory_usage}';
}
}
But there are still a few questions:
"if ($point1 === '')" it returns '{elapsed_time}'. And I kinda don't understand what it means both from syntax point of view and how do the PHP interpreter behave when it sees this line of code? What does it do in real world? Just returns the string?
function memory_usage() also not clear.
The documentation states:
* Simply returns the {memory_usage} marker.
*
* This permits it to be put it anywhere in a template
* without the memory being calculated until the end.
* The output class will swap the real value for this variable.
What "output class" will swap real value?
I am kinda confused, any help or explanation would be great.
:(
Those pseudo variables are replaced in output.php after the page is loaded in the next code:
$elapsed = $BM->elapsed_time('total_execution_time_start', 'total_execution_time_end');
if ($this->parse_exec_vars === TRUE)
{
$memory = round(memory_get_usage() / 1024 / 1024, 2).'MB';
$output = str_replace(array('{elapsed_time}', '{memory_usage}'), array($elapsed, $memory), $output);
}
It is built like this due to the reason that we don't know how much actual memory we consumed before the page is loaded.
I will come up with more explanations in the future for "new in Codeignaiter" guys like me .
I get the tutorial in:
http://yaminnoor.com/redis-codeigniter/
https://codeigniter.com/user_guide/libraries/caching.html#redis
I try it like this:
Config (application\config\redis.php):
defined('BASEPATH') OR exit('No direct script access allowed');
$config['socket_type'] = 'tcp'; //`tcp` or `unix`
$config['socket'] = '/var/run/redis.sock'; // in case of `unix` socket type
$config['host'] = '127.0.0.1'; //change this to match your amazon redis cluster node endpoint
$config['password'] = NULL;
$config['port'] = 6379;
$config['timeout'] = 0;
Controller:
<?php
if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Redis_tes extends CI_Controller {
public function __construct() {
parent::__construct();
$this->load->driver('cache', array('adapter' => 'redis', 'backup' => 'file'));
}
public function index() {
// die('tes');
if($this->cache->redis->is_supported() || $this->cache->file->is_supported()) {
$var1 = $this->cache->get('cache_var1');
} else {
$cache_var1 = $this->_model_data->get_var1();
$this->cache->save('cache_var1', $cache_var1);
}
}
}
?>
I run http://localhost/app_redis/redis_tes, which produces the following error:
An Error Was Encountered
Invalid driver requested: CI_Cache_redis
Any solution to solve my problem?
Look here:
https://github.com/joelcox/codeigniter-redis
Try to use this library.
Update : This library is deprecated. Author recommends to migrate on Predis.
In CodeIgniter I often have many scripts inherent to my project, for instance:
<?php
// Load many things
$this->load->model('news_model');
$this->load->helper('utility_helper');
$news = $this->news_model->get_basic_news();
// For moment no news
$view_datas['news']['check'] = false;
if ($news) {
$view_datas['news'] = array(
'check' => true,
'news' => _humanize_news($news)
);
}
?>
This script is used in different controllers, at the moment I create a scripts folder and I import it like that: include(APPPATH . 'scripts/last_news.php'); I'm quite sure it's not the best way to handle this problem. Any thoughts on that?
Update:
A solution given in the answers is to use a helper or a library.
Let's imagine a rewrite of my previous code:
class Scripts {
public function last_news() {
// Load many things to use
$CI =& get_instance();
$CI->load->model('news_model');
$CI->load->model('utility_helper');
$news = $CI->news_model->get_basic_news();
// Avoid the rest of code
}
}
Just create a new library and load that library whereever you require?
e.g.
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Newclass {
public function get_news($limit)
{
//return news
}
}
/* End of file Newsclass.php */
In your controllers
$this->load->library('newsclass');
$this->newsclass->get_news($limit);
Or another idea is to create helper functions.
I tried to follow the instructions here: http://kohanaframework.org/3.0/guide/kohana/tutorials/error-pages But for some reason I am unable to catch the HTTP_Exception_404 I still get a ugly error page and not my custom page.
Also when I type in the URL error/404/Message, I get a ugly Kohana HTTP 404 error message.
Here is the files structure:
modules
my
init.php
classes
controller
error_handler.php
http_response_exception.php
kohana.php
views
error.php
Code:
init.php:
<?php defined('SYSPATH') or die('No direct access');
Route::set('error', 'error/<action>(/<message>)', array('action' => '[0-9]++', 'message' => '.+'))
->defaults(array(
'controller' => 'error_handler'
));
http_response_exception.php:
<?php defined('SYSPATH') or die('No direct access');
class HTTP_Response_Exception extends Kohana_Exception {
public static function exception_handler(Exception $e)
{
if (Kohana::DEVELOPMENT === Kohana::$environment)
{
Kohana_Core::exception_handler($e);
}
else
{
Kohana::$log->add(Kohana::ERROR, Kohana::exception_text($e));
$attributes = array
(
'action' => 500,
'message' => rawurlencode($e->getMessage()),
);
if ($e instanceof HTTP_Response_Exception)
{
$attributes['action'] = $e->getCode();
}
// Error sub-request.
echo Request::factory(Route::url('error', $attributes))
->execute()
->send_headers()
->response;
}
}
}
kohana.php:
<?php defined('SYSPATH') or die('No direct script access.');
class Kohana extends Kohana_Core
{
/**
* Redirect to custom exception_handler
*/
public static function exception_handler(Exception $e)
{
Error::exception_handler($e);
}
} // End of Kohana
error_handler.php:
<?php defined('SYSPATH') or die('No direct access');
class Controller_Error_handler extends Controller {
public function before()
{
parent::before();
$this->template = View::factory('template/useradmin');
$this->template->content = View::factory('error');
$this->template->page = URL::site(rawurldecode(Request::$instance->uri));
// Internal request only!
if (Request::$instance !== Request::$current)
{
if ($message = rawurldecode($this->request->param('message')))
{
$this->template->message = $message;
}
}
else
{
$this->request->action = 404;
}
}
public function action_404()
{
$this->template->title = '404 Not Found';
// Here we check to see if a 404 came from our website. This allows the
// webmaster to find broken links and update them in a shorter amount of time.
if (isset ($_SERVER['HTTP_REFERER']) AND strstr($_SERVER['HTTP_REFERER'], $_SERVER['SERVER_NAME']) !== FALSE)
{
// Set a local flag so we can display different messages in our template.
$this->template->local = TRUE;
}
// HTTP Status code.
$this->request->status = 404;
}
public function action_503()
{
$this->template->title = 'Maintenance Mode';
$this->request->status = 503;
}
public function action_500()
{
$this->template->title = 'Internal Server Error';
$this->request->status = 500;
}
} // End of Error_handler
I really cannot see where I have done wrong. Thanks in advance for any help.
First of all, you need to make sure you are loading your module by including it in the modules section of your application/bootstrap.php file like so
Kohana::modules(array(
'my'=>MODPATH.'my'
)
);
The fact that you mentioned going directly to the url for your error handler controller triggers a 404 error makes me think your module has not been loaded.
I would also suggest a few more changes.
http_response_exception.php does not need to extend Kohana_Exception, since this class is not an exception, but an exception handler. Along those same lines, a more appropriate class name might be Exception_Handler, since the class is not representing an exception, but handling them. Secondly, because of how you've named this file, it should be located in modules/my/classes/http/response/exception.php. Other than that, the code for this class looks ok.
Similarly, because of how you've named your controller, it should be located and named a bit differently. Move it to modules/my/classes/controller/error/handler.php
Remember that underscores in a class name means a new directory, as per http://kohanaframework.org/3.2/guide/kohana/conventions
Finally, I don't think you really need to extend the Kohana_Core class here, but instead just register your own custom exception handler. You can register your custom exception handler in either your application's bootstrap file, or in your module's init file with the following generic code:
set_exception_handler(array('Exception_Handler_Class', 'handle_method'));
Here's a customer exception handler I use, which is pretty similar to yours:
<?php defined('SYSPATH') or die('No direct script access.');
class Exception_Handler {
public static function handle(Exception $e)
{
$exception_type = strtolower(get_class($e));
switch ($exception_type)
{
case 'http_exception_404':
$response = new Response;
$response->status(404);
$body = Request::factory('site/404')->execute()->body();
echo $response->body($body)->send_headers()->body();
return TRUE;
break;
default:
if (Kohana::$environment == Kohana::DEVELOPMENT)
{
return Kohana_Exception::handler($e);
}
else
{
Kohana::$log->add(Log::ERROR, Kohana_Exception::text($e));
$response = new Response;
$response->status(500);
$body = Request::factory('site/500')->execute()->body();
echo $response->body($body)->send_headers()->body();
return TRUE;
}
break;
}
}
}
You're using an outdated documentation. HTTP_Exception_404 was bundled in 3.1, and you're trying to implement a solution from 3.0.
See documentation for your version of Kohana for a solution that works.
All you need to do is set the path to a different view in your bootstrap.php add:
Kohana_Exception::$error_view = 'error/myErrorPage';
that will parse all the variables currently being parsed to the error page that lives in:
system/views/kohana/error.php
ie:
<h1>Oops [ <?= $code ?> ]</h1>
<span class="message"><?= html::chars($message) ?></span>
After a VERY LONG TIME of searching I finally found a solution to my little problem.
Here is a step by step tutorial on how to load your own custom error pages with Kohana 3.2:
Change the environment variable in the bootstrap.
Here you have multiple options:
a. Do what they say in the documentation of the bootstrap.php:
/**
* Set the environment status by the domain.
*/
if (strpos($_SERVER['HTTP_HOST'], 'kohanaphp.com') !== FALSE)
{
// We are live!
Kohana::$environment = Kohana::PRODUCTION;
// Turn off notices and strict errors
error_reporting(E_ALL ^ E_NOTICE ^ E_STRICT);
}
b. Or just add those two lines without the "if":
Kohana::$environment = Kohana::PRODUCTION;
error_reporting(E_ALL ^ E_NOTICE ^ E_STRICT);
c. I have not try this way but in the new bootstrap.php you have this code:
/**
* Set Kohana::$environment if a 'KOHANA_ENV' environment variable has been supplied.
*
* Note: If you supply an invalid environment name, a PHP warning will be thrown
* saying "Couldn't find constant Kohana::<INVALID_ENV_NAME>"
*/
if (isset($_SERVER['KOHANA_ENV']))
{
Kohana::$environment = constant('Kohana::'.strtoupper($_SERVER['KOHANA_ENV']));
}
I assume that you could just give the value "production" to "$_SERVER['KOHANA_ENV']" before those lines.
Again, like I said I haven't tried it, but it should work.
I personally just commented out those lines of codes.
2 Now you need to add a few configurations in a "ini.php" file, or in the "bootstra.php" file.
<?php defined('SYSPATH') or die('No direct script access.');
/**
* Turn errors into exceptions.
*/
Kohana::$errors = true;
/**
* Custom exception handler.
*/
restore_exception_handler();
set_exception_handler(array('Exception_Handler', 'handler'));
/**
* Error route.
*/
Route::set('error', 'error/<action>(/<message>)', array('action' => '[0-9]++', 'message' => '.+'))
->defaults(array(
'controller' => 'exception_handler'
));
This is what was missing and made it to hard. For the rest you can easily just follow Kohana3.2 documentation or you can get the module that I added to a repo in GitHub: https://github.com/jnbdz/Kohana-error
Every underscore is a directory separator in a class name. So when naming your class Http_Response_Exception, the class should be in classes/http/response/exception.php. Otherwise the class will not be found by the autoloader of Kohana.
edit
Hmm, seems like the documentation is wrong in this aspect. classes/http_response_exception.php doesn't make sense.
I am trying to implement CAS authentication in a CodeIgniter application though I cannot find if there are any libraries currently set up for it. I am managing by just including the class and adding in a few dirty fixes though if anyone knows of a proper library I think it would be a cleaner solution.
I have been looking through a range of posts on here as well as all over Google but seem to be coming up short on what I need. The only place of any relevance is a post on VCU Libraries but that did not include the library download link.
Thanks everyone!
UPDATE: You can find the latest version of the library at Github: https://github.com/eliasdorneles/code-igniter-cas-library
You can also install via sparks: http://getsparks.org/packages/cas-auth-library/versions/HEAD/show
I've started a CAS library to simplify setting up CAS authentication for CodeIgniter, that relies on the existing phpCAS.
To start using it, you just have installation phpCAS in some accessible directory, put the library file in application/libraries/Cas.php and create a config file config/cas.php like this:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
$config['cas_server_url'] = 'https://yourserver.com/cas';
$config['phpcas_path'] = '/path/to/phpCAS-1.3.1';
$config['cas_disable_server_validation'] = TRUE;
// $config['cas_debug'] = TRUE; // <-- use this to enable phpCAS debug mode
Then, in your controllers you would be able to do this:
function index() {
$this->load->library('cas');
$this->cas->force_auth();
$user = $this->cas->user();
echo "Hello, $user->userlogin!";
}
Here is the library file (has to be named Cas.php):
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
function cas_show_config_error(){
show_error("CAS authentication is not properly configured.<br /><br />
Please, check your configuration for the following file:
<code>config/cas.php</code>
The minimum configuration requires:
<ul>
<li><em>cas_server_url</em>: the <strong>URL</strong> of your CAS server</li>
<li><em>phpcas_path</em>: path to a installation of
phpCAS library</li>
<li>and one of <em>cas_disable_server_validation</em> and <em>cas_ca_cert_file</em>.</li>
</ul>
");
}
class Cas {
public function __construct(){
if (!function_exists('curl_init')){
show_error('<strong>ERROR:</strong> You need to install the PHP module <strong>curl</strong>
to be able to use CAS authentication.');
}
$CI =& get_instance();
$this->CI = $CI;
$CI->config->load('cas');
$this->phpcas_path = $CI->config->item('phpcas_path');
$this->cas_server_url = $CI->config->item('cas_server_url');
if (empty($this->phpcas_path)
or filter_var($this->cas_server_url, FILTER_VALIDATE_URL) === FALSE) {
cas_show_config_error();
}
$cas_lib_file = $this->phpcas_path . '/CAS.php';
if (!file_exists($cas_lib_file)){
show_error("Could not find file: <code>" . $cas_lib_file. "</code>");
}
require_once $cas_lib_file;
if ($CI->config->item('cas_debug')) {
phpCAS::setDebug();
}
// init CAS client
$defaults = array('path' => '', 'port' => 443);
$cas_url = array_merge($defaults, parse_url($this->cas_server_url));
phpCAS::client(CAS_VERSION_2_0, $cas_url['host'],
$cas_url['port'], $cas_url['path']);
// configures SSL behavior
if ($CI->config->item('cas_disable_server_validation')){
phpCAS::setNoCasServerValidation();
} else {
$ca_cert_file = $CI->config->item('cas_server_ca_cert');
if (empty($ca_cert_file)) {
cas_show_config_error();
}
phpCAS::setCasServerCACert($ca_cert_file);
}
}
/**
* Trigger CAS authentication if user is not yet authenticated.
*/
public function force_auth()
{
phpCAS::forceAuthentication();
}
/**
* Return an object with userlogin and attributes.
* Shows aerror if called before authentication.
*/
public function user()
{
if (phpCAS::isAuthenticated()) {
$userlogin = phpCAS::getUser();
$attributes = phpCAS::getAttributes();
echo "has attributes? ";
var_dump(phpCAS::hasAttributes());
return (object) array('userlogin' => $userlogin,
'attributes' => $attributes);
} else {
show_error("User was not authenticated yet.");
}
}
/**
* Logout and redirect to the main site URL,
* or to the URL passed as argument
*/
public function logout($url = '')
{
if (empty($url)) {
$this->CI->load->helper('url');
$url = base_url();
}
phpCAS::logoutWithRedirectService($url);
}
}
I recommend using Ion Auth Library, it's built upon Redux Auth, which became outdated. Ion Auth is light weight, easy to customize, and does the things you need. Ion Auth is one of the best authentication libraries for CodeIgniter.
What exactly is not working with the VCU library?
Anything you can do in PHP, you can do in CodeIgniter.
So you can just use the PHP CAS client:
http://www.jasig.org/phpcas-121-final-release
And here is a example of how to authenticate.
https://source.jasig.org/cas-clients/phpcas/trunk/docs/examples/example_simple.php