I am trying my hand out with mongodb as a backend to my codeigniter application.
I found and followed this example: http://www.surfinme.com/codeigniter-mongodb/
So I have the following structure:
+application\
libraries\
Mongo_db.php
config\
mongodb.php
controllers\
api.php
This is what my api.php file looks like so far:
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Api extends CI_Controller {
public function __construct()
{
parent::__construct();
//loading the mongodb library
$this->load->library('mongo_db');
}
public function index()
{
$data['main_content'] = "dashboard";
$this->load->view('includes/template',$data);
}
public function list_available()
{
//connect to mongodb collection (i.e., table) named as ‘surfinme_index’
$collection = $this->mongo_db->db->selectCollection('testcollection');
$result=$collection->find();
foreach($result as $data)
{
var_dump($data);
}
}
}
And the code seems to be working. It gets my data out of the database and dumps it to my browser. But this "feels" wrong becuase I don't have a model.
Or should I be viewing the library as my model layer?
I could just as easily create a file in the models folder called api_model and make the calls to the library from there.
But is that overkill?
Any comments would be appreciated.
Thanks.
Depends on how tightly you want to adhere to MVC principals.
By creating a model for database operations you get several potential benefits. First, it provides a source that can be reused by multiple controllers. For example, there may be more than one controller that uses selectCollection. Second, if for some reason you decide to change databases you only have to modify the Models as opposed to every controller that makes calls to mongo_db.
Related
I am working on a Yii1 old website. which is linked with some external PHP controllers. These external controllers provide some common functions that are used between 2 different applications. I have a function in Yii model that I want to use in one of the external PHP controller is there a way to do this? Currently, this is done by rewriting MySQL query in the PHP external controller but I don't want to follow this lame practice.
I found this link and I am able to access Yii externally but it's still not very helpful. Using Yii in 3rd-Party Systems
Here's a sample of my code:
namespace main\Helpers;
require_once('path/to/yii.php');
Class HelperClass {
public static function yiisupport($id){
// I am able to access Yii variables using
\Yii::app()->name
// But how to access the yii model or controller functions? I need something like the follwoing
$model = \Yii::app()->YiiModel::model()->findByPK($id);
}
}
Can anyone help?
You need to create Yii application first (using config file path) to access its models and controllers as it is mentioned in the documentation. Then you can access any model class in your external application just like you would access it in your Yii application, and you can use controller actions as below;
$controller = new \YOURController('ACTION_NAME');
$controller->ACTION_NAME();
If you have already imported models/controllers in your config file then you will not need to import any class but if you have not then you can import specific model/controller like below;
\Yii::import('application.models.MODEL_NAME');
\Yii::import('application.controllers.CONTROLLER_NAME');
Check the examples below;
namespace main\Helpers;
require_once('path/to/yii.php');
\Yii::createWebApplication('path/to/config.php');
Class HelperClass {
public static function yiisupport($id){
// Access Yii variables
\Yii::app()->name;
// Access yii model
$model = \YiiModel::model()->findByPK($id);
// Access yii controller and its actions
$controller = new \YiiController('actionCreate');
$controller->actionCreate();
}
}
Update:
As mentioned by #rob006 in the comment below that calling yii controller action outside Yii application is a bad idea, however if you still want to do that, there is a safer way which follows the Yii application lifecycle and this way access filters and beforeAction() will be triggered. So you can call controller action in a safer way as below;
\Yii::app()->runController('route/to/action');
I have a sidebar in my site that receive some information from db and I can't use controller for retrieve data because I have different controller and same sidebar. How can I print this data in view page.
when I wrote in P.h.P code in the view it shows an error that it cant define variables.
How could I do this?
When you find that you need the same code in many different controllers a "custom library" (class) is the perfect choice. Documentation for creating your own libraries is found HERE.
Controllers should be using models to get data from the database. Custom libraries can also use models just like controllers. Here is a very basic custom library called Sidebar. It depends on a model (sidebar_model) that will not be shown. The purpose of the Sidebar library is to return the variables need by the sidebar_view file.
File: application/libraries/Sidebar.php
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Sidebar
{
protected $CI; // Read the documentation link to see why this is needed.
public function __construct()
{
$this->CI = & get_instance();
$this->CI->load->database(); //only needed if not already done
$this->CI->load->model('sidebar_model');
}
public function get_sidebar_data()
{
return $this->CI->sidebar_model->get_sidebar();
}
}
The library method get_sidebar_data() returns the variables for the view.
Here is a controller that uses the custom library. It will use the custom library and a view file (not shown) containing HTML for the sidebar.
File: application/controllers/Main.php
class Main extends CI_Controller
{
function __construct()
{
parent::__construct();
$this->load->library('sidebar'); //can also be autoloaded
}
public function index()
{
$data['sidebar'] = $this->sidebar->get_sidebar();
$this->load
->view('banner')
->view('sidebar_view', $data)
->view('main_view')
->view('footer_view');
}
}
Any other controller that needs to show the sidebar would use this same pattern.
This controller loads four different view files and is using "method chaining" which is encouraged. Method chaining executes a tiny bit faster. But the best reason for using it? Less typing.
The method chaning could also be type like this:
$this->load->view('banner')->view('sidebar_view', $data)->view('main_view')->view('footer_view');
But, IMO, putting each ->view() on a separate line makes it easier to read.
You can create a helper for your common tasks. Then create a function for your sidebar and call it where you need it. Check this link for more details about creating helper
You can also create a library for it. Although it will not a very good choice.
create sidebar (view page) and Call model directly inside that sidebar (view page).
secondly call sidebar (view page) directly inside all other view pages.
I'm about to write my own library in codeigniter to check if the logged in user is an admin or not. To do that I need to compare a value with the value of the typeAccount in the DB.
Because I'm still learning the MVC pattern I had a question about this before starting to write my library.
Can I load a model in my library? Or should I communicate directly to my DB in my library? Or is there a better way to approach this?
Yes, you can load your model to into your library, simply add CI.
class Validator
{
private $CI = null;
function __construct()
{
$this->CI =& get_instance();
}
public function validate_merchantaccount_status($param)
{
//Code Here
$this->CI->load->model('merchantaccount_model');
$res_merchant = $this->CI->merchantaccount_model->get_list($param);
}
}
Dont forget to make your model.
Since the library is some kind of logic, you can see it as a piece of the Controller.
The Controller usually just loads a Model to use it.
So yes just load the Model from CodeIgniter instead of connecting to the database yourself.
Makes your code more DRY too.
Make you models
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class My_model extends CI_Model
{
/// Here the code
}
And then in controller use
$this->load->model('my_model');
Ant i think that is best approach :)
I am creating a order fulfillment system for mu E-commerce system. I am stuck in a situation. Every 1 hour 1 cron job runs and it assigns ware house and does other processes.So this is a class where i do 1 full process. I need to give option for user to do each of them individually also manually i.e. assign warehouse manually etc. So this warehouse functions will be used in multiple places i.e in cron class and warehouse class. So should i create these functions in 1 library like warehouse.php or else in cron class create instance of each class and call its functions? i am using Codeigniter.
Hope below code makes my self clear. So should i create a warehouse library or a controller is my question.
Main question is to use like this
class cron extends CI_Controller{
function index(){
$this->load->library('blacklist');
$this->load->library('warehouse');
$this->load->library('lsp');
$this->blacklist->function1();
$this->warehouse->function2();
}
}
or
class cron extends CI_Controller{
function index(){
$blacklist = new blacklist();
$warehouse = new warehouse();
$lsp = new lsp();
$blacklist->function1();
$warehouse->function2();
}
}
Set up a MY_Controller in your Core folder which extends CI_Controller - make your normal controllers extend MY_Controller instead of CI_Controller and put the functions you need to access from multiple controllers in there. I did something similar and then restricted my cron controller to cli requests only using an if(!$this->input->is_cli_request()){ exit(); } for added security.
Sample:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class MY_Controller extends CI_Controller {
public function __construct() {
parent::__construct();
}
protected function _order_export()
{
// Export routine goes here
}
}
/* End of file MY_Controller.php */
/* Location: ./application/core/MY_Controller.php */
Make calls to this function using $this->_order_export(); in your other controllers.
Yes, you can. Write a warehouse class/controller or set of functions that can adapt to multiple uses in different part of your system. You can then logically programme the class/function to work for each use.
Very basic pseudo-code:
If (CLI)
{
// do this
} elseif (BATCH) {
// do that
} elseif (MANUAL) {
// do other
}
Helping you any further than this is impossible at this point as we're like blind men in a minefield.
In my CI system\libraries directory I have a new class named DD_Controller.php. This file looks like this:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class DD_Controller extends Controller
{
protected $ddauthentication;
function __construct()
{
parent::Controller();
$this->ddauthentication = "Authenticated";
}
}
?>
My application controller is defined like this:
class Inquiry extends DD_Controller
{...}
The Inquiry class works fine when I extend Controller, but I get a
Fatal error: Class 'DD_Controller' not
found in
C:\development\localhost\applications\inquiry\controllers\inquiry.php
on line 4
When I extend DD_Controller. In the config file I have the prefix defined as such:
$config['subclass_prefix'] = 'DD_';
Any idea of what I'm missing?
TIA
This is a better approach. Do the following:
Go to the following directory: your_ci_app/application/core/ and create a php file called MY_Controller.php (this file will be where your top parent classes will reside)
Open this the file you just created and add your multiple classes, like so:
class Admin_Parent extends CI_Controller {
public function __construct() {
parent::__construct();
}
public function test() {
var_dump("from Admin_Parent");
}
}
class User_Parent extends CI_Controller {
public function __construct() {
parent::__construct();
}
public function test(){
var_dump("from User_Parent");
}
}
Create your children controllers under this directory your_ci_app/application/controllers/ . I will call it adminchild.php
Open adminchild.php and create your controller code, make sure to extend the name of the parent class, like so:
class Adminchild extends Admin_Parent {
function __construct() {
parent::__construct();
}
function test() {
parent::test();
}
}
DD_Controller.php should be in /system/application/libraries/
If you're using the same CI for multiple apps, and you want them all to be able to extends their controllers to your custom one then you can extend the base Controller class in the same file.
In system/libraries/Controller.php below the Controller class:
class Mega_Controller extends Controller {
function Mega_Controller()
{
parent::Controller();
// anything you want to do in every controller, ye shall perform here.
}
}
Then you'll be able to do this in your app controllers:
class Home extends Mega_Controller {
....
Since the extended controller class you created will be available. I think this is better then overwriting the base controller, but that would work as well.
I recommend to avoid "cracking" CodeIgniter core files.
Better use its native extending possibilities and try to fit into them.
The same rule I would recommend for any PHP library / CMS.
This rule has few reasons:
- ability to quiclky upgrade without takint into account thousands of notes where and how was cracked in core files;
- portability;
- possibility to share your code - eg, this will be usable by both you and your friends in case of need, and it will help them to keep their library up to date, the same as you.
In other words, this is much more professional and it pays to you in the future by usability, portability and by update application possibility.
Regarding your personal question...
As for me, there is nothing bad to create your own library with everything you need to extend native CodeIgniter Controller, then load this library in Controller's constructor and you are done. The only thing to make better usability is to give short name to your library.
This way you can even divide what you need in different pieces and put into separate libraries:
WebFeatures
AdminFeatures
etc.
Then you just load needed libraries in your controller's constructor and you are done.
P.S. I know that proposed way does not fit into "right" OOP concept, but in the same time you must never forget about the integrity of the libraries used.
Everything above is just one more view of mine 7-years experience in professional web development, so I hope it will be helpful if not to follow, then at least to take into account.
Regards,
Anton