Best way to name controllers and models in codeigniter - php

I am trying to make some basic web apps using code igniter and I have realized that I have a lot of elements calling controller methods which grab data from its corresponding model and I am trying to figure out the best way to name these methods which pretty much do the same thing.
For an example, say I want to grab all the users on my site. I would have a method in my controller named get_users() and then that method would load and call a method in my model named fetch_users() which would grab the users from the database and return the result_array to the controller and then from there to the view.
This seems a little redundant (Calling get_users() which calls yet another function named fetch_users())
I just want to know if this is the only way to do this sort of action, or if there is another "cleaner" way of doing it.
Hope this makes sense.
Thanks!

I like to separate more code, to be more clear.
For example:
USERS
I crate one controller class with name Users and with:
function index() {} // (where show the list),
function add() {} // (add one user)
function edit($user_id) {} // (edit one user)
function view($user_id) {} // (view one user)
function delete($user_id) {} // (delete one user)
I create one model with name Users_model and with:
function get_list() {} // Get list of users
function get_one($user_id) {} // Get one user
function add() {} // add one user on db
function update($id, $data) {} // Update one user on db
function delete($id) {} // Delete one user on db
In this form I do with other things like (Blog, posts, comments etc).

Dear if you are going to build a large application try to put each of your controllers
and models
in different folders and name all of your controllers as home or index and different name for each folders
for example:
you have a controller for assets so create a folder inside your applications controller
folder and name it assets and than inside this assets create a controller name it home.php
class Home extends CI_Controller
{
function __construct()
{
parent::__construct();
}
}
for models you should use the name of operations which your models perform
for example for CRUD model do create something like this: crud_model
class Crud_model extends CI_Model
{
function __construct()
{
parent::__construct();
}
}
for functions you should give function names which is understandable and separate each part with underlines
for example if you have a function that gets total of users you may do write like this:
function get_total_users()
{}
or for users function
function users()
{
}
for update, delete and insert the same way.

Related

What add to controller and what to models

I have a little problem. What data keep in controllers and what in models? I know in models keep whole logic of applications etc, but what's query and helpers functions? for example
Controller:
public function add(Request $request)
{
$item = new Item()
$item->name = $request->name;
$item->save();
$this->makeDirectory();
}
private function makeDirectory()
{
//make a directory with photo this product
}
Where should I keep "makeDirecory" method in controller or models?
This is another situation when i would delete product and reference from another table.
public function delete(Items $id)
{
$id->delete();
$this->deleteProperties($id->properties); // $id->properties is a method from Items model with references to table Properties
}
private function deleteProperties(Properties $id)
{
$id->delete();
}
Should I keep "deleteProperties" method in controller, Items model or Properties model? and invoke this method from this model?
You should keep methods like makeDirectory() in a service class and call it with:
$this->fileService->makeDirectory($directory);
You should keep data related logic in model classes or repository classes and use it in controller with:
$this->model->getSomeData();
You may also want to google "Fat models, skinny controllers".
Regarding helper functions, you should use these only when you really need one. For example, isAdmin() is a very handy global helper, but you should never create helpers like getAllUsers() or Helpers::getAllUsers()
I use controllers only to validate the incoming data and passing data to views.
I add another layer of classes that I call Departments. So, I have a department for profiles, artiles, info pages etc. Each department has its own namespace and a set of classes connected with the functionality.
Always think about SoC - separation of concerns. If you put a lot of logic into a controller, it will eventually get huge, hard to maintain and extend.
Example:
Controller:
public function addItem (Request $request, Item $item, ItemStorage
$itemStorage) {
if ($item->verifyInput($request->all())) {
$itemStorage->createItem ($item, $request->all());
}
else {
// ... handle input error
}
// ... view
}
App\Departments\Items:
class ItemStorage {
public function createItem ($newItem, $attributes) {
$newItem->create($attributes);
// ... prepare data for creating a directory
$this->makeDirectory($directoryName);
}
private function makeDirectory ($directoryName) {
//... create directory
}
}
You can/should separate the tasks even further. ItemStorage might not need to handle actual directory creation. You can call another department/service class name e.g. DiskManagement. This department would contain Classes like FileSystem. So, inside the makeDirectory() method, you would call a method from a class specialized in file system operations.

how to create multiple models against multiple function in single controller in CakePHP

