Codeigniter Config Folder - php

Is is possible to move config folder on same level of application folder?
I would like to have a structure like this:
application
controllers
models
views
config
error
system

No, You can't do it with CodeIgniter's native functions. But You can load them manually if You really want.
At the end of /application/config/config.php add "folder scanner" function with require_once(). Something like this:
foreach(glob(FCPATH.'config/*.php') as $cfg){
require_once($cfg);
}
upd Also You can add FCPATH.'config/' to CodeIgniter's core (/system/core/Config.php at var $_config_paths = array(APPPATH); // => var $_config_paths = array(APPPATH,FCPATH.'config/');) but this is bad practice because folder /system/ updates when CI updates.
upd2 as #jhuet wrote at the comments below: Instead of hacking right into CI's core classes, you should rather create at class called MY_Config in application/core directory. Make this class extend CI_Config and in the constructor change the value of $_config_path

Related

Codeigniter 3 - Third_party and controllers / loading ressources

I'd like to use the controllers from the /third_party/myapp/controllers folder without having to move them to the /application/controllers one
It doesn't seem possible (at least not without hacking the core). Though the question concerns loading model, limitations are mentioned here
I don't feel like using HMVC - as stated in the solution proposed there, cause I don't need any other functionality than avoiding to multiply file transfer in CI base folders (i don't really need the 'hierarchical' part of it)
But I don't really get it... if one declares its third_party app, CI will load resources from those folders (as stated by the doc)
config/
helpers/
language/
libraries/
models/
[metaphysical] Why wouldn't it be possible to simply load controllers as well ?
[pragmatic] is it a good idea to try to hack the core system or should I stay on the "HMVC or do copy your files" choice ?
[optimistic] do someone have a solution ?
EDIT
While looking further to trajchevska tip in another installation of CI, I tried to implement DFriend example of spl_register. I read several times the manual and this answer as well :
So far I understood that spl_autoload_register is triggered when a class is called, which allows to skip their manual loading
So I've tried simply adding the spl_autoload_register at the end of the config file in application/config/config.php, expecting it to print Auto load ClassName when a first class is called - a bit naïve, I know.
but from what I understood (thanks to DFriend), this spl_autoload_register would NOT work with controllers, as CI will always check if the file exists (in its own path) before trying to declare the controller.
It seems on the other hand that it could work with other classes (core, model ... see DFriend answer below)
Conclusion
So, after a few hairs pulled out of my head, I decided to try the HMVC extension for CI - MX from WireDesign. It solved my problem of loading any resources from different folder, along with bringing a brand new scope of shared classes and their attached issues (what is available where ?).
As it's the beginning the project I had the opportunity to switch to the "hierarchical" side, otherwise I'd followed Dfriend's advice of
going with the flow and putting controllers for third-party packages
where CI expects them to be
You could use PHP's spl_autoload_register to implement an autoloader. A google search will reveal multiple approaches for using one within the CI framework.
One that works and is often described is to register the autoloader in config.php or maybe a site-specific constants file. Such a solution is to put something like this in one of the mentioned files.
spl_autoload_register(function($class)
{
if(strpos($class, 'CI_') !== 0)
{
if(file_exists($file = APPPATH.`/third_party/myapp/controllers/`.$class.'.php'))
{
require_once $file;
}
}
});
You can use hooks if you want to avoid hacking config.php or some other file. Here's one way to do that.
application/config/config.php
$config['enable_hooks'] = TRUE;
application/config/hooks.php
$hook['pre_system'][] = array(
'class' => '',
'function' => 'register_autoloader',
'filename' => 'Auto_load.php',
'filepath' => 'hooks'
);
application/hooks/Auto_load.php
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
function register_autoloader()
{
spl_autoload_register('my_autoloader');
}
function my_autoloader($class)
{
if(strpos($class, 'CI_') !== 0)
{
if(file_exists($file = APPPATH.`/third_party/myapp/controllers/`.$class.'.php'))
{
require_once $file;
}
}
}
Addendum
On further digging and consideration the above will not work because CI insists that Controllers be in the application/controllers directory or a subdirectory thereof.
PHP will run a registered autoloader when you try to use a class/interface which hasn’t been defined yet. Controllers are php classes so you might expect an autoloader to come to the rescue. But CI is very explicit about where it looks for controller files. If the file is not found then it never attempts any calls to the class. Instead it abandons all hope and immediately issues an 404 error. The autoloader never gets a chance to look for the file.
The answer to the metaphysical question is that CI's routing and URL parsing are tightly coupled to the file storage structure making the desired functionality impossible. (without some serious core hacking)
The answer to the pragmatic question is very subjective. I'm not fond of the HMVC approach and personally would opt for going with the flow and putting controllers for third-party packages where CI expects them to be.
Start: Serious diversion from question at hand
So, what good is registering an autoloader in the CI environment?
Controllers are defined like so.
class Home extends CI_Controller{ ...
The class being extended, CI_Controller, is a core class. If you want to extend this core class for use by multiple other controllers you can use the CI convention of prepending the class name with "MY_". e.g.
class MY_Controller extends CI_Controller
(
//class implementation
}
and then use it to define actual controllers using the extended core class
class Home extends MY_Controller{ ...
The problem is that you can only extend the core CI_Controller once using this convention. What if you have a need for more than one extension to the CI_Controller core class? One solution is registering an autoloader. (A good discussion of this and other ways to overcome the MY_Controller monopoly is HERE.)
An autoloader for these purposes could look this.
spl_autoload_register(function($class)
{
if(strpos($class, 'CI_') !== 0)
{
if(file_exists($file = APPPATH.'libraries/'.$class.'.php'))
{
require_once $file;
}
elseif(file_exists($file = APPPATH.'models/'.$class.'.php'))
{
require_once $file;
}
elseif(file_exists($file = APPPATH.'core/'.$class.'.php'))
{
require_once $file;
}
}
}
Note that the above also allows you to extend models from other models.
End: Serious diversion from question at hand
I assume it's because of the routing process - the CI Router checks whether a corresponding controller exists in the application folder, or a respective route is defined in the config. If none of them is found, 404 is returned.
You can override the Router file to enable loading controllers from other locations. In the core folder, create a MY_Router file that will extend the CI_Router. Then extend the _validate_request function, to allow loading controller files from different path than the default.
UPDATE: So, I've spent some time on this and didn't manage to extend the Router to get the controller file from the third party folder. It's easy to do when it comes to subfolders of the default controllers directory, but setting up a custom directory for reading the controllers is not that straightforward and unfortunately, I couldn't find any documentation on that.

Location of config in an OpenCart extension

I am currently developing OpenCart extensions. I am looking through existing extensions to understand the architecture (and familiarizing MVC/PHPOO concepts).
Frequently, this line of code comes up:
$seller_email = $this->config->get('service_seller_email');
My interpretation based on reading this thread:
I understand that this is a variable assignment, where it's accessing a model (?) called config to retrieve a string called service_seller_email from the admin settings portal. However, I have tried navigating through the various MVC folders within OpenCart, and I could not find a specific config.php. Could you please correct my interpretation if it's wrong?
EDIT: To add to the confusion, the article I linked specifies that you need to load a config in a controller before using it, like $this->language->load('product/search');, but I cannot find a line such as $this->config->load('...'); or the like.
Your interpretation is incorrect. The config class is not considered as model (despite it is accessing DB directly) but as a system library class - that's why you can find it under system/library/ folder.
OpenCart has it's implementation of service locator (registry) which is used to to store the config object so that you can access it directly from anywhere (inside of OpenCart of course).
It is loaded in both index.php files (in root and under admin/) like this:
$config = new Config();
$registry->set('config', $config);
This $registry is our service locator and it is passed over to any controller in it's __construct() method. Each controller has also a magic method __get() which is responsible for retrieving objects from this $registry - take a look at abstract Controller class at system/engine/controller.php which each controller extends (and should extend).
That's why you can freely call directly
$this->config->get('some_config_key');
The first part, $this->config will fall into the __get() method passing over the 'config' value as a $key which in turn is passed over to next call
return $this->registry->get($key);
And since the config object is registered under 'config' key in our service locator, it is retrieved and returned so that we could call get('some_config_key') on it.
Now the some_config_key key is stored in DB in setting table and the config object tries to find it and get it's value (you can take a look at how this works in system/library/config.php).
Hopefully this clarifies your confusion.
Looking at the docs, it looks like the config values are stored in the setting table. The Config class itself is located in /system/library/config.php.
In admin > index.php you wil find
// Config
$config = new Config();
$registry->set('config', $config);
That's where it is initialized. The class is located in
system > library > config.php
Config loaded in system > engine >loader.php:
public function config($config) {
$this->config->load($config);
}

Where can I put my global code in Kohana 3.3?

Say I want a constant, a function or a class to be available in all my models, views and controllers code (within a particular web site (application)). Where can I put them? I don't mind importing them explicitly in every file I need them in but I don't know how (simple require_once does not seem to work).
You can put them in the vendor folder (in application/vendor or modules/MOD/vendor). Then you can load it like this:
require Kohana::find_file('vendor', 'folder/file','ext');
You can read up more on this in the user guide
Now, it should be stated you should in general not use functions or globals.
I declare Constants in Bootstrap.php and create my own Helpers for general functions under application/classes/Helpers.
If you need to integrate a third party library into Kohana or want to make code available to other Kohana users consider creating a module instead.
You can define all your constants in new php file and place it in the application/classes directory. In your Template controller or in the main controller like Welcome or Website, just place the code in the __constructor()
require_once Kohana::find_file( 'classes', 'filename' );
I suggest you to put your constant variables in the bootstrap.php file because this is loaded by the framework before every request.
You can simply put your classes in the root of the classes directory, the framework will find.
This worked well for me...
In application/config/constants.php:
define('SOME_COOL_CONSTANT', 'foo');
return array();
In index.php:
Kohana::$config->load('constants');
SOME_COOL_CONSTANT should then be available globally.

How to include a class in CakePHP 2.x

This is a very basic question but I can't figure it out.
I have a class that could be named myClass.php, this is a standalone PHP script that contains a standard object definition like this:
<?php
class myClass
{
public function myFunction($param1, $param2){
return $param1*$param2;
}
}
All I want to do is to be able to call to this class from a model, this is from App/Models/MyModel.php be able to simply do $myClass = new MyClass();
Where should I store myClass.php in the file structure and how can I make it visible for MyModel?
Thanks!
You'll note that you have a 'vendors' directory inside the root (ie, on the same level as the 'app' folder). This is for placing non-CakePHP related files that are shared across applications. You also have an 'app/Vendor' directory, which is for storing non-CakePHP files that are specific to that one app.
So, it should go in one of these two directories - most likely, in app/Vendor.
There's a little bit to know about loading vendor files - you can read the details here.
In your case, you probably just need:
App::uses('myClass', 'Vendor');

Using custom classes in Kohana 3

Hey, I'm creating a Call of duty 4 Server Watcher in Kohana 3, and I had created the basic classes for it before:
A static Socket class (for handling basic network commands)
A Cod4Socket class, (which uses the previously mentioned Socket class) that provides wrapper functions for basic commands.
What I want is to be able to use said classes inside the controllers for the website.
Where am I supposed to put the class files, where should I "include" them, and how do I use them?
Edit: I'm using Kohana 3.
Where am I supposed to put the class files?
Add your class files into the application/classes/ directory with lowercase filenames.
Socket should go into application/classes/socket.php
Cod4Socket should go into application/classes/cod4socket.php
Where should I "include" them, and how do I use them?
There is no need to manually include them; simply use them as if they were already included.
The Kohana autoloader will find the classes if they're in the right files.
Additional Info:
Sometimes, you want to place your custom classes in a place like this
application/
classes/
controllers/
.......
models/
......
etc/
CustomClassFirst.php
CustomClassSecond.php
You can call these classes by
$customClassOne = new Etc_CustomClassFirst();
and then redefine the class name into this
class Etc_CustomeClassFirst {}
Did it on my own: http://www.dealtaker.com/blog/2010/06/02/kohana-php-3-0-ko3-tutorial-part-9/
You have to include the files in the bootstrap.php file, and then just call it normally on your controller.

Categories