I've been developing a custom CMS using Codeigniter locally and I've just gotten to the point where I need to upload it to a staging server to do some more testing.
Everything works except for the sidebar section of the site that uses a widget system. I initially thought it was just differences between PHP versions, as I am running 5.4.4 locally and the server was 5.3. After upgrading the server to 5.4.7, the sidebar is still not appearing. I get no error, just nothing displays.
This is the Widget library code:
<?php
if (!defined('BASEPATH')) exit('No direct script access allowed');
class Widgets {
private $_ci;
protected $parser_enable = FALSE;
public function __construct() {
$this->widgets();
}
public function widgets(){
$this->_ci =& get_instance();
}
public function build($view,$data=array()){
$view = get_class($this).'/'.$view;
$subdir = '';
if (strpos($view, '/') !== FALSE)
{
// explode the path so we can separate the filename from the path
$x = explode('/', $view);
// Reset the $class variable now that we know the actual filename
$view = end($x);
// Kill the filename from the array
unset($x[count($x)-1]);
// Glue the path back together, sans filename
$subdir = implode($x, '/').'/';
}
$widget_view = APPPATH.'widgets/'.$subdir.'views/'.$view.EXT;
if(file_exists($widget_view)){
$widget_view = '../widgets/'.$subdir.'views/'.$view.EXT;
if($this->parser_enable){
$this->_ci->load->library('parser');
return $this->_ci->parser->parse($widget_view,$data,TRUE);
}
else{
return $this->_ci->load->view($widget_view,$data,TRUE);
}
}
return FALSE;
}
public function __get($var) {
static $ci;
isset($ci) OR $ci = get_instance();
return $ci->$var;
}
}
Does anything jump out that could cause it not to display?
Is there anything I should be looking at to make it compatible, such as server modules? What on the server could be affecting this?
EDIT:
I have the widgets residing in the following path:
/public_html/application/widgets/recent_news/views/view.php
The $widget_view = 'widgets/'.$subdir.'views/'.$view.EXT; variable is returning widgets/Recent_news/views/view.php which is getting passed to:
if(file_exists($widget_view)){
return $this->_ci->load->view($widget_view,$data,TRUE);
}
The application path in $widget_view doesn't seem to be correct on the staging server, so file_exists() returns false and doesn't load the view (which would have an incorrect path anyways).
I just can't seem to make it read the correct path, any suggestions?
If it's a staging server, go into the php.ini file and set
error_reporting = E_ALL | E_STRICT
display_errors = On
This will output whatever errors it finds so you can debug it.
Ended up just needing to subdir = strtolower($subdir);
Thanks for the help everyone
Related
I'm a newbie with XCache and I'm trying to use this feature for have an editable configuration over the air in my application.
So I need to store some data, for doing this I did:
class Settings
{
private $_config = array();
function __construct()
{
$file = 'config.php'; //return $config content
require_once $file;
$this->_config = $config;
foreach($config as $item => $value)
{
if(!xcache_isset($item))
{
xcache_set($item, $value);
}
}
}
}
Unfortunately today the official site seems down, so I can't follow the documentation to check if I did something wrong.
I've created also two method:
public static function setItem($name, $value)
{
xcache_set($name, $value);
}
public static function getItem($name)
{
return xcache_get($name);
}
now getItem after 15/20 minute can't get the key value. Why?
UPDATE
Okay, the problem it's when an header('Location..) is called. Infact if I do a redirection I lost the value stored in cache, anyone know why?
As the name implies, XCache is a cache, not a database. Values that you store in the cache may be purged without warning if space is needed for other data, and will be lost entirely when the web server is restarted. It's not an appropriate place to store configuration information.
I can't say for certain why you're seeing values become unavailable after a redirect, though. That shouldn't happen.
I am trying to use elliothaughins Socialize system for code igniter,
However I keep getting
Message: include(application/third_party/config/socializenetworks.php): failed to open stream: No such file or directory
I have traced this issue and when I call
$this->load->add_package_path(APPPATH.'third_party/socialize/');
In the loader class if I do die($path) I only get application/third_party.
It seems strange though as the code for the controller is
class SocializeController extends CI_Controller {
function __construct(){
parent::__construct();
parse_str($_SERVER['QUERY_STRING'], $_GET);
$this->load->add_package_path(APPPATH.'third_party/socialize/');
$this->_autoload();
}
private function _autoload(){
$this->load->model('socialize_migration_model');
$autoload = array();
include(APPPATH.'third_party/socialize/config/autoload'.EXT);
foreach ( $autoload as $type => $files ) {
$type = ($type == 'libraries') ? 'library' : $type;
foreach ( $files as $file ){
$this->load->$type($file);
}
}
}
public function data($key, $value)
{
$this->load->vars(array($key => $value));
}
}
Which as you can see it is calling a model, which it successfully loads,
It is when It gets to the autoloader where it loads the libraries where it breaks,
The particular library that is giving issue starts like
class SocializeNetworks {
private $_obj;
private $_networks = array();
function __construct(){
$this->_obj =& get_instance();
$this->_obj->load->config('socializenetworks'); // this is the line we die on :(
So,
Whats going on here and how can I fix it?
I traced this down to a bug just yesterday in the CI v2.0.2 code base. Essentially what is happening is you are adding an additional path to check for files in (which is correct) and the load method loops through each of the paths until it finds the file you are looking for.
If you output your CI object, you'll probably see that what you are looking for is there, but it's still failing.
In the file /codeigniter/core/Config.php where the load method is, for some reason, the $found=false; isn't reset on each iteration through the path loop, so if the path is found on the first run (as it was in my case) then $found is set to true, but then on subsequent runs, $found is still true, so it tries to include a non-existent file.
I solved this by moving the declaration for the $found variable to just below the start of the first foreach loop. This way it resets it each time. I reported the bug, so hopefully it will be addressed in subsequent versions.
I'm working on a PHP project that has a lot of hard coded paths in it. I'm not the main developer, just working on a small part of the project.
I'd like to be able to test my changes locally before committing them, but my directory structure is completely different. For example, there's a lot of this in the code:
require_once("/home/clientx/htdocs/include.php")
Which doesn't work on my local WAMP server because the path is different. Is there a way to tell either WAMP or XP that "/home/clientx/htdocs/" really means "c:/shared/clients/clientx"?
If its a local copy, do a search and replace on the whole directory , Please don't forget trailing slash. And when you commit the code, do reverse.
This is the solution, if you don't want to add extra variables and stuff (because that would change other developers' code/work/dependencies (if any)
search "/home/clientx/htdocs/" and replace to this: "c:/shared/clients/clientx/"
Always use $_SERVER['DOCUMENT_ROOT'] instead of hardcoded path.
require_once($_SERVER['DOCUMENT_ROOT']."/include.php")
as for your wamb environment, you will need a dedicated drive to simulate file structure. You can use NTFS tools or simple subst command to map some directory to a drive.
Create /home/clientx/htdocs/ folder on this drive and change your httpd.conf to reflect it.
But again, you will do yourself a huge favor by convincing your coworkers to stop using hardcoded paths
WARNING: ONLY USE THIS SOLUTION FOR EMERGENCY REPAIRS, NEVER FOR LONGER PRODUCTION CODE
Define a class with rewriting methods, see http://php.net/manual/en/class.streamwrapper.php
<?php
class YourEmergencyWrapper {
static $from = '/home/clientx/htdocs/';
static $to = 'c:/shared/clients/client';
private $resource = null;
//...some example stream_* functions, be sure to implement them all
function stream_open($path,$mode,$options=null,&$opened_path){
$path = self::rewrite($path);
self::restore();
$this->resource = fopen($path,$mode,$options);
self::reenable();
$opened_path = $path;
return is_resource($this->resource);
}
function stream_read($count){
self::restore();
$ret = fread($this->resource,$count);
self::reenable();
return $ret;
}
function stream_eof(){
self::restore();
$ret = feof($this->resource);
self::reenable();
return $ret;
}
function stream_stat(){
self::restore();
$ret = fstat($this->resource);
self::reenable();
return $ret;
}
static function rewrite($path){
if(strpos($path,self::$from)===0) $path = self::$to.substr($path,strlen(self::$from));
return $path;
}
//... other functions
private static function restore(){
stream_wrapper_restore('file');
}
private static function reenable(){
stream_wrapper_unregister('file');
stream_wrapper_register('file',__CLASS__);
}
}
stream_wrapper_unregister('file');
stream_wrapper_register('file','YourEmergencyWrapper');
Seriously, only some local debugging on your own dev-server. You can force it as an auto_prepend on almost any code. Left some function yet be implemented ;P
We may replace a PHP app with a Java EE app, but the problem is we wanna replace the modules one by one, which means two apps would co-exist and communicate with each other.
So is it possible to share the user session between the 2 apps? Or use a cookie to solve the problem?
Sharing a regular Java EE session with PHP can be done very efficient and fast with PHP-java-bridge.
This solution offer superior performance over using a database as it does not generate any disk IO. It also does not need any changes on the PHP webserver or Java EE server. Just add some code, configure and you're done.
Setting up the php-java-bridge can be confusing, but if you know how to do it, it's only a 10-minute job. As I just did a proof of concept my self I can hand you the cookbook solutions:
Download PHP-java-bridge files. I downloaded JavaBridgeTemplate610.zip (for the needed jar files) and php-java-bridge_6.1.0_documentation.zip for the needed examples, php include file and sample code (session sharing!).
Add the "JavaBridge.jar", "php-script.jar" and "php-servlet.jar" to you're webapp by putting it in the "/WEB-INF/lib/" of you're Java EE server.
Add a "test.jsp" to you're Java EE servers "/web" directory:
<HTML>
<TITLE>PHP and JSP session sharing</title>
<BODY>
<%
javax.servlet.http.HttpSession $session = request.getSession();
if($session.getAttribute("counter")==null) {
$session.setAttribute("counter", new java.lang.Integer(1));
}
int $counter = ((java.lang.Integer)$session.getAttribute("counter")).intValue();
out.println ("HttpSession variable \"counter\": " + $counter + "<br>");
java.lang.Integer $next = new java.lang.Integer($counter+1);
session.setAttribute("counter", $next);
%>
PHP page
</BODY>
</HTML>
Configure the JavaBridge servlet so it can be used by PHP to communicate to the Java EE server. Just add the following lines to you're web.xml:
<servlet>
<servlet-name>PhpJavaServlet</servlet-name>
<servlet-class>php.java.servlet.PhpJavaServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>PhpJavaServlet</servlet-name>
<url-pattern>*.phpjavabridge</url-pattern>
</servlet-mapping>
Add a file named "test.php" to you're webserver root and make sure you edit the JAVA_HOSTS and JAVA_SERVLET to correctly point to the Javabridgeservlet as configured in the web.xml.
<?php
define ("JAVA_HOSTS", "127.0.0.1:8084");
define ("JAVA_SERVLET", "/JavaBridge.phpjavabridge");
require_once("java/Java.inc");
$session = java_session();
?>
<HTML>
<TITLE>PHP and JSP session sharing</title>
<BODY>
<?php
if(is_null(java_values($session->get("counter")))) {
$session->put("counter", 1);
}
$counter = java_values($session->get("counter"));
print "HttpSession variable \"counter\": $counter<br>\n";
$session->put("counter", $counter+1);
?>
JSP page
</BODY>
</HTML>
Install the needed "java.inc" php include file. You will find the file in the downloaded "php-java-bridge_6.1.0_documentation.zip" in the src.zip. Copy the "java.inc" file in the "/java" directory (just this one php file!).
Restart Application server
Start the test.php script (for example goto: http://127.0.0.1/test.php)
If you click on the links to the jsp and php file back, you will notice that the counter shares the Java session between both JSP and PHP scripts!
In order to share the same JSession cookie in a JSP/Servlet and PHP they both need to run on the same domain name (also make sure that JAVA_HOSTS is the PHP file uses the same domain name!).
One option you might want to look at is Quercus which is tied into Resin, and allows you to run PHP code on a Java EE app server, and enables some communication between the 2 platforms.
Save your session data to a database with session_set_save_handler().
UPDATE
Efficiency wise it would be very mininal, the difference from reading a text file to querying a database (presumably using an existing connection).
Some example code (simplified from what I use)
class Session {
public function __construct() {
session_start();
$this->clean();
}
public function __destruct() {
session_write_close();
}
public function open() {
return TRUE;
}
public function close() {
return TRUE;
}
public function read($id) {
global $Database;
if ($Database->select('session_data FROM sessions WHERE session_id="%s"', $id)) {
list($data) = $Database->fetch(MYSQL_NUM);
return $data;
} else {
return '';
}
}
public function write($id, $data) {
global $Database;
return $Database->replace('sessions SET session_id="%s", session_data="%s", session_updated=%d', array($id, $data, time()));
}
public function destroy($id) {
global $Database;
$_SESSION = array();
return $db->delete('sessions WHERE session_id="%s"', $id);
}
public function clean($expire = 600) {
global $Database;
$Database->delete('FROM sessions WHERE session_updated<%d', $time - $expire);
return TRUE;
}
}
// Declare the functions to use:
session_set_save_handler(array('Session', 'open'), array('Session', 'close'), array('Session', 'read'), array('Session', 'write'), array('Session', 'destroy'), array('Session', 'clean'));
$Session = new Session;
The you can read/write to the session data using $_SESSION['name'] = data; in the usual technique.
I have just started out with testing some php mvc framework
In it, it has this function that throws an error.
The cachedirectory is set to /tmp/cache from the config file
additional:
The php is hosted on an IIS server.
Can someone help me out to get this working somehow?
This is the function within the class
function setCacheDir($cacheDir = null)
{
if( is_null( $cacheDir ) )
{
$config = config::getInstance();
$cacheDir = $config->config_values['template']['cache_dir'];
}
if (is_dir($cacheDir) && is_writable($cacheDir))
{
$config = config::getInstance();
$this->cache_dir = $cacheDir;
}
else
{
throw new Exception("De cache directory '$cacheDir' either does not exist, or is unwriteble");
}
}
thanks, Richard
Why don't you set the cache directory to something a little more Windows-y, like c:\temp (and make sure that folder exists).
I'm guessing "/tmp/cache" doesn't exist and isn't writable, so in the configuration file, set cache_dir to a directory that is.
Some PHP frameworks work best (or better) in a LAMP stack, the first letter (L) being Linux. If the documentation of your framework advises a LAMP stack, I'd go with that.