i think, In "CakePHP" one model is against each controller but i have multiple functions in single controller and each function represent different page and database table.
i.e
public function manage_categories(){}
public function manage_sub_categories(){}
above 2 functions are in Admin Controller but now the issue is how to create model against each function to represent database. each function has unique attributes in database.
One thing more either model name should be same to controller name "admin" or this name will be same as functions name. while in normal circumstances model name is same to controller name.
"Users" model name is used against "UsersController"
kindly guide me ti resolve above said issue. i tried enough to solve it bot couldn't.
Thanks in advance.
If you have two database tables it would be logical and best practice in terms of SoC to have two controllers instead of throwing a lot different things that don't belong into the same domain into a single controller.
Sometimes when you just want to use a part of data from an associated model you can access it through the associations:
$this->Model->SubModel->foo();
Also you say you have an admin controller which is a working but not very good approach. Instead CakePHP features prefix routing. So an action accessed like /admin/categories/some_action will route to the CategoriesController some_action() action.
"Users" model name is used against "UsersController"
Is wrong, by convention models should be named singular, not plural. Your UsersController won't find an Users model because it's looking for an User model.
And stay away from Model::query(), use the ORM instead as much as you can.
public function manage_categories(){}
public function manage_sub_categories(){}
Should become:
class CategoriesController extends AppController {
public function admin_index() { /*...*/ }
}
class SubCategoriesController extends AppController {
public function admin_index() { /*...*/ }
}
But assuming that sub-categories belong to a category which is the same table I don't see a need for a second model or second controller at all.

How to load Model into a controller in MVC

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.

How do i restrict the list in a referenced model in ATK4

I have a model called Task defined like this (fields not relevent to question removed)
<?php
class Model_Task extends Model_Table {
public $entity_code='vscrum_task';
public $table_alias='tk';
function init(){
parent::init();
// debug causes error in Ajax in ATK v4.1.1
// $this->debug(true);
$this->addField('id')->system(true)->visible(false);
$this->addField('task_desc')->mandatory(true)->visible(true);
$this->addField('tasktype_id')->mandatory(true)->refModel('Model_TaskType');
$this->addField('team_id')->system(true)->visible(false);
and the refModel tasktype is defined like this (fields not relevent to question removed)
<?php
class Model_TaskType extends Model_Table {
public $entity_code='vscrum_tasktype';
public $table_alias='ty';
function init(){
parent::init();
$this->addField('id')->mandatory(true);
$this->addField('name')->mandatory(true);
$this->addField('team_id');
}
}
I have a CRUD which is based on task and is now (thanks to help from Jancha and Romans on stackoverflow) is working fine.
I want to limit the options in the drop down for TaskType to only those tasktypes defined for the user's team. I tried putting an addCondition in the TaskType Model referencing a session variable i had previously memorized
$this->addCondition('team_id',$p->api->recall('team_id'));
and also using a direct call to a value for the logged in use
$this->addCondition('team_id',$p->api->auth->get('team_id'));
but this results in showing the Tasktype fine in the Grid
but leaves it empty for both Edit and Add in the Ajax dialog.
If i remove the addCondition line from the TaskType Model, it shows all values in the list but i will always want this restricted to a subset.
As this is the referred Model and not the Model that the CRUD is based on, any suggestions on how i get this to work as expected ?
I tried Roman's suggestion of having a model which is the TaskType and a new model extended from that which is the TaskType_Team with the addCondition in it like this
class Model_TaskType_Team extends Model_TaskType {
function init(){
parent::init();
$this->addCondition('team_id',$p->api->auth->get('team_id'));
}
for which i needed to create a subdirectory undel Model called TaskType otherwise it didnt find the new Model but the end result is the same. I think this is related to another issue i previously had where the Ajax dialog loses access to $p->api and so doesnt display the restriction (and this is why it works fine for the grid on the same page as that isnt in an ajax dialog but i dont want to use a stickyGet to resolve this for security (dont want to be able to modify the URL to see other teams data) and session variables ($p->auth->memorise and $p->auth->recall) also dont seem work in this case - any further suggestions ?
Remember that you can extend your models like that. In fact, this is very often used in larger projects.
class Model_TaskType_Team extends Model_TaskType {
function init(){
parent::init();
$this->addCondition('team_id',$this->api->auth->get('team_id'));
}
}

How to make a proper index page for subdirectories in CodeIgniter

I'm building an app that has a section for consumers and businesses, and I want to separate the controllers folder appropriately, so it looks like this -
http://domain.com/users/signup/
http://domain.com/business/signup/
I have it working by creating a separate folder for each section in the "controllers" folder, but I want to know how to make an appropriate page when the user visits the http://domain.com/users/. It currently just loads the homepage. How can I fix this?
You don't need to put them in separate folders for this to work.
File system/application/controllers/users.php:
<?php
class Users extends Controller {
function index() {
// this function will be called at http://domain.com/users
}
function signup() {
// this function will be called at http://domain.com/users/signup
}
}
?>
File system/application/controllers/business.php:
<?php
class Business extends Controller {
function index() {
// this function will be called at http://domain.com/business
}
function signup() {
// this function will be called at http://domain.com/business/signup
}
}
?>
If I understand your question correct, you might be looking for URI Routing. I don't see why you would need folders for this. Simply just create the routes you need and make use of the index methods in the controllers for making the "homepage" for both users and business.

Categories