I have user library currentLang that detect current language of web site.
Also there is model that does request and gets data from.
Request is based on current language.
This is library currentLang was set in autoload.
Problem is that is loaded at first all models in Codeigniter, after libraries.
Therefore when I open web site I get empty page, because query is done without params from library.
What I must to change in this way?
It doesn't matter which one is loaded first, As long as you're able to inject the current language id in the CodeIgniter instance, You'll be fine.
Example:
// Library
class CurrentLang {
// A variable that will hold the CodeIgniter object.
protected $CI;
public function __construct () {
$this->CI = get_instance();
$this->set_language();
}
protected function set_language () {
// Some code to determine which language to set (your logic goes in determine_language method in this class)
$Language = $this->determine_language();
// then we inject the language id in the instance as follows.
$this->CI->CurrentLanguageId = $Language->id;
}
}
// Model
class Some_model extends CI_Model {
public function get_posts () {
$q = $this->db
->where('language_id', $this->CurrentLanguageId)
->limit(10)
->get('posts');
return $q->result();
}
}
Please keep in mind in CodeIgniter 3x the first letter in a library name should be capitalized.
Related
So I tried to create a library in which I can get some "global" data from one of my data tables (site name, logo, favicon, etc).
This is my current library:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Settings {
//holds the CI instance
//var $ci;
protected $ci;
//the array the settings will be stored as
public $settings = array();
//
public function __construct()
{
//load CI instance
$this->ci =& get_instance();
//fire the method loading the data
$this->get_settings();
}
public function get_settings()
{
$this->ci->load->model('settings_model');
$this->settings = $this->ci->Settings_model->get_list();
return $this->settings;
}
}
?>
This library should access to my method get_list() on my Settings_model and so far it seems to be able to do so (keep reading).
This is my settings model:
function __construct()
{
parent::__construct();
$this->table = 'ci_settings';
}
public function get_list()
{
$query = $this->db->get($this->table);
return $query->result();
}
Now to use the data which comes from the database in my views without having to declare them in all my controllers, I just have to do this(I did something similar with my menu library so I know it should work):
<?php echo $this->settings['website_name'] ?>
Here is the PROBLEM, my library is being able to access to my model which seems fine(I suppose), the problem comes when it tries to access to the get_list method itself; is apparently having some issues returning the data as this is the error that I get:
Should not this be possible just like this?.. what I'm trying is to have global variable for logo, website name, etc... I'm sure it should not be that hard but I'm having a really big pain in the *** trying to figure out a solution.
Any idea where is my error?,
Thanks in advance.
Try with ->settings_model-> with S in lowercase, but why ?
CI save the instance of your model internally like a property of the object CI that you have with function get_instance()
Remember: class properties are case sensitive
I was just wondering if there is a way to use codeigniter model in other non Codeigniter classes... Let me give you an example.
I have this MyTestClassTests class which extends PHPUNIT_Framework_testCase
<?php
require_once '../../vendor/autoload.php';
use Facebook\WebDriver\Remote\WebDriverCapabilityType;
use Facebook\WebDriver\Remote\RemoteWebDriver;
use Facebook\WebDriver\WebDriverBy;
use Facebook\WebDriver\Interactions\WebDriverActions;
use Sunra\PhpSimple\HtmlDomParser;
class MyTestClassTests extends PHPUnit_Framework_TestCase
{
public function testDoSomething()
{
// Do some test
// get results
// Store results via Codeigniter Model, if possible?
$results = 'some results';
$this->load->model('results');
$this->results->import($results);
}
}
Now once test is finished i would like to store test results in to the database. Is there a way to call/initialize CodeIgniter model in current class to use it and store data? This file is located in the Codeigniters controllers folder.
If you need any additional information's please let me know and i will provide. Thank you!
Since you appear to be unit testing you should consider using ci_phpunit-test which makes it much easier to use PHPUnit with CodeIgniter 3.x.
Because you're unit testing the following may not apply. These examples only work within an fully instantiated CI framework. Within that context there are a couple ways to give a stand-alone class access to the CI object.
One approach is to capture the CI instance in a class property.
class MyTestClassTests extends PHPUnit_Framework_TestCase
{
protected $CI;
public function __construct()
{
// Assign the CodeIgniter super-object
$this->CI = & get_instance();
}
public function testDoSomething()
{
// Do some test
// get results
// Store results via Codeigniter Model, if possible?
$results = 'some results';
//use the class property to access CI classes and methods
$this->CI->load->model('results');
$this->CI->results->import($results);
}
}
A second approach uses the PHP magic method __get. The advantage is it's much easier to write the code. The disadvantage is it's a tiny bit less efficient because extra code is executed each time you access the CI instance.
class MyTestClassTests extends PHPUnit_Framework_TestCase
{
/**
* Enables the use of CI super-global without having to define an extra variable.
*
* #param $var The CI property or method to access
* #return mixed
*/
public function __get($var)
{
return get_instance()->$var;
}
public function testDoSomething()
{
// Do some test
// get results
// Store results via Codeigniter Model, if possible?
$results = 'some results';
//you get to write code as if you were part of the CI object.
//IOW, you write code normally
$this->load->model('results');
$this->results->import($results);
}
}
In order to use codeigniter model in your non codeigniter class you have to instantiate CI first.
In your case below code will work.
$CI = & get_instance()
$CI->load->model('results');
$CI->results->your_function();
I simply do not mean how to define a global variable/constant in CodeIgniter.
Let me explain:
I have made a theme engine which is select-able from the current logged in user's control panel. This engine is not very complicated, but a simple folder. anyway, what I do across the application, is that I write one line of code to get the current theme selected by the user. I use a one line of code to get the name, and then store it in a variable:
$theme_name = $this->theme->get_theme_with_slash(false);
And then, I user $theme_name like this to get the proper view:
$this->load->view($theme_name.'result', $data);
And in all of my controllers that loads view I should repeat this process. What I need, is to call the function which gets the theme_name and store in the variable and then use the variable/session/function across the application. My approach currently is the helper's function which is a little less convenient compared to session/variable.
I got this from the manual and this what I have at the top of my config/config.php file: (i have a custom config set to paypal testing)
// HOW TO USE - For example if there's $config['foo'] = 'bar';
// in the config
// using $this- >config->item('foo') will be 'bar'.
// example for my paypal testing:
$config['paypaltest']=0;
http://ellislab.com/codeigniter%20/user-guide/libraries/config.html
and how to access in a controller:
$paypaltest = $this->config->item('paypaltest');
Create A core controller, since your process requires logical operations then you need a method for that.
application/core/MY_Controller.php
class MY_Controller Extends CI_Controller
{
protected $default_theme = 'theme';
public function __construct()
{
parent::__construct();
}
public function get_theme()
{
//your code for selecting the current theme selected from
//the database
$theme_from_db = '';
return $theme_from_db == NULL ? $this->default_theme : $theme_from_db;
}
}
Your Controller must extend MY_Controller
application/controller/view.php
class view extends MY_Controller
{
public function index()
{
$this->load->view($this->get_theme().'result', $data);
}
}
in code igniter global constants can be defined in
config->constants.php
even you no need to load it,it automatically autoloaded by CI automatically.
In Codeigniter all constant is defined inside application/config/constant.php.
like: define("CONSTANTNAME","value");
Constant degined here is accessible throughout all pages, ie; controllers, models and views
I am working on building a lightweight MVC, mainly for the learning process but I would like it to be good enough to use eventually.
Below is a basic example/demo of how a basic controller might would look, let's assume the URI has been processed and routed to this controller and these 2 methods.
1) I need to get data from database/cache/etc... inside my Model classes, I just need help on how I should load my models into my example controller below, you can see that I have added this below $profileData = $this->model->getProfile($userId) that is just made up and does not exist's, how could I get something like that to work though? Or should I load the model into the class a different way?
2) A lot of pages will require a user to be logged into the site. SHould I process that part below in the controller to check if a user is logged in, example, before building the profile page, check if user is logged in, if not then build a login page instead and add these checks inside of each controller method/page?
/**
* Example Controller
*/
class User_Controller extends Core_Controller {
// domain.com/user/id-53463463
function profile($userId)
{
//GET data from a Model
$profileData = $this->model->getProfile($userId);
$this->view->load('userProfile', $profileData);
}
// domain.com/user/friends/
function friends()
{
//GET data from a Model
$friendsData = $this->model->getFriendlist();
$this->view->load('userFriends', $friendsData);
}
}
core
abstract class Core_Controller {
protected $view;
protected $model;
function __construct(DependencyContainer $dependencyContainer){
$this->view = new Core_View();
//$this->view = $dependencyContainer->get(view);
}
}
There are probably tons of ways to accomplish what you are trying.
The "easiest" is probably to just override the constructor and instantiate the model directly.
in User_Controller:
public function __construct(DependencyContainer $dc) {
parent::__construct($dc);
$this->model = new User_Model();
}
I'm guessing that you are looking for something a little more automated though. If you want the Model to have the same name as the controller minus "_Controller", just use get_class($this) in the constructor and use PHP's string functions to parse out what you want. Once you have that in a variable, you can use that variable to instantiate the model:
in Core_Controller:
public function __construct(DependencyContainer $dc) {
$this->view = new Core_View();
// $model_class should be 'User_Model' now
$model_class = str_replace('_Controller', '_Model', get_class($this));
// now instantiate the model
$this->model = new $model_class();
}
I haven't actually worked with any framework that can only have one model associated with each controller (except may CakePHP? I can't remember). With Symfony, the models and controllers are completely decoupled so you can use any model with any controller. You just instantiate the model as need. Symfony use the Doctrine ORM so for example, in a controller action, if you needed a model you would do something like this:
$model = Doctrine::getTable('User');
It might be worthwhile to consider a design more like that in order to promote a decoupled design and I promise that you will want more than one model in some controller at some point.
2.) As far as authentication. Something that seems to be fairly common is to have some sort of setting (whether in a config file or a member variable) that says whether or not the current action needs the user to be authenticated. This is processed each time the action runs (Yii calls these kinds of things filters). If the user needs to be logged in, it stores the page that they are trying to access, and then redirects them to a log in page (you should only ever have to create one). Once they properly authenticate, it will redirect them back to where they were originally heading.
Should I not be using Index as the name for a controller class in CodeIgniter? I have an Index controller, and I'm seeing its methods being called multiple times. More specifically, I always see its index method called first, whether or not I'm visiting a path that should be routed there.
In application/controllers/index.php
class Index extends CI_Controller
{
public function index()
{
echo "index";
}
public function blah()
{
echo "blah";
}
}
When I visit index/blah, I see indexblah printed. When I visit index/index, I see indexindex. If I rename the controller to something else (e.g. Foo), it doesn't have a problem. That's the obvious workaround, but can anyone tell me why this is happening? Should I report this as a bug to CodeIgniter?
(Notes: I have no routes set up in configs/routes.php; my index.php is outside the CodeIgniter tree)
To further clarify what the issue is, in PHP4 Constructors were a function that had the same name as the Class...
example
class MyClass
{
public function MyClass()
{
// as a constructor, this function is called every
// time a new "MyClass" object is created
}
}
Now for the PHP5 version (Which codeigniter now, as of 2.0.x, holds as a system requirement)
class MyClass
{
public function __construct()
{
// as a constructor, this function is called every
// time a new "MyClass" object is created
}
}
So To answer the question that addresses the problem...
Should I not be using Index as the name for a controller class in CodeIgniter?
I believe it would be best to not choose Index as a controller name as the index() function has a reserved use in codeigniter. This could cause issues depending on your PHP configuration.
can anyone tell me why this is happening?
When your controller get's instantiated, index as the constructor is getting called.
Compare Constructors and DestructorsDocs:
For backwards compatibility, if PHP 5 cannot find a __construct() function for a given class, it will search for the old-style constructor function, by the name of the class . [highlighting by me]
In your case your Controller does not have any __construct() function but a function that has the same name as the class: index. It is getting called in the moment Codeigniter resolves and loads and then instantiates your Index Controller.
You can solve this by just adding the constructor to your Controller:
class Index extends CI_Controller
{
public function __construct() {}
public function index()
{
echo "index";
}
public function blah()
{
echo "blah";
}
}
After this change, it does not happen again.
Should I report this as a bug to CodeIgniter?
No, there is not really a need to report this as a bug, it's how the language work and as Codeigniter supports PHP 4 it must remain backwards compatible and needs to offer PHP 4 constructors. (Note: The Codeigniter project documents, they need server support for PHP version 5.1.6 or newer, but the actual code has PHP 4 compatiblity build in, I'm referring to the codebase here, not the documentation.)
Here is another solution using Codeigniter3
require_once 'Base.php';
class Index extends Base
{
public function __construct()
{
parent::index();
$classname=$this->router->fetch_class();
$actioname=$this->router->fetch_method();
if($actioname=='index' || $actioname == '')
{
$this->viewall();
}
}
}
And the viewall() had the following
$this->siteinfo['site_title'].=' | Welcome';
$this->load->view('templates/header', $this->siteinfo);
$this->load->view('templates/menu', $this->siteinfo);
$this->load->view('index/viewall', $data);
$this->load->view('templates/footer', $this->siteinfo);
The Base controller does all the library and helper loading for the entire application which is why it is being required in the default class
Basically from my short understanding of CodeIgniter, having a default action as index is a wrong. I found this out by using the printing the result of $this->router->fetch_method(); in the construct() of my index class. The default action by CodeIgniter is index, you may only set the default controller within application/config/routes.php and not the default action.
So my advice, never use index() as the default action especially if you are using index as the default controller