I ran into a problem, while coding around in CI 3.0.3 and latest HMVC Extension. I'm autoloading some libraries, helpers and much more. The Session library too. Now i have a few controllers all working fine, except one.
In that controller i use this code:
modules::run($module->module . '/' . $module->controller . '/' . $module->method, unserialize($block->configuration));
While using this static function i got the error:
Unable to locate the specified class: Session.php
The log says that the Session class is initialized.
INFO - 2015-12-01 09:41:40 --> Session: Class initialized using 'database' driver.
Any ideas why i got this error?
EDIT: -----------------------------------------------------------------------
To prevent stupid answers as below ...
In CI we can’t call more than 1 controller per request. Therefore, to achieve HMVC, we have to simulate controllers. It can be done with libraries, or with this “Modular Extensions HMVC” contribution.
The differences between using a library and a “Modular HMVC” HMVC class is: 1. No need to get and use the CI instance within an HMVC class 2. HMVC classes are stored in a modules directory as opposed to the libraries directory.
EDIT 2: ---------------------------------------------------------------------
For further questions:
Yes, the Session Library is the problem
Yes, only in combination with this HMVC Plugin
Yes, only if you use the static method modules::run();
No, i need this method for simulating a controller in a controller
Simple.
If you want to load a controller in a controller use:
Modules::load();
or outsource the Modules::run(); into a view that is loaded by the main controller.
Simple.
Related
I'm using Codeigniter 2.1.0.
I'm including the Amazon Web Services SDK in a custom model using require_once APPPATH . "/libraries/aws_sdk/sdk.class.php";
This works well. However when CI decides it later needs to load it's db cache class, it calls (via CI_DB_driver::_cache_init):
if ( ! class_exists('CI_DB_Cache'))
{
if ( ! #include(BASEPATH.'database/DB_cache.php'))
{
return $this->cache_off();
}
}
This triggers the autoload of the AWS SDK (the exact method being CFLoader::autoloader).
I can get around this by telling class_exists not to autoload, as it seems that DB_cache.php is included anyway if class_exists returns false:
if ( ! class_exists('CI_DB_Cache', false))
{
if ( ! #include(BASEPATH.'database/DB_cache.php'))
{
return $this->cache_off();
}
}
This dirty fix works, but obviously only fixes the immediate problem. In general, what is the best way to ensure that CodeIgniter doesn't get confused with the autoload from other libraries?
Please note:
I've read bits and pieces about using spl_autoload_register. It seems that Codeigniter doesn't use this and I'm not sure how I should implement this safely. I would find a solid example of how and where I should implement this most useful (if, of course, this is the solution).
It appears that the AWS SDK already uses spl_autoload_register: spl_autoload_register(array('CFLoader', 'autoloader'));
As you probably know, you don't really want to be modifying the core methods in CI. So, to prevent CI from conflicting with your class, you want to do something very similar to the following:
Leave your folder structure as is, but create a new file outside your aws_sdk folder. Name it something like *Aws_loader* or something that makes sense to you. If you want to autoload the sdk, then in the CI autoloader file, add:
CI Autoload file (application/config/autoload.php):
$autoload['libraries'] = array('Aws_loader');
Your init file:
class CI_Aws_sdk{
// for use with PHP < version 5
/*public function CI_Aws_sdk(){
require dirname(__FILE__) . DIRECTORY_SEPARATOR . "aws_sdk" .DIRECTORY_SEPARATOR . 'sdk.class.php';
}*/
// for use with PHP >= 5
public function __construct(){
require dirname(__FILE__) . DIRECTORY_SEPARATOR . "aws_sdk" .DIRECTORY_SEPARATOR . 'sdk.class.php';
}
}
So your directory structure looks like this now:
application --
config --
...
libraries --
Aws_loader.php
aws_sdk --
sdk.class.php
If you aren't autoloading the sdk, then in your controller, you can do this:
$this->load->library('Aws_loader');
Either way, CI with load the class for you and effectively separate any methods within it and now you can operate within that class just like any other library or model that you've loaded previously, without interfering with CI's methods, similar to this:
$this->Aws_loader->do_something();
You can use the same method for any third party class library or even one that you wrote yourself. A very similar arrangement can be used for models, libraries, helpers and the like.
Hope this helps!
I have a class Called MyClass. It lives in app/Lib/MyDir/MyClass. I'd like to use App:uses() to load it, but can't get it to work.
In CakePHP 1.3 I would load it via:
App::import('Lib', 'MyDir/MyClass'); //this still works in CakePHP 2.1
In CakePHP 2.1 I'm trying to do:
App::uses('MyClass', 'Lib/MyDir');
When I try to 'new' up MyClass I get Class 'MyClass' not found.
Is it not possible to use App::uses on custom Lib classes? I can't continue to use App::import() because if 'App::import('Lib', 'MyDir/MyClass');' appears 2x in the code path I get a 'Cannot redeclare class' error in lib/Cake/Core/App.php on line 531
what am I doing wrong?
Edit: so if I do App::uses('MyClass', 'MyDir'); it works. Not sure if thats how its supposed to behaive, but reporting bug.
did you try
App::uses('MyClass', 'MyDir');
? since "Lib" itself can be seen as a base directory
PS: you are even supposed to group everything inside Lib in subfolders (packages) similar to the core.
I have a library which is used by all controllers. But for a specific controller i dont want to load that library. Is there any way i can stop loading that library for that controller.
i am using this command but its failing:
$this->load->library('xyz',array('autoload' => FALSE));
Thanks
Autoloading is meant for site-global items.
A cleaner solution may be to extend the controller and load the library in that new controller's constructor. Then all of your controllers extend from that controller, except the one(s) you don't want to load that library - those can extend the original CI controller.
That should take you < 5 minutes to implement and you won't have to hack anything.
You can take a look at this link:
http://xplus3.net/2010/05/31/conditional-auto-loading-of-libraries-in-codeigniter/
Basically, you'd be overwriting the autoload.php library to check for a variable. If that variable is false, then explicitly add the specific library to the autoload array.
Hello and thanks for reading.
I'll get straight to the point: I have a website project that I've been building using CodeIgniter 1.7.3, which I have thoroughly enjoyed using, however I have been contemplating upgrading to CI 2.0+.
I tried a straight copy, just moved my folders for controllers, models and views over to a CI 2.0 framework, but I got a 500 server error when I tried to view my pages.
After doing some investigation I discovered that all of your controllers must now use "CI_Controller" as their parent class. Also I noticed that if you want to include a constructor in your controller class that it must use the syntax "function __construct()" as its name and of the parent class. It seems that CI 2.0+ no longer supports using a constructor that has the same name as the class name, e.g. "class Blogs extends CI_controller{ function Blogs(){parent::__construct();}}" is no longer supported?
I've been reading the CI Change Log, but all I see are bug fixes, and new features, nothing about compatibility issues with older versions of CI?
Does anyone else know of any other secret little pitfalls?
Thanks,
H
CI 2.x removed all compatibility with PHP4 and also updated a number of standards to be compliant with PHP 5.3 going forward. One of these is the constructor issue you have encountered. As of PHP 5.3, the function ClassName() is no longer the constructor for a class, it is simply another function. You must explicitly declare a __construct function to perform any tasks that need to be done when a new instance of the class is created. Given this, you should see it no longer makes sense to call parent::ClassName() in your child constructor as that function would no longer be the parent's constructor.
Another pitfall I recently had to work out is how the $_GET array is now handled. In the 1.x versions, you could use query strings to pass back extra information and still use URI segments to route to controllers and functions. This is especially useful for AJAX calls where you may not always know all the parameters being sent to and from the server in a particular request. In the 2.x versions, the config.php file contains a new option, $config['allow_get_array']. This must be set to TRUE if you want to use query strings otherwise the input class clears out the $_GET array as part of CI's initialization routine on each request.
Something which isn't a pitfall but you may find useful is the new options in config/autoload.php that allows you to add new application directories to your project. If you work on a number of different projects with CI and want to keep any useful libraries you write in a single location, you can now add that location to $autoload['packages']. CI expects any path in this array to contain the sub-directories "controllers", "models", "libraries" and "helpers". It won't complain if you don't have those directories but you will at least need them for anything you intend to load, i.e. libraries would live in /libraries as with the main application folder.
Have you read the official guide for upgrading from 1.7.x to 2.x ?
so in short
Update Models and Controllers to
extend CI_Model and CI_Controller
Update Parent Constructor calls
class Wow extends CI_Controller {
function __construct()
{
parent::__construct();
//your stuff
}
function index()
{
// just for example
}
}
I'm building a library for our CodeIgniter app, but it requires many classes (currently I'm at 12).
Is there a best practice for packaging these many clients into one library. So I can just make one call to load it. i.e:
$this->load->library('soaplibrary');
Thanks!
As Summer points out, they have handled this situation somewhat elegantly in CI 2.0 with the concept of Drivers.
With a Driver, you actually create a subdirectory within your 'libraries' directory that contains your 'super' class, and another directory for 'child' classes. Better visual representation of the structure...
This was taken from Here.
and once you have constructed your library, here is the documentation on how to use it.
In CI 2.0, there are drivers to handle this situation. Good luck!
In CodeIgniter 3.1.9 when you load a library file, all classes in this file are included into code.
Let's say in soaplibrary.php you have
class SoapLibrary {
public function someMethod(...
class Test {
public function anotherMethod(...
In your controller you can do:
$this->load->library('soaplibrary');
//now on you can do
$this->soaplibrary->someMethod();
//but also
$test = new Test();
$test->anotherMethod();
CodeIgniter attempts to call the constructor of class SoapLibrary, hence a class with that name must be in there.