
CodeIgniter Application Development Standard
And we use internal standards. They are really useful:
- standards do not have to be followed ;
- they allow you to learn faster and more comfortably;
- they help to get less lost in the creative process.
Historically, we are actively using CodeIgniter. The CodeIgniter application development standard is brought to your attention.
1. One controller must be responsible for one functional module.
2. Modules with cross functionality can be allocated to separate controllers, or connected to existing ones. In both cases, the architectural solution should be the same for the entire product.
3. In each controller method, the functional zones should be taken into account and, if possible, divided:
- access rights;
- receiving and processing data;
- data output.
In this case, both the use of the _remap () method and the extension of the controller class, as well as duplication of functional zones in each method are allowed. It is important that actions are clearly defined and separated.
4. Do not use routing if this can be avoided.
5. Do not output data from the controller, bypassing the class Output (display), if it is not AMF.
6. It makes sense to use private functions to reduce code with identical functionality.
7. The code of the public methods of the controllers should be high-level, concise and concise. It makes sense to perform all obvious routine actions in private methods of controllers, in models, mappings, helpers or libraries.
8. It makes sense to use clear and concise method names, which will give beautiful and obvious URLs, which, among other things, contributes to a more comfortable accompaniment of the program.
1. Each model performs actions only with its associated entity.
2. If possible, each entity must correspond to one table in the database. If additional tables are required for servicing, for example, relationships, it makes sense to consider the question: whether or not to make the relationship an additional entity with its model.
3. It makes sense to expand the class of models (example below).
4. It makes sense to use ORM.
5. It makes sense to avoid complex queries in favor of a series of simple queries that allow you to cache data and perform more flexible and faster processing.
6. Use Active Record.
7. Do not store information in the database that does not change during program execution.
1. It makes sense to create and use an alias for $ this-> load-> view ($ view, $ data, TRUE ) in the procedural context (example below).
2. Mappings may load other mappings. You should use this opportunity:
- to organize the hierarchical structure of the output
- to separate the functional logic of the output and routines from the templates
- to separate the design templates. For example, this makes it possible to quickly and literally switch designs
- for formatting structural and functional output (HTML page, JSON, HTML fragment, dynamic data)
3. It is not necessary to generate files and non-dynamic data in displays
4. In the displays, you can change the format of the data presentation. But you should not change the contents of the data in the displays - for this there is the OOP power of controllers, models and libraries, as well as procedural helpers.
5. You should not use JavaScript in mappings, unless there is an obvious need for the opposite.
1. It makes sense to create your own configuration files, since native ones tend to be updated along with the framework.
2. It makes sense to use subdirectories for functional configurations.
3. It is advisable to make out in the configuration all specific data and data that may change during the development of the project, instead of explicitly indicating them in the program code. This allows you to quickly find them, and comfortably modify.
4. For some configuration data that may change during the development of the project, it makes sense to provide denormalization in the database to ensure the correctness of the story.
1. Do not create a library if the need for its creation is not obvious. For example, instead of a library, you can create a controller.
2. Libraries use an object context, and this must be considered before its design.
General remarks
1. It is very useful to study, follow and re-read the Style Guide at least once a year.
2. It makes sense to use the solutions available in the framework before creating your own alternatives.
3. The framework is reliably super lightweight. This is confirmed by many tests and studies. It makes no sense to optimize it.
4. It makes sense to use debugging tools built into the framework (profiler and error logging modes).
5. It makes sense to place the application and system directories, as well as other files that should not be accessible by default to site users, above the Document Root of the virtual host.
6. Before you design something fundamentally new, it makes sense to peek in Google, on GitHub and BitBucket, the implementation of similar tasks. With a probability of 99%, any arbitrary problem has already been solved. All trivial tasks have several solutions for CodeIgniter.
7. In startup, it makes sense to indicate what is reliably often used in the current and subsequent applications.
8. It is not necessary to specify in the startup specific resources that can be loaded in the designers of the controllers.
9. Comments are good when they are relevant, concise, and written in English.
10. TODO must be marked with the keyword TODO.
11. Before using third-party libraries, make sure that they are written in PHP5 (and not PHP4)
Extension option application / core / MY_Model.php
With this extension, the models look ascetic, and have the same API for most of the actions.
The design () function in application / helpers / MY_html_helper.php, which is often missing.
Hint if you liked the material. Tell me what is missing, what can be supplemented.
- standards do not have to be followed ;
- they allow you to learn faster and more comfortably;
- they help to get less lost in the creative process.
Historically, we are actively using CodeIgniter. The CodeIgniter application development standard is brought to your attention.
Controllers
1. One controller must be responsible for one functional module.
2. Modules with cross functionality can be allocated to separate controllers, or connected to existing ones. In both cases, the architectural solution should be the same for the entire product.
3. In each controller method, the functional zones should be taken into account and, if possible, divided:
- access rights;
- receiving and processing data;
- data output.
In this case, both the use of the _remap () method and the extension of the controller class, as well as duplication of functional zones in each method are allowed. It is important that actions are clearly defined and separated.
4. Do not use routing if this can be avoided.
5. Do not output data from the controller, bypassing the class Output (display), if it is not AMF.
6. It makes sense to use private functions to reduce code with identical functionality.
7. The code of the public methods of the controllers should be high-level, concise and concise. It makes sense to perform all obvious routine actions in private methods of controllers, in models, mappings, helpers or libraries.
8. It makes sense to use clear and concise method names, which will give beautiful and obvious URLs, which, among other things, contributes to a more comfortable accompaniment of the program.
Models
1. Each model performs actions only with its associated entity.
2. If possible, each entity must correspond to one table in the database. If additional tables are required for servicing, for example, relationships, it makes sense to consider the question: whether or not to make the relationship an additional entity with its model.
3. It makes sense to expand the class of models (example below).
4. It makes sense to use ORM.
5. It makes sense to avoid complex queries in favor of a series of simple queries that allow you to cache data and perform more flexible and faster processing.
6. Use Active Record.
7. Do not store information in the database that does not change during program execution.
Mappings
1. It makes sense to create and use an alias for $ this-> load-> view ($ view, $ data, TRUE ) in the procedural context (example below).
2. Mappings may load other mappings. You should use this opportunity:
- to organize the hierarchical structure of the output
- to separate the functional logic of the output and routines from the templates
- to separate the design templates. For example, this makes it possible to quickly and literally switch designs
- for formatting structural and functional output (HTML page, JSON, HTML fragment, dynamic data)
3. It is not necessary to generate files and non-dynamic data in displays
4. In the displays, you can change the format of the data presentation. But you should not change the contents of the data in the displays - for this there is the OOP power of controllers, models and libraries, as well as procedural helpers.
5. You should not use JavaScript in mappings, unless there is an obvious need for the opposite.
Configuration
1. It makes sense to create your own configuration files, since native ones tend to be updated along with the framework.
2. It makes sense to use subdirectories for functional configurations.
3. It is advisable to make out in the configuration all specific data and data that may change during the development of the project, instead of explicitly indicating them in the program code. This allows you to quickly find them, and comfortably modify.
4. For some configuration data that may change during the development of the project, it makes sense to provide denormalization in the database to ensure the correctness of the story.
Libraries
1. Do not create a library if the need for its creation is not obvious. For example, instead of a library, you can create a controller.
2. Libraries use an object context, and this must be considered before its design.
General remarks
1. It is very useful to study, follow and re-read the Style Guide at least once a year.
2. It makes sense to use the solutions available in the framework before creating your own alternatives.
3. The framework is reliably super lightweight. This is confirmed by many tests and studies. It makes no sense to optimize it.
4. It makes sense to use debugging tools built into the framework (profiler and error logging modes).
5. It makes sense to place the application and system directories, as well as other files that should not be accessible by default to site users, above the Document Root of the virtual host.
6. Before you design something fundamentally new, it makes sense to peek in Google, on GitHub and BitBucket, the implementation of similar tasks. With a probability of 99%, any arbitrary problem has already been solved. All trivial tasks have several solutions for CodeIgniter.
7. In startup, it makes sense to indicate what is reliably often used in the current and subsequent applications.
8. It is not necessary to specify in the startup specific resources that can be loaded in the designers of the controllers.
9. Comments are good when they are relevant, concise, and written in English.
10. TODO must be marked with the keyword TODO.
11. Before using third-party libraries, make sure that they are written in PHP5 (and not PHP4)
Extension option application / core / MY_Model.php
_table = strtolower(get_class($this));
}
function get_count($factors = FALSE)
{
if ($factors)
{
$this->db->where($factors);
}
return $this->db->
count_all_results($this->_table);
}
function get_item($id)
{
$id = intval($id);
if ( ! $id)
{
return FALSE;
}
return $this->db->
where('id',$id)->
get($this->_table)->
row();
}
function get_item_by($factors) // by some parameters
{
if ( ! $factors)
{
return FALSE;
}
return $this->db->
where($factors)->
get($this->_table)->
row();
}
/**
* Get list of items
*
* $all_items = $this->get_list(FALSE);
* $all_active_items = $this->get_list();
* $all_active_items_by_pages = $this->get_list(TRUE,$from,$limit);
* $all_deleted_items = $this->get_list('deleted');
* $some_items = $this->get_list(array(
'is_active' => TRUE,
'counter >=' => 10
),
$from,
FALSE,
'created',
'desc'
);
*/
function get_list($factors = array('is_active' => 1),$from = FALSE, $limit = FALSE,$order = FALSE,$direction = 'asc')
{
if ( ! is_array($factors))
{
if (TRUE === $factors)
{
$this->db->where($this->_active_key,1);
}
elseif ('deleted' == $factors)
{
$this->db->where($this->_active_key,NULL);
}
elseif ('active' == $factors)
{
$this->db->where($this->_active_key,1);
}
}
elseif ($factors)
{
$this->db->where($factors);
}
if ($order)
{
$this->db->
order_by($order,$direction);
}
if ($limit == FALSE)
{
return $this->db->
get($this->_table)->
result();
}
else
{
return $this->db->
get($this->_table, $limit, $from)->
result();
}
}
// Get active elements
function get_active($from = FALSE, $limit = FALSE,$order = FALSE,$direction = 'asc')
{
return $this->get_list(TRUE,$from,$limit,$order,$direction);
}
// Get deleted elements
function get_deleted($from = FALSE, $limit = FALSE,$order = FALSE,$direction = 'asc')
{
return $this->get_list('deleted',$from,$limit,$order,$direction);
}
// add item from post data
function add($fields,$data = FALSE)
{
foreach ($fields as $field)
{
$this->db->set($field['field'],$this->input->post($field['field']));
}
$this->accordion('add');
return $this->insert($data);
}
// data insert
function insert($data = FALSE)
{
if ($data)
{
$this->db->set($data);
}
$this->db->insert($this->_table);
return $this->db->insert_id();
}
// edit record
function edit($id,$fields,$data = FALSE)
{
foreach ($fields as $field)
{
$this->db->set($field['field'],$this->input->post($field['field']));
}
$this->accordion('edit');
$this->update($id,$data);
}
// update record
function update($id,$data = FALSE) // found by ID
{
$id = intval($id);
if ( ! $id)
{
return FALSE;
}
if ($data)
{
$this->db->
where($this->_primary_key,$id)->
update($this->_table, $data);
}
else
{
$this->db->
where($this->_primary_key,$id)->
update($this->_table);
}
}
// set records parameter
function set_property($id, $key, $value)
{
$this->db->
where($this->_primary_key, $id)->
set($key, $value)->
update($this->_table);
}
// enable item
function enable($item)
{
$active_key = $this->_active_key;
if ($item->$active_key)
{
return;
}
$primary_key = $this->_primary_key;
$this->set_property($item->$primary_key,$active_key,1);
}
// delete item
function disable($item)
{
$active_key = $this->_active_key;
if ( ! $item->$active_key)
{
return;
}
$primary_key = $this->_primary_key;
$this->set_property($item->$primary_key,$active_key,NULL);
}
// related items
var $list = array();
function set_related($data,$key = 'uid')
{
if ( ! $data)
{
return;
}
if (is_array($data))
{
if (isset($data[$key]))
{
$this->list[$data[$key]] = FALSE;
return;
}
foreach ($data as $row)
{
if (is_object($row))
{
if (isset($row->$key))
{
$this->list[$row->$key] = FALSE;
}
}
elseif (is_array($row))
{
if (isset($row[$key]))
{
$this->list[$row[$key]] = FALSE;
}
}
elseif (is_numeric($row))
{
$this->list[$row] = FALSE;
}
}
}
elseif (is_object($data))
{
if (isset($data->$key))
{
$this->list[$data->$key] = FALSE;
}
}
elseif (is_numeric($data))
{
$this->list[(int)$data] = FALSE;
}
}
// load list data
function load_related($list = FALSE,$key = 'uid')
{
if ($list)
{
$this->set_related($list,$key);
}
if (empty($this->list))
{
return;
}
$keys = array_keys($this->list);
$listing = $this->db->
where_in($this->_primary_key,$keys)->
get($this->_table)->
result();
if ( ! $listing)
{
return;
}
foreach ($listing as $record)
{
$this->list[$record->id] = $record;
}
}
// returns related items
function related($list = FALSE,$key = 'uid')
{
$this->load_related($list,$key);
return $this->list;
}
// set or update standart fields
function accordion($action = 'add')
{
if ( ! in_array($action,array('add','edit')))
{
// dont knew what to do
return;
}
// get table
// found acquaintance fields
// make some actions
$this->config->load('tables/'.$this->_table,TRUE);
$fields = config_item('tables/'.$this->_table);
if ($action == 'add')
{
if (array_key_exists('created',$fields))
{
$this->db->set('created',time());
}
if (array_key_exists($this->_active_key,$fields))
{
$this->db->set($this->_active_key,1);
}
if (array_key_exists('uid',$fields))
{
if ($this->user)
{
$this->db->set('uid',$this->user->profile['id']);
}
}
}
elseif ($action == 'edit')
{
if (array_key_exists('created',$fields))
{
if (array_key_exists('updated',$fields))
{
$this->db->set('updated',time());
}
}
if (array_key_exists('changed',$fields))
{
$this->db->set('changed',time());
}
}
}
// counter increment
function increment($id,$field)
{
$this->db->
set($field,$field.' + 1',FALSE)->
where($this->_primary_key,$id)->
update($this->_table);
}
// counter decrement
function decrement($id,$field)
{
$this->db->
set($field,$field . ' - 1 ',FALSE)->
where($this->_primary_key,$id)->
update($this->_table);
}
// move item up
function move_up($item,$sortorder = 'sortorder')
{
$active_key = $this->_active_key;
$prev = $this->db->
where('`'.$sortorder.'` < '.$item->$sortorder)->
where($active_key,$item->$active_key)->
order_by($sortorder,'DESC')->
get($this->_table)->
row();
if ($prev)
{
$primary_key = $this->_primary_key;
$this->db->
set($sortorder,$prev->$sortorder)->
where($primary_key,$item->$primary_key)->
update($this->_table);
$this->db->
set($sortorder,$item->$sortorder)->
where($primary_key,$prev->$primary_key)->
update($this->_table);
}
}
// move item down
function move_down($item,$sortorder = 'sortorder')
{
$active_key = $this->_active_key;
$prev = $this->db->
where('`'.$sortorder.'` > '.$item->sortorder)->
where($active_key,$item->is_active)->
order_by($sortorder)->
get($this->_table)->
row();
if ($prev)
{
$primary_key = $this->_primary_key;
$this->db->
set($sortorder,$prev->$sortorder)->
where($primary_key,$item->$primary_key)->
update($this->_table);
$this->db->
set($sortorder,$item->$sortorder)->
where($primary_key,$prev->$primary_key)->
update($this->_table);
}
}
}
With this extension, the models look ascetic, and have the same API for most of the actions.
The design () function in application / helpers / MY_html_helper.php, which is often missing.
function design($view,$data = FALSE)
{
$CI =& get_instance();
return $CI->load->view($view,$data,TRUE);
}
Hint if you liked the material. Tell me what is missing, what can be supplemented.