diff options
author | Andrey Andreev <narf@bofh.bg> | 2011-10-20 08:22:12 +0200 |
---|---|---|
committer | Andrey Andreev <narf@bofh.bg> | 2011-10-20 08:22:12 +0200 |
commit | d8442dd015d9e16929825bc51f3cac25c2f74c73 (patch) | |
tree | b9d1a059683b0e31cf056150cc375941a91be252 | |
parent | 56b21e1233855e9ea87ece7bb92e7994042b9cb3 (diff) | |
parent | 9fca615492ba481f5c27890b3b61f0603f45c55b (diff) |
Merge remote-tracking branch 'upstream/develop' into ci-oci8-driver-php5
31 files changed, 1278 insertions, 252 deletions
diff --git a/application/config/constants.php b/application/config/constants.php index 4a879d360..ee177f5ad 100644 --- a/application/config/constants.php +++ b/application/config/constants.php @@ -36,6 +36,18 @@ define('FOPEN_READ_WRITE_CREATE', 'a+b'); define('FOPEN_WRITE_CREATE_STRICT', 'xb'); define('FOPEN_READ_WRITE_CREATE_STRICT', 'x+b'); +/* +|-------------------------------------------------------------------------- +| Display Debug backtrace +|-------------------------------------------------------------------------- +| +| If set to TRUE, a backtrace will be displayed along with php errors. If +| error_reporting is disabled, the backtrace will not display, regardless +| of this setting +| +*/ +define('SHOW_DEBUG_BACKTRACE', TRUE); + /* End of file constants.php */ /* Location: ./application/config/constants.php */
\ No newline at end of file diff --git a/application/config/migration.php b/application/config/migration.php index 1f532f170..3ca47f688 100644 --- a/application/config/migration.php +++ b/application/config/migration.php @@ -1,71 +1,71 @@ -<?php defined('BASEPATH') OR exit('No direct script access allowed');
-/*
-|--------------------------------------------------------------------------
-| Enable/Disable Migrations
-|--------------------------------------------------------------------------
-|
-| Migrations are disabled by default for security reasons.
-| You should enable migrations whenever you intend to do a schema migration
-| and disable it back when you're done.
-|
-*/
-$config['migration_enabled'] = FALSE;
-
-/*
-|--------------------------------------------------------------------------
-| Migrations table
-|--------------------------------------------------------------------------
-|
-| This is the name of the table that will store the current migrations state.
-| When migrations runs it will store in a database table which migration
-| level the system is at. It then compares the migration level in the this
-| table to the $config['migration_version'] if they are not the same it
-| will migrate up. This must be set.
-|
-*/
-$config['migration_table'] = 'migrations';
-
-
-/*
-|--------------------------------------------------------------------------
-| Auto Migrate To Latest
-|--------------------------------------------------------------------------
-|
-| If this is set to TRUE when you load the migrations class and have
-| $config['migration_enabled'] set to TRUE the system will auto migrate
-| to your latest migration (whatever $config['migration_version'] is
-| set to). This way you do not have to call migrations anywhere else
-| in your code to have the latest migration.
-|
-*/
-$config['migration_auto_latest'] = FALSE;
-
-
-/*
-|--------------------------------------------------------------------------
-| Migrations version
-|--------------------------------------------------------------------------
-|
-| This is used to set migration version that the file system should be on.
-| If you run $this->migration->latest() this is the version that schema will
-| be upgraded / downgraded to.
-|
-*/
-$config['migration_version'] = 0;
-
-
-/*
-|--------------------------------------------------------------------------
-| Migrations Path
-|--------------------------------------------------------------------------
-|
-| Path to your migrations folder.
-| Typically, it will be within your application path.
-| Also, writing permission is required within the migrations path.
-|
-*/
-$config['migration_path'] = APPPATH . 'migrations/';
-
-
-/* End of file migration.php */
+<?php defined('BASEPATH') OR exit('No direct script access allowed'); +/* +|-------------------------------------------------------------------------- +| Enable/Disable Migrations +|-------------------------------------------------------------------------- +| +| Migrations are disabled by default for security reasons. +| You should enable migrations whenever you intend to do a schema migration +| and disable it back when you're done. +| +*/ +$config['migration_enabled'] = FALSE; + +/* +|-------------------------------------------------------------------------- +| Migrations table +|-------------------------------------------------------------------------- +| +| This is the name of the table that will store the current migrations state. +| When migrations runs it will store in a database table which migration +| level the system is at. It then compares the migration level in the this +| table to the $config['migration_version'] if they are not the same it +| will migrate up. This must be set. +| +*/ +$config['migration_table'] = 'migrations'; + + +/* +|-------------------------------------------------------------------------- +| Auto Migrate To Latest +|-------------------------------------------------------------------------- +| +| If this is set to TRUE when you load the migrations class and have +| $config['migration_enabled'] set to TRUE the system will auto migrate +| to your latest migration (whatever $config['migration_version'] is +| set to). This way you do not have to call migrations anywhere else +| in your code to have the latest migration. +| +*/ +$config['migration_auto_latest'] = FALSE; + + +/* +|-------------------------------------------------------------------------- +| Migrations version +|-------------------------------------------------------------------------- +| +| This is used to set migration version that the file system should be on. +| If you run $this->migration->latest() this is the version that schema will +| be upgraded / downgraded to. +| +*/ +$config['migration_version'] = 0; + + +/* +|-------------------------------------------------------------------------- +| Migrations Path +|-------------------------------------------------------------------------- +| +| Path to your migrations folder. +| Typically, it will be within your application path. +| Also, writing permission is required within the migrations path. +| +*/ +$config['migration_path'] = APPPATH . 'migrations/'; + + +/* End of file migration.php */ /* Location: ./application/config/migration.php */
\ No newline at end of file diff --git a/application/errors/error_php.php b/application/errors/error_php.php index f085c2037..514e477e8 100644 --- a/application/errors/error_php.php +++ b/application/errors/error_php.php @@ -7,4 +7,21 @@ <p>Filename: <?php echo $filepath; ?></p> <p>Line Number: <?php echo $line; ?></p> +<?php if(defined('SHOW_DEBUG_BACKTRACE') && SHOW_DEBUG_BACKTRACE === TRUE): ?> + + <p>Backtrace: </p> + <?php foreach(debug_backtrace() as $error): ?> + + <?php if(isset($error['file']) && ! stristr($error['file'], SYSDIR)): ?> + <p style="margin-left:10px"> + File: <?php echo $error['file'] ?><br /> + Line: <?php echo $error['line'] ?><br /> + Function: <?php echo $error['function'] ?> + </p> + <? endif ?> + + <? endforeach ?></p> + +<?php endif ?> + </div>
\ No newline at end of file diff --git a/system/core/Loader.php b/system/core/Loader.php index de0fc06d2..5539aae14 100755..100644 --- a/system/core/Loader.php +++ b/system/core/Loader.php @@ -616,6 +616,11 @@ class CI_Loader { require BASEPATH.'libraries/Driver.php'; } + if ($library == '') + { + return FALSE; + } + // We can save the loader some time since Drivers will *always* be in a subfolder, // and typically identically named to the library if ( ! strpos($library, '/')) diff --git a/system/database/DB_active_rec.php b/system/database/DB_active_rec.php index 83518232e..f99d13ec8 100644 --- a/system/database/DB_active_rec.php +++ b/system/database/DB_active_rec.php @@ -28,39 +28,42 @@ */ class CI_DB_active_record extends CI_DB_driver { - var $ar_select = array(); - var $ar_distinct = FALSE; - var $ar_from = array(); - var $ar_join = array(); - var $ar_where = array(); - var $ar_like = array(); - var $ar_groupby = array(); - var $ar_having = array(); - var $ar_keys = array(); - var $ar_limit = FALSE; - var $ar_offset = FALSE; - var $ar_order = FALSE; - var $ar_orderby = array(); - var $ar_set = array(); - var $ar_wherein = array(); - var $ar_aliased_tables = array(); - var $ar_store_array = array(); + protected $return_delete_sql = FALSE; + protected $reset_delete_data = FALSE; + + protected $ar_select = array(); + protected $ar_distinct = FALSE; + protected $ar_from = array(); + protected $ar_join = array(); + protected $ar_where = array(); + protected $ar_like = array(); + protected $ar_groupby = array(); + protected $ar_having = array(); + protected $ar_keys = array(); + protected $ar_limit = FALSE; + protected $ar_offset = FALSE; + protected $ar_order = FALSE; + protected $ar_orderby = array(); + protected $ar_set = array(); + protected $ar_wherein = array(); + protected $ar_aliased_tables = array(); + protected $ar_store_array = array(); // Active Record Caching variables - var $ar_caching = FALSE; - var $ar_cache_exists = array(); - var $ar_cache_select = array(); - var $ar_cache_from = array(); - var $ar_cache_join = array(); - var $ar_cache_where = array(); - var $ar_cache_like = array(); - var $ar_cache_groupby = array(); - var $ar_cache_having = array(); - var $ar_cache_orderby = array(); - var $ar_cache_set = array(); + protected $ar_caching = FALSE; + protected $ar_cache_exists = array(); + protected $ar_cache_select = array(); + protected $ar_cache_from = array(); + protected $ar_cache_join = array(); + protected $ar_cache_where = array(); + protected $ar_cache_like = array(); + protected $ar_cache_groupby = array(); + protected $ar_cache_having = array(); + protected $ar_cache_orderby = array(); + protected $ar_cache_set = array(); - var $ar_no_escape = array(); - var $ar_cache_no_escape = array(); + protected $ar_no_escape = array(); + protected $ar_cache_no_escape = array(); // -------------------------------------------------------------------- @@ -660,7 +663,7 @@ class CI_DB_active_record extends CI_DB_driver { $prefix = (count($this->ar_like) == 0) ? '' : $type; $v = $this->escape_like_str($v); - + if ($side == 'none') { $like_statement = $prefix." $k $not LIKE '{$v}'"; @@ -931,7 +934,37 @@ class CI_DB_active_record extends CI_DB_driver { return $this; } + + // -------------------------------------------------------------------- + /** + * Get SELECT query string + * + * Compiles a SELECT query string and returns the sql. + * + * @access public + * @param string the table name to select from (optional) + * @param boolean TRUE: resets AR values; FALSE: leave AR vaules alone + * @return string + */ + public function get_compiled_select($table = '', $reset = TRUE) + { + if ($table != '') + { + $this->_track_aliases($table); + $this->from($table); + } + + $select = $this->_compile_select(); + + if ($reset === TRUE) + { + $this->_reset_select(); + } + + return $select; + } + // -------------------------------------------------------------------- /** @@ -1148,6 +1181,41 @@ class CI_DB_active_record extends CI_DB_driver { return $this; } + + // -------------------------------------------------------------------- + + /** + * Get INSERT query string + * + * Compiles an insert query and returns the sql + * + * @access public + * @param string the table to insert into + * @param boolean TRUE: reset AR values; FALSE: leave AR values alone + * @return string + */ + public function get_compiled_insert($table = '', $reset = TRUE) + { + if ($this->_validate_insert($table) === FALSE) + { + return FALSE; + } + + $sql = $this->_insert( + $this->_protect_identifiers( + $this->ar_from[0], TRUE, NULL, FALSE + ), + array_keys($this->ar_set), + array_values($this->ar_set) + ); + + if ($reset === TRUE) + { + $this->_reset_write(); + } + + return $sql; + } // -------------------------------------------------------------------- @@ -1156,17 +1224,50 @@ class CI_DB_active_record extends CI_DB_driver { * * Compiles an insert string and runs the query * + * @access public * @param string the table to insert data into * @param array an associative array of insert values * @return object */ - function insert($table = '', $set = NULL) + public function insert($table = '', $set = NULL) { if ( ! is_null($set)) { $this->set($set); } + + if ($this->_validate_insert($table) === FALSE) + { + return FALSE; + } + + $sql = $this->_insert( + $this->_protect_identifiers( + $this->ar_from[0], TRUE, NULL, FALSE + ), + array_keys($this->ar_set), + array_values($this->ar_set) + ); + $this->_reset_write(); + return $this->query($sql); + } + + // -------------------------------------------------------------------- + + /** + * Validate Insert + * + * This method is used by both insert() and get_compiled_insert() to + * validate that the there data is actually being set and that table + * has been chosen to be inserted into. + * + * @access public + * @param string the table to insert data into + * @return string + */ + protected function _validate_insert($table = '') + { if (count($this->ar_set) == 0) { if ($this->db_debug) @@ -1186,14 +1287,13 @@ class CI_DB_active_record extends CI_DB_driver { } return FALSE; } - - $table = $this->ar_from[0]; } - - $sql = $this->_insert($this->_protect_identifiers($table, TRUE, NULL, FALSE), array_keys($this->ar_set), array_values($this->ar_set)); - - $this->_reset_write(); - return $this->query($sql); + else + { + $this->ar_from[0] = $table; + } + + return TRUE; } // -------------------------------------------------------------------- @@ -1242,7 +1342,39 @@ class CI_DB_active_record extends CI_DB_driver { $this->_reset_write(); return $this->query($sql); } + + // -------------------------------------------------------------------- + /** + * Get UPDATE query string + * + * Compiles an update query and returns the sql + * + * @access public + * @param string the table to update + * @param boolean TRUE: reset AR values; FALSE: leave AR values alone + * @return string + */ + public function get_compiled_update($table = '', $reset = TRUE) + { + // Combine any cached components with the current statements + $this->_merge_cache(); + + if ($this->_validate_update($table) === FALSE) + { + return FALSE; + } + + $sql = $this->_update($this->_protect_identifiers($this->ar_from[0], TRUE, NULL, FALSE), $this->ar_set, $this->ar_where, $this->ar_orderby, $this->ar_limit); + + if ($reset === TRUE) + { + $this->_reset_write(); + } + + return $sql; + } + // -------------------------------------------------------------------- /** @@ -1265,6 +1397,42 @@ class CI_DB_active_record extends CI_DB_driver { $this->set($set); } + if ($this->_validate_update($table) === FALSE) + { + return FALSE; + } + + if ($where != NULL) + { + $this->where($where); + } + + if ($limit != NULL) + { + $this->limit($limit); + } + + $sql = $this->_update($this->_protect_identifiers($this->ar_from[0], TRUE, NULL, FALSE), $this->ar_set, $this->ar_where, $this->ar_orderby, $this->ar_limit); + + $this->_reset_write(); + return $this->query($sql); + } + + // -------------------------------------------------------------------- + + /** + * Validate Update + * + * This method is used by both update() and get_compiled_update() to + * validate that data is actually being set and that a table has been + * chosen to be update. + * + * @access public + * @param string the table to update data on + * @return string + */ + protected function _validate_update($table = '') + { if (count($this->ar_set) == 0) { if ($this->db_debug) @@ -1284,27 +1452,13 @@ class CI_DB_active_record extends CI_DB_driver { } return FALSE; } - - $table = $this->ar_from[0]; - } - - if ($where != NULL) - { - $this->where($where); } - - if ($limit != NULL) + else { - $this->limit($limit); + $this->ar_from[0] = $table; } - - $sql = $this->_update($this->_protect_identifiers($table, TRUE, NULL, FALSE), $this->ar_set, $this->ar_where, $this->ar_orderby, $this->ar_limit); - - $this->_reset_write(); - return $this->query($sql); } - - + // -------------------------------------------------------------------- /** @@ -1503,7 +1657,27 @@ class CI_DB_active_record extends CI_DB_driver { return $this->query($sql); } + + // -------------------------------------------------------------------- + /** + * Get DELETE query string + * + * Compiles a delete query string and returns the sql + * + * @access public + * @param string the table to delete from + * @param boolean TRUE: reset AR values; FALSE: leave AR values alone + * @return string + */ + public function get_compiled_delete($table = '', $reset = TRUE) + { + $this->return_delete_sql = TRUE; + $sql = $this->delete($table, '', NULL, $reset); + $this->return_delete_sql = FALSE; + return $sql; + } + // -------------------------------------------------------------------- /** @@ -1576,10 +1750,15 @@ class CI_DB_active_record extends CI_DB_driver { { $this->_reset_write(); } + + if ($this->return_delete_sql === true) + { + return $sql; + } return $this->query($sql); } - + // -------------------------------------------------------------------- /** @@ -1659,7 +1838,7 @@ class CI_DB_active_record extends CI_DB_driver { } } } - + // -------------------------------------------------------------------- /** @@ -1965,6 +2144,22 @@ class CI_DB_active_record extends CI_DB_driver { $this->ar_no_escape = $this->ar_cache_no_escape; } + + // -------------------------------------------------------------------- + + /** + * Reset Active Record values. + * + * Publicly-visible method to reset the AR values. + * + * @access public + * @return void + */ + public function reset_query() + { + $this->_reset_select(); + $this->_reset_write(); + } // -------------------------------------------------------------------- diff --git a/system/database/DB_cache.php b/system/database/DB_cache.php index 3bf065ca5..ad1c28d72 100644 --- a/system/database/DB_cache.php +++ b/system/database/DB_cache.php @@ -33,7 +33,7 @@ class CI_DB_Cache { * Grabs the CI super object instance so we can access it. * */ - function CI_DB_Cache(&$db) + function __construct(&$db) { // Assign the main CI object to $this->CI // and load the file helper since we use it a lot diff --git a/system/database/DB_driver.php b/system/database/DB_driver.php index 237a4fcea..d7b63b9dc 100644 --- a/system/database/DB_driver.php +++ b/system/database/DB_driver.php @@ -78,7 +78,7 @@ class CI_DB_driver { * * @param array */ - function CI_DB_driver($params) + function __construct($params) { if (is_array($params)) { diff --git a/system/database/DB_forge.php b/system/database/DB_forge.php index 0dd29c238..6bc40411b 100644 --- a/system/database/DB_forge.php +++ b/system/database/DB_forge.php @@ -35,7 +35,7 @@ class CI_DB_forge { * Grabs the CI super object instance so we can access it. * */ - function CI_DB_forge() + function __construct() { // Assign the main database object to $this->db $CI =& get_instance(); diff --git a/system/database/DB_utility.php b/system/database/DB_utility.php index a5f174f0a..52196b7ce 100644 --- a/system/database/DB_utility.php +++ b/system/database/DB_utility.php @@ -33,7 +33,7 @@ class CI_DB_utility extends CI_DB_forge { * Grabs the CI super object instance so we can access it. * */ - function CI_DB_utility() + function __construct() { // Assign the main database object to $this->db $CI =& get_instance(); diff --git a/system/database/drivers/odbc/odbc_driver.php b/system/database/drivers/odbc/odbc_driver.php index 08cd27b6c..bcd7937d9 100644 --- a/system/database/drivers/odbc/odbc_driver.php +++ b/system/database/drivers/odbc/odbc_driver.php @@ -48,9 +48,9 @@ class CI_DB_odbc_driver extends CI_DB { var $_random_keyword; - function CI_DB_odbc_driver($params) + function __construct($params) { - parent::CI_DB_driver($params); + parent::__construct($params); $this->_random_keyword = ' RND('.time().')'; // database specific random keyword } diff --git a/system/helpers/captcha_helper.php b/system/helpers/captcha_helper.php index 19ec0c778..2bbb9d3a5 100644 --- a/system/helpers/captcha_helper.php +++ b/system/helpers/captcha_helper.php @@ -243,4 +243,4 @@ if ( ! function_exists('create_captcha')) // ------------------------------------------------------------------------ /* End of file captcha_helper.php */ -/* Location: ./system/heleprs/captcha_helper.php */
\ No newline at end of file +/* Location: ./system/helpers/captcha_helper.php */
\ No newline at end of file diff --git a/system/libraries/Cache/drivers/Cache_apc.php b/system/libraries/Cache/drivers/Cache_apc.php index de75719c4..79d91b320 100644 --- a/system/libraries/Cache/drivers/Cache_apc.php +++ b/system/libraries/Cache/drivers/Cache_apc.php @@ -132,7 +132,7 @@ class CI_Cache_apc extends CI_Driver { */ public function is_supported() { - if ( ! extension_loaded('apc') OR ! function_exists('apc_store')) + if ( ! extension_loaded('apc') OR ini_get('apc.enabled') != "1") { log_message('error', 'The APC PHP extension must be loaded to use APC Cache.'); return FALSE; @@ -148,4 +148,4 @@ class CI_Cache_apc extends CI_Driver { // End Class /* End of file Cache_apc.php */ -/* Location: ./system/libraries/Cache/drivers/Cache_apc.php */
\ No newline at end of file +/* Location: ./system/libraries/Cache/drivers/Cache_apc.php */ diff --git a/system/libraries/Email.php b/system/libraries/Email.php index ef20e1978..c7d0bc52b 100644 --- a/system/libraries/Email.php +++ b/system/libraries/Email.php @@ -381,7 +381,15 @@ class CI_Email { */ public function message($body) { - $this->_body = stripslashes(rtrim(str_replace("\r", "", $body))); + $this->_body = rtrim(str_replace("\r", "", $body)); + + //strip slashes only if magic quotes is ON + //if we do it with magic quotes OFF, it strips real, user-inputted chars. + if (get_magic_quotes_gpc()) + { + $this->_body = stripslashes($this->_body); + } + return $this; } diff --git a/system/libraries/Session.php b/system/libraries/Session.php index 8ee08c5b2..867314bf9 100644 --- a/system/libraries/Session.php +++ b/system/libraries/Session.php @@ -688,13 +688,7 @@ class CI_Session { { if (is_array($data)) { - foreach ($data as $key => $val) - { - if (is_string($val)) - { - $data[$key] = str_replace('\\', '{{slash}}', $val); - } - } + array_walk_recursive($data, array(&$this, '_escape_slashes')); } else { @@ -703,9 +697,23 @@ class CI_Session { $data = str_replace('\\', '{{slash}}', $data); } } - return serialize($data); } + + /** + * Escape slashes + * + * This function converts any slashes found into a temporary marker + * + * @access private + */ + function _escape_slashes(&$val, $key) + { + if (is_string($val)) + { + $val = str_replace('\\', '{{slash}}', $val); + } + } // -------------------------------------------------------------------- @@ -725,19 +733,27 @@ class CI_Session { if (is_array($data)) { - foreach ($data as $key => $val) - { - if (is_string($val)) - { - $data[$key] = str_replace('{{slash}}', '\\', $val); - } - } - + array_walk_recursive($data, array(&$this, '_unescape_slashes')); return $data; } return (is_string($data)) ? str_replace('{{slash}}', '\\', $data) : $data; } + + /** + * Unescape slashes + * + * This function converts any slash markers back into actual slashes + * + * @access private + */ + function _unescape_slashes(&$val, $key) + { + if (is_string($val)) + { + $val= str_replace('{{slash}}', '\\', $val); + } + } // -------------------------------------------------------------------- diff --git a/user_guide_src/source/_themes/eldocs/layout.html b/user_guide_src/source/_themes/eldocs/layout.html index da59e5302..a79720ef1 100644 --- a/user_guide_src/source/_themes/eldocs/layout.html +++ b/user_guide_src/source/_themes/eldocs/layout.html @@ -124,7 +124,15 @@ {%- block footer %} <div id="footer"> - <p class="top"><a href="#header" title="Return to top">Return to top</a></p> + <p class="top"> + {% if prev %} + <span class="prev">Previous Topic: <a href="{{ prev.link }}">{{ prev.title }}</a></span> + {% endif %} + {% if next %} + <span class="next">Next Topic: <a href="{{ next.link }}">{{ next.title }}</a></span> + {% endif %} + <a href="#header" title="Return to top">Return to top</a> + </p> <p><a href="{{ project_url }}">{{ project }}</a> – Copyright © {{ copyright }}</a> – Last updated: {{ last_updated }}</p> </div><!-- /#footer --> {%- endblock %} diff --git a/user_guide_src/source/_themes/eldocs/static/asset/css/common.css b/user_guide_src/source/_themes/eldocs/static/asset/css/common.css index c216c3666..28182a162 100644 --- a/user_guide_src/source/_themes/eldocs/static/asset/css/common.css +++ b/user_guide_src/source/_themes/eldocs/static/asset/css/common.css @@ -119,6 +119,8 @@ img{ display: block; max-width: 100%; } fieldset{ border: 0; } .top{ float: right; } +.next{ padding: 0 20px 0 10px; } +.prev{ padding-right: 10px; } .highlight-ci, .highlight-ee, diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst index 925785d13..8249b63ad 100644 --- a/user_guide_src/source/changelog.rst +++ b/user_guide_src/source/changelog.rst @@ -9,6 +9,7 @@ Release Date: Not Released - General Changes + - Added an optional backtrace to php-error template. - Added Android to the list of user agents. - Added Windows 7 to the list of user platforms. - Callback validation rules can now accept parameters like any other @@ -30,22 +31,25 @@ Release Date: Not Released - Altered form helper - made action on form_open_multipart helper function call optional. Fixes (#65) - url_title() will now trim extra dashes from beginning and end. - - Improved speed of <a href="helpers/string_helper.html">String Helper</a>'s <b>random_string()</b> method - - Added XHTML Basic 1.1 doctype to <a href="helpers/html_helper.html">HTML Helper</a>. + - Improved speed of :doc:`String Helper <helpers/string_helper>`'s random_string() method + - Added XHTML Basic 1.1 doctype to :doc:`HTML Helper <helpers/html_helper>`. - Database - - Added a `CUBRID <http://www.cubrid.org/>`_ driver to the `Database + - Added a `CUBRID <http://www.cubrid.org/>`_ driver to the :doc:`Database Driver <database/index>`. Thanks to the CUBRID team for supplying this patch. - - Added a PDO driver to the <a href="database/index.html">Database Driver</a>. + - Added a PDO driver to the :doc:`Database Driver <database/index>`. - Typecast limit and offset in the :doc:`Database Driver <database/queries>` to integers to avoid possible injection. - Added additional option 'none' for the optional third argument for $this->db->like() in the :doc:`Database Driver <database/active_record>`. - - Added <kbd>$this->db->insert_batch()</kbd> support to the OCI8 (Oracle) driver. + - Added $this->db->insert_batch() support to the OCI8 (Oracle) driver. + - Added new :doc:`Active Record <database/active_record>` methods that return + the SQL string of queries without executing them: get_compiled_select(), + get_compiled_insert(), get_compiled_update(), get_compiled_delete(). - Libraries @@ -55,13 +59,15 @@ Release Date: Not Released - Added support to set an optional parameter in your callback rules of validation using the :doc:`Form Validation Library <libraries/form_validation>`. + - Added a :doc:`Migration Library <libraries/migration>` to assist with applying + incremental updates to your database schema. - Driver children can be located in any package path. - Added max_filename_increment config setting for Upload library. - CI_Loader::_ci_autoloader() is now a protected method. - Added is_unique to the :doc:`Form Validation library <libraries/form_validation>`. - Modified valid_ip() to use PHP's filter_var() when possible (>= PHP 5.2) in the <a href="libraries/form_validation.html">Form Validation</a> library. - - Added <kbd>$config['use_page_numbers']</kbd> to the <a href="libraries/pagination.html">Pagination library</a>, which enables real page numbers in the URI. + - Added $config['use_page_numbers'] to the :doc:`Pagination library <libraries/pagination>`, which enables real page numbers in the URI. - Added TLS and SSL Encryption for SMTP. - Core @@ -108,6 +114,7 @@ Bug fixes for 2.1.0 - Fixed a bug (#484) - First time _csrf_set_hash() is called, hash is never set to the cookie (in Security.php). - Fixed a bug (#60) - Added _file_mime_type() method to the `File Uploading Library <libraries/file_uploading>` in order to fix a possible MIME-type injection. - Fixed a bug (#537) - Support for all wav type in browser. +- Fixed a bug (#576) - Using ini_get() function to detect if apc is enabled or not. Version 2.0.3 ============= @@ -145,16 +152,8 @@ Release Date: August 20, 2011 Thanks to epallerols for the patch. - Added "application/x-csv" to mimes.php. - Added CSRF protection URI whitelisting. - - Fixed a bug where `Email library <libraries/email>` + - Fixed a bug where :doc:`Email library <libraries/email>` attachments with a "." in the name would using invalid MIME-types. - - Added support for - pem,p10,p12,p7a,p7c,p7m,p7r,p7s,crt,crl,der,kdb,rsa,cer,sst,csr - Certs to mimes.php. - - Added support pgp,gpg to mimes.php. - - Added support 3gp, 3g2, mp4, wmv, f4v, vlc Video files to - mimes.php. - - Added support m4a, aac, m4u, xspf, au, ac3, flac, ogg Audio files - to mimes.php. - Helpers @@ -319,6 +318,8 @@ Bug fixes for 2.0.1 - Fixed a bug (Reactor #69) where the SHA1 library was named incorrectly. +.. _2.0.0-changelog: + Version 2.0.0 ============= diff --git a/user_guide_src/source/database/active_record.rst b/user_guide_src/source/database/active_record.rst index e1fc00bc5..5555a30bc 100644 --- a/user_guide_src/source/database/active_record.rst +++ b/user_guide_src/source/database/active_record.rst @@ -54,6 +54,37 @@ $query, which can be used to show the results:: Please visit the :doc:`result functions <results>` page for a full discussion regarding result generation. +$this->db->get_compiled_select() +================================ + +Compiles the selection query just like `$this->db->get()`_ but does not *run* +the query. This method simply returns the SQL query as a string. + +Example:: + + $sql = $this->db->get_compiled_select('mytable'); + echo $sql; + + // Produces string: SELECT * FROM mytable + +The second parameter enables you to set whether or not the active record query +will be reset (by default it will be—just like `$this->db->get()`):: + + echo $this->db->limit(10,20)->get_compiled_select('mytable', FALSE); + // Produces string: SELECT * FROM mytable LIMIT 20, 10 + // (in MySQL. Other databases have slightly different syntax) + + echo $this->db->select('title, content, date')->get_compiled_select(); + + // Produces string: SELECT title, content, date FROM mytable + +The key thing to notice in the above example is that the second query did not +utilize `$this->db->from()`_ and did not pass a table name into the first +parameter. The reason for this outcome is because the query has not been +executed using `$this->db->get()`_ which resets values or reset directly +using `$this-db->reset_query()`_. + + $this->db->get_where() ====================== @@ -540,6 +571,41 @@ object. .. note:: All values are escaped automatically producing safer queries. +$this->db->get_compiled_insert() +================================ +Compiles the insertion query just like `$this->db->insert()`_ but does not +*run* the query. This method simply returns the SQL query as a string. + +Example:: + + $data = array( + 'title' => 'My title', + 'name' => 'My Name', + 'date' => 'My date' + ); + + $sql = $this->db->set($data)->get_compiled_insert('mytable'); + echo $sql; + + // Produces string: INSERT INTO mytable (title, name, date) VALUES ('My title', 'My name', 'My date') + +The second parameter enables you to set whether or not the active record query +will be reset (by default it will be--just like `$this->db->insert()`_):: + + echo $this->db->set('title', 'My Title')->get_compiled_insert('mytable', FALSE); + + // Produces string: INSERT INTO mytable (title) VALUES ('My Title') + + echo $this->db->set('content', 'My Content')->get_compiled_insert(); + + // Produces string: INSERT INTO mytable (title, content) VALUES ('My Title', 'My Content') + +The key thing to notice in the above example is that the second query did not +utlize `$this->db->from()`_ nor did it pass a table name into the first +parameter. The reason this worked is because the query has not been executed +using `$this->db->insert()`_ which resets values or reset directly using +`$this->db->reset_query()`_. + $this->db->insert_batch() ========================= @@ -717,6 +783,14 @@ array of values, the third parameter is the where key. .. note:: All values are escaped automatically producing safer queries. +$this->db->get_compiled_update() +================================ + +This works exactly the same way as ``$this->db->get_compiled_insert()`` except +that it produces an UPDATE SQL string instead of an INSERT SQL string. + +For more information view documentation for `$this->get_compiled_insert()`_. + ************* Deleting Data @@ -784,6 +858,13 @@ Generates a truncate SQL string and runs the query. .. note:: If the TRUNCATE command isn't available, truncate() will execute as "DELETE FROM table". + +$this->db->get_compiled_delete() +================================ +This works exactly the same way as ``$this->db->get_compiled_insert()`` except +that it produces a DELETE SQL string instead of an INSERT SQL string. + +For more information view documentation for `$this->get_compiled_insert()`_. *************** Method Chaining @@ -854,3 +935,31 @@ Here's a usage example:: where, like, group_by, having, order_by, set + +******************* +Reset Active Record +******************* + +Resetting Active Record allows you to start fresh with your query without +executing it first using a method like $this->db->get() or $this->db->insert(). +Just like the methods that execute a query, this will *not* reset items you've +cached using `Active Record Caching`_. + +This is useful in situations where you are using Active Record to generate SQL +(ex. ``$this->db->get_compiled_select()``) but then choose to, for instance, +run the query:: + + // Note that the second parameter of the get_compiled_select method is FALSE + $sql = $this->db->select(array('field1','field2')) + ->where('field3',5) + ->get_compiled_select('mytable', FALSE); + + // ... + // Do something crazy with the SQL code... like add it to a cron script for + // later execution or something... + // ... + + $data = $this->db->get()->result_array(); + + // Would execute and return an array of results of the following query: + // SELECT field1, field1 from mytable where field3 = 5; diff --git a/user_guide_src/source/database/index.rst b/user_guide_src/source/database/index.rst index 3b59986be..ab12b7cb7 100644 --- a/user_guide_src/source/database/index.rst +++ b/user_guide_src/source/database/index.rst @@ -6,24 +6,20 @@ CodeIgniter comes with a full-featured and very fast abstracted database class that supports both traditional structures and Active Record patterns. The database functions offer clear, simple syntax. -- :doc:`Quick Start: Usage Examples <examples>` -- :doc:`Database Configuration <configuration>` -- :doc:`Connecting to a Database <connecting>` -- :doc:`Running Queries <queries>` -- :doc:`Generating Query Results <results>` -- :doc:`Query Helper Functions <helpers>` -- :doc:`Active Record Class <active_record>` -- :doc:`Transactions <transactions>` -- :doc:`Table MetaData <table_data>` -- :doc:`Field MetaData <fields>` -- :doc:`Custom Function Calls <call_function>` -- :doc:`Query Caching <caching>` -- :doc:`Database manipulation with Database Forge <forge>` -- :doc:`Database Utilities Class <utilities>` - .. toctree:: - :glob: :titlesonly: - :hidden: - *
\ No newline at end of file + Quick Start: Usage Examples <examples> + Database Configuration <configuration> + Connecting to a Database <connecting> + Running Queries <queries> + Generating Query Results <results> + Query Helper Functions <helpers> + Active Record Class <active_record> + Transactions <transactions> + Table MetaData <table_data> + Field MetaData <fields> + Custom Function Calls <call_function> + Query Caching <caching> + Database Manipulation with Database Forge <forge> + Database Utilities Class <utilities>
\ No newline at end of file diff --git a/user_guide_src/source/general/index.rst b/user_guide_src/source/general/index.rst index ae0d0961c..2162b8140 100644 --- a/user_guide_src/source/general/index.rst +++ b/user_guide_src/source/general/index.rst @@ -1,39 +1,32 @@ -################## -General -################## - - -- :doc:`CodeIgniter URLs <urls>` -- :doc:`Controllers <controllers>` -- :doc:`Reserved Names <reserved_names>` -- :doc:`Views <views>` -- :doc:`Models <models>` -- :doc:`Helpers <helpers>` -- :doc:`Using CodeIgniter Libraries <libraries>` -- :doc:`Creating Your Own Libraries <creating_libraries>` -- :doc:`Using CodeIgniter Drivers <drivers>` -- :doc:`Creating Your Own Drivers <creating_drivers>` -- :doc:`Creating Core Classes <core_classes>` -- :doc:`Creating Ancillary Classes <ancillary_classes>` -- :doc:`Hooks - Extending the Core <hooks>` -- :doc:`Auto-loading Resources <autoloader>` -- :doc:`Common Function <common_functions>` -- :doc:`URI Routing <routing>` -- :doc:`Error Handling <errors>` -- :doc:`Caching <caching>` -- :doc:`Profiling Your Application <profiling>` -- :doc:`Running via the CLI <cli>` -- :doc:`Managing Applications <managing_apps>` -- :doc:`Handling Multiple Environments <environments>` -- :doc:`Alternative PHP Syntax <alternative_php>` -- :doc:`Security <security>` -- :doc:`PHP Style Guide <styleguide>` -- :doc:`Server Requirements <requirements>` -- :doc:`Credits <credits>` +############## +General Topics +############## .. toctree:: - :glob: :titlesonly: - :hidden: - *
\ No newline at end of file + urls + controllers + reserved_names + views + models + Helpers <helpers> + libraries + creating_libraries + drivers + creating_drivers + core_classes + ancillary_classes + hooks + autoloader + common_functions + routing + errors + Caching <caching> + profiling + cli + managing_apps + environments + alternative_php + security + PHP Style Guide <styleguide> diff --git a/user_guide_src/source/general/styleguide.rst b/user_guide_src/source/general/styleguide.rst index 0373fc791..b3dc08871 100644 --- a/user_guide_src/source/general/styleguide.rst +++ b/user_guide_src/source/general/styleguide.rst @@ -1,6 +1,7 @@ -######################## -General Style and Syntax -######################## +############### +PHP Style Guide +############### + The following page describes the use of coding rules adhered to when developing CodeIgniter. diff --git a/user_guide_src/source/helpers/date_helper.rst b/user_guide_src/source/helpers/date_helper.rst index 378ff362b..ad06dd628 100644 --- a/user_guide_src/source/helpers/date_helper.rst +++ b/user_guide_src/source/helpers/date_helper.rst @@ -162,7 +162,8 @@ Example :: - $mysql = '20061124092345'; $unix = mysql_to_unix($mysql); + $mysql = '20061124092345'; + $unix = mysql_to_unix($mysql); unix_to_human() =============== diff --git a/user_guide_src/source/helpers/directory_helper.rst b/user_guide_src/source/helpers/directory_helper.rst index 6c259adb1..fd169886c 100644 --- a/user_guide_src/source/helpers/directory_helper.rst +++ b/user_guide_src/source/helpers/directory_helper.rst @@ -18,15 +18,20 @@ This helper is loaded using the following code The following functions are available: -directory_map('source directory') -================================= +directory_map() +=============== This function reads the directory path specified in the first parameter and builds an array representation of it and all its contained files. + +.. php:method:: directory_map($source_dir[, $directory_depth = 0[, $hidden = FALSE]]) -Example - -:: + :param string $source_dir: path to the ource directory + :param integer $directory_depth: depth of directories to traverse (0 = + fully recursive, 1 = current dir, etc) + :param boolean $hidden: whether to include hidden directories + +Examples:: $map = directory_map('./mydirectory/'); @@ -35,23 +40,17 @@ Example Sub-folders contained within the directory will be mapped as well. If you wish to control the recursion depth, you can do so using the second -parameter (integer). A depth of 1 will only map the top level directory - -:: +parameter (integer). A depth of 1 will only map the top level directory:: $map = directory_map('./mydirectory/', 1); By default, hidden files will not be included in the returned array. To -override this behavior, you may set a third parameter to true (boolean) - -:: +override this behavior, you may set a third parameter to true (boolean):: $map = directory_map('./mydirectory/', FALSE, TRUE); Each folder name will be an array index, while its contained files will -be numerically indexed. Here is an example of a typical array - -:: +be numerically indexed. Here is an example of a typical array:: Array ( [libraries] => Array diff --git a/user_guide_src/source/index.rst b/user_guide_src/source/index.rst index e53182550..6cdeb2442 100644 --- a/user_guide_src/source/index.rst +++ b/user_guide_src/source/index.rst @@ -37,9 +37,13 @@ CodeIgniter is right for you if: * overview/index + general/requirements installation/index general/index libraries/index - database/index helpers/index - documentation/index
\ No newline at end of file + database/index + documentation/index + tutorial/index + general/quick_reference + general/credits
\ No newline at end of file diff --git a/user_guide_src/source/installation/upgrade_200.rst b/user_guide_src/source/installation/upgrade_200.rst index 064e1b534..0bcbd5c99 100644 --- a/user_guide_src/source/installation/upgrade_200.rst +++ b/user_guide_src/source/installation/upgrade_200.rst @@ -5,6 +5,10 @@ Upgrading from 1.7.2 to 2.0.0 Before performing an update you should take your site offline by replacing the index.php file with a static one. +******************* +Update Instructions +******************* + Step 1: Update your CodeIgniter files ===================================== @@ -88,3 +92,51 @@ Step 8: Update your user guide Please replace your local copy of the user guide with the new version, including the image files. + + +************ +Update Notes +************ + +Please refer to the :ref:`2.0.0 Change Log <2.0.0-changelog>` for full +details, but here are some of the larger changes that are more likely to +impact your code: + +- CodeIgniter now requires PHP 5.1.6. +- Scaffolding has been removed. +- The CAPTCHA plugin in now a :doc:`helper </helpers/captcha_helper>`. +- The JavaScript calendar plugin was removed. +- The *system/cache* and *system/logs* directories are now in the application + directory. +- The Validation class has been removed. Please see the + :doc:`Form Validation library </libraries/form_validation>` +- "default" is now a reserved name. +- The xss_clean() function has moved to the :doc:`Security Class + </libraries/security>`. +- do_xss_clean() now returns FALSE if the uploaded file fails XSS checks. +- The :doc:`Session Class </libraries/sessions>` requires now the use of an + encryption key set in the config file. +- The following deprecated Active Record functions have been removed: + ``orwhere``, ``orlike``, ``groupby``, ``orhaving``, ``orderby``, + ``getwhere``. +- ``_drop_database()`` and ``_create_database()`` functions have been removed + from the db utility drivers. +- The ``dohash()`` function of the :doc:`Security helper + </helpers/security_helper>` + has been renamed to ``do_hash()`` for naming consistency. + +The config folder +================= + +The following files have been changed: + +- config.php +- database.php +- mimes.php +- routes.php +- user_agents.php + +The following files have been added: + +- foreign_chars.php +- profiler.php diff --git a/user_guide_src/source/overview/index.rst b/user_guide_src/source/overview/index.rst index d541e796c..dc91f78c4 100644 --- a/user_guide_src/source/overview/index.rst +++ b/user_guide_src/source/overview/index.rst @@ -4,15 +4,13 @@ CodeIgniter Overview The following pages describe the broad concepts behind CodeIgniter: -- :doc:`CodeIgniter at a Glance <at_a_glance>` -- :doc:`Supported Features <features>` -- :doc:`Application Flow Chart <appflow>` -- :doc:`Introduction to the Model-View-Controller <mvc>` -- :doc:`Design and Architectural Goals <goals>` - .. toctree:: - :glob: - :hidden: :titlesonly: - *
\ No newline at end of file + Getting Started <getting_started> + CodeIgniter at a Glance <at_a_glance> + CodeIgniter Cheatsheets <cheatsheets> + Supported Features <features> + Application Flow Chart <appflow> + Model-View-Controller <mvc> + Architectural Goals <goals>
\ No newline at end of file diff --git a/user_guide_src/source/tutorial/conclusion.rst b/user_guide_src/source/tutorial/conclusion.rst new file mode 100644 index 000000000..48fbdcc8a --- /dev/null +++ b/user_guide_src/source/tutorial/conclusion.rst @@ -0,0 +1,26 @@ +########## +Conclusion +########## + +This tutorial did not cover all of the things you might expect of a +full-fledged content management system, but it introduced you to the +more important topics of routing, writing controllers, and models. We +hope this tutorial gave you an insight into some of CodeIgniter's basic +design patterns, which you can expand upon. + +Now that you've completed this tutorial, we recommend you check out the +rest of the documentation. CodeIgniter is often praised because of its +comprehensive documentation. Use this to your advantage and read the +"Introduction" and "General Topics" sections thoroughly. You should read +the class and helper references when needed. + +Every intermediate PHP programmer should be able to get the hang of +CodeIgniter within a few days. + +If you still have questions about the framework or your own CodeIgniter +code, you can: + +- Check out our `forums <http://codeigniter.com/forums>`_ +- Visit our `IRC chatroom <http://codeigniter.com/wiki/IRC>`_ +- Explore the `Wiki <http://codeigniter.com/wiki/>`_ + diff --git a/user_guide_src/source/tutorial/create_news_items.rst b/user_guide_src/source/tutorial/create_news_items.rst new file mode 100644 index 000000000..003b94bd8 --- /dev/null +++ b/user_guide_src/source/tutorial/create_news_items.rst @@ -0,0 +1,153 @@ +################# +Create news items +################# + +You now know how you can read data from a database using CodeIgnite, but +you haven't written any information to the database yet. In this section +you'll expand your news controller and model created earlier to include +this functionality. + +Create a form +------------- + +To input data into the database you need to create a form where you can +input the information to be stored. This means you'll be needing a form +with two fields, one for the title and one for the text. You'll derive +the slug from our title in the model. Create the new view at +application/views/news/create.php. + +:: + + <h2>Create a news item</h2> + + <?php echo validation_errors(); ?> + + <?php echo form_open('news/create') ?> + + <label for="title">Title</label> + <input type="input" name="title" /><br /> + + <label for="text">Text</label> + <textarea name="text"></textarea><br /> + + <input type="submit" name="submit" value="Create news item" /> + + </form> + +There are only two things here that probably look unfamiliar to you: the +form_open() function and the validation_errors() function. + +The first function is provided by the `form +helper <../helpers/form_helper.html>`_ and renders the form element and +adds extra functionality, like adding a hidden `CSFR prevention +field <../libraries/security.html>`_. The latter is used to report +errors related to form validation. + +Go back to your news controller. You're going to do two things here, +check whether the form was submitted and whether the submitted data +passed the validation rules. You'll use the `form +validation <../libraries/form_validation.html>`_ library to do this. + +:: + + public function create() + { + $this->load->helper('form'); + $this->load->library('form_validation'); + + $data['title'] = 'Create a news item'; + + $this->form_validation->set_rules('title', 'Title', 'required'); + $this->form_validation->set_rules('text', 'text', 'required'); + + if ($this->form_validation->run() === FALSE) + { + $this->load->view('templates/header', $data); + $this->load->view('news/create'); + $this->load->view('templates/footer'); + + } + else + { + $this->news_model->set_news(); + $this->load->view('news/success'); + } + } + +The code above adds a lot of functionality. The first few lines load the +form helper and the form validation library. After that, rules for the +form validation are set. The set\_rules() method takes three arguments; +the name of the input field, the name to be used in error messages, and +the rule. In this case the title and text fields are required. + +CodeIgniter has a powerful form validation library as demonstrated +above. You can read `more about this library +here <../libraries/form_validation.html>`_. + +Continuing down, you can see a condition that checks whether the form +validation ran successfully. If it did not, the form is displayed, if it +was submitted **and** passed all the rules, the model is called. After +this, a view is loaded to display a success message. Create a view at +application/view/news/success.php and write a success message. + +Model +----- + +The only thing that remains is writing a method that writes the data to +the database. You'll use the Active Record class to insert the +information and use the input library to get the posted data. Open up +the model created earlier and add the following: + +:: + + public function set_news() + { + $this->load->helper('url'); + + $slug = url_title($this->input->post('title'), 'dash', TRUE); + + $data = array( + 'title' => $this->input->post('title'), + 'slug' => $slug, + 'text' => $this->input->post('text') + ); + + return $this->db->insert('news', $data); + } + +This new method takes care of inserting the news item into the database. +The third line contains a new function, url\_title(). This function - +provided by the `URL helper <../helpers/url_helper.html>`_ - strips down +the string you pass it, replacing all spaces by dashes (-) and makes +sure everything is in lowercase characters. This leaves you with a nice +slug, perfect for creating URIs. + +Let's continue with preparing the record that is going to be inserted +later, inside the $data array. Each element corresponds with a column in +the database table created earlier. You might notice a new method here, +namely the post() method from the `input +library <../libraries/input.html>`_. This method makes sure the data is +sanitized, protecting you from nasty attacks from others. The input +library is loaded by default. At last, you insert our $data array into +our database. + +Routing +------- + +Before you can start adding news items into your CodeIgniter application +you have to add an extra rule to config/routes.php file. Make sure your +file contains the following. This makes sure CodeIgniter sees 'create' +as a method instead of a news item's slug. + +:: + + $route['news/create'] = 'news/create'; + $route['news/(:any)'] = 'news/view/$1'; + $route['news'] = 'news'; + $route['(:any)'] = 'pages/view/$1'; + $route['default_controller'] = 'pages/view'; + +Now point your browser to your local development environment where you +installed CodeIgniter and add index.php/news/create to the URL. +Congratulations, you just created your first CodeIgniter application! +Add some news and check out the different pages you made. diff --git a/user_guide_src/source/tutorial/index.rst b/user_guide_src/source/tutorial/index.rst new file mode 100644 index 000000000..c959d04d2 --- /dev/null +++ b/user_guide_src/source/tutorial/index.rst @@ -0,0 +1,46 @@ +######## +Tutorial +######## + +This tutorial is intended to introduce you to the CodeIgniter framework +and the basic principles of MVC architecture. It will show you how a +basic CodeIgniter application is constructed in step-by-step fashion. + +In this tutorial, you will be creating a **basic news application**. You +will begin by writing the code that can load static pages. Next, you +will create a news section that reads news items from a database. +Finally, you'll add a form to create news items in the database. + +This tutorial will primarily focus on: + +- Model-View-Controller basics +- Routing basics +- Form validation +- Performing basic database queries using "Active Record" + +The entire tutorial is split up over several pages, each explaining a +small part of the functionality of the CodeIgniter framework. You'll go +through the following pages: + +- Introduction, this page, which gives you an overview of what to + expect. +- `Static pages <static_pages.html>`_, which will teach you the basics + of controllers, views and routing. +- `News section <news_section.html>`_, where you'll start using models + and will be doing some basic database operations. +- `Create news items <create_news_items.html>`_, which will introduce + more advanced database operations and form validation. +- `Conclusion <conclusion.html>`_, which will give you some pointers on + further reading and other resources. + +Enjoy your exploration of the CodeIgniter framework. + +.. toctree:: + :glob: + :hidden: + :titlesonly: + + static_pages + news_section + create_news_items + conclusion
\ No newline at end of file diff --git a/user_guide_src/source/tutorial/news_section.rst b/user_guide_src/source/tutorial/news_section.rst new file mode 100644 index 000000000..fe8e41607 --- /dev/null +++ b/user_guide_src/source/tutorial/news_section.rst @@ -0,0 +1,214 @@ +############ +News section +############ + +In the last section, we went over some basic concepts of the framework +by writing a class that includes static pages. We cleaned up the URI by +adding custom routing rules. Now it's time to introduce dynamic content +and start using a database. + +Setting up your model +--------------------- + +Instead of writing database operations right in the controller, queries +should be placed in a model, so they can easily be reused later. Models +are the place where you retrieve, insert, and update information in your +database or other data stores. They represent your data. + +Open up the application/models directory and create a new file called +news_model.php and add the following code. Make sure you've configured +your database properly as described +`here <../database/configuration.html>`_. + +:: + + <?php + class News_model extends CI_Model { + + public function __construct() + { + $this->load->database(); + } + } + +This code looks similar to the controller code that was used earlier. It +creates a new model by extending CI\_Model and loads the database +library. This will make the database class available through the +$this->db object. + +Before querying the database, a database schema has to be created. +Connect to your database and run the SQL command below. Also add some +seed records. + +:: + + CREATE TABLE news ( + id int(11) NOT NULL AUTO_INCREMENT, + title varchar(128) NOT NULL, + slug varchar(128) NOT NULL, + text text NOT NULL, + PRIMARY KEY (id), + KEY slug (slug) + ); + +Now that the database and a model have been set up, you'll need a method +to get all of our posts from our database. To do this, the database +abstraction layer that is included with CodeIgniter — `Active +Record <../database/active_record.html>`_ — is used. This makes it +possible to write your 'queries' once and make them work on `all +supported database systems <../general/requirements.html>`_. Add the +following code to your model. + +:: + + public function get_news($slug = FALSE) + { + if ($slug === FALSE) + { + $query = $this->db->get('news'); + return $query->result_array(); + } + + $query = $this->db->get_where('news', array('slug' => $slug)); + return $query->row_array(); + } + +With this code you can perform two different queries. You can get all +news records, or get a news item by its `slug <#>`_. You might have +noticed that the $slug variable wasn't sanitized before running the +query; Active Record does this for you. + +Display the news +---------------- + +Now that the queries are written, the model should be tied to the views +that are going to display the news items to the user. This could be done +in our pages controller created earlier, but for the sake of clarity, a +new "news" controller is defined. Create the new controller at +application/controllers/news.php. + +:: + + <?php + class News extends CI_Controller { + + public function __construct() + { + parent::__construct(); + $this->load->model('news_model'); + } + + public function index() + { + $data['news'] = $this->news_model->get_news(); + } + + public function view($slug) + { + $data['news'] = $this->news_model->get_news($slug); + } + } + +Looking at the code, you may see some similarity with the files we +created earlier. First, the "\_\_construct" method: it calls the +constructor of its parent class (CI\_Controller) and loads the model, so +it can be used in all other methods in this controller. + +Next, there are two methods to view all news items and one for a +specific news item. You can see that the $slug variable is passed to the +model's method in the second method. The model is using this slug to +identify the news item to be returned. + +Now the data is retrieved by the controller through our model, but +nothing is displayed yet. The next thing to do is passing this data to +the views. + +:: + + public function index() + { + $data['news'] = $this->news_model->get_news(); + $data['title'] = 'News archive'; + + $this->load->view('templates/header', $data); + $this->load->view('news/index', $data); + $this->load->view('templates/footer'); + } + +The code above gets all news records from the model and assigns it to a +variable. The value for the title is also assigned to the $data['title'] +element and all data is passed to the views. You now need to create a +view to render the news items. Create application/views/news/index.php +and add the next piece of code. + +:: + + <?php foreach ($news as $news_item): ?> + + <h2><?php echo $news_item['title'] ?></h2> + <div id="main"> + <?php echo $news_item['text'] ?> + </div> + <p><a href="news/<?php echo $news_item['slug'] ?>">View article</a></p> + + <?php endforeach ?> + +Here, each news item is looped and displayed to the user. You can see we +wrote our template in PHP mixed with HTML. If you prefer to use a +template language, you can use CodeIgniter's `Template +Parser <../libraries/parser.html>`_ class or a third party parser. + +The news overview page is now done, but a page to display individual +news items is still absent. The model created earlier is made in such +way that it can easily be used for this functionality. You only need to +add some code to the controller and create a new view. Go back to the +news controller and add the following lines to the file. + +:: + + public function view($slug) + { + $data['news_item'] = $this->news_model->get_news($slug); + + if (empty($data['news_item'])) + { + show_404(); + } + + $data['title'] = $data['news_item']['title']; + + $this->load->view('templates/header', $data); + $this->load->view('news/view', $data); + $this->load->view('templates/footer'); + } + +Instead of calling the get\_news() method without a parameter, the $slug +variable is passed, so it will return the specific news item. The only +things left to do is create the corresponding view at +application/views/news/view.php. Put the following code in this file. + +:: + + <?php + echo '<h2>'.$news_item['title'].'</h2>'; + echo $news_item['text']; + +Routing +------- + +Because of the wildcard routing rule created earlier, you need need an +extra route to view the controller that you just made. Modify your +routing file (application/config/routes.php) so it looks as follows. +This makes sure the requests reaches the news controller instead of +going directly to the pages controller. The first line routes URI's with +a slug to the view method in the news controller. + +:: + + $route['news/(:any)'] = 'news/view/$1'; + $route['news'] = 'news'; + $route['(:any)'] = 'pages/view/$1'; + $route['default_controller'] = 'pages/view'; + +Point your browser to your document root, followed by index.php/news and +watch your news page. diff --git a/user_guide_src/source/tutorial/static_pages.rst b/user_guide_src/source/tutorial/static_pages.rst new file mode 100644 index 000000000..0bbf51b1b --- /dev/null +++ b/user_guide_src/source/tutorial/static_pages.rst @@ -0,0 +1,170 @@ +############ +Static pages +############ + +**Note:** This tutorial assumes you've downloaded CodeIgniter and +`installed the framework <../installation/index.html>`_ in your +development environment. + +The first thing you're going to do is set up a **controller** to handle +static pages. A controller is simply a class that helps delegate work. +It is the glue of your web application. + +For example, when a call is made to: +``http://example.com/news/latest/10`` We might imagine that there is a +controller named "news". The method being called on news would be +"latest". The news method's job could be to grab 10 news items, and +render them on the page. Very often in MVC, you'll see URL patterns that +match: +``http://example.com/[controller-class]/[controller-method]/[arguments]`` +As URL schemes become more complex, this may change. But for now, this +is all we will need to know. + +Create a file at application/controllers/pages.php with the following +code. + +:: + + <?php + class Pages extends CI_Controller { + + public function view($page == 'home') + { + + } + + } + +You have created a class named "pages", with a view method that accepts +one argument named $page. The pages class is extending the +CI_Controller class. This means that the new pages class can access the +methods and variables defined in the CI_Controller class +(system/core/Controller.php). + +The **controller is what will become the center of every request** to +your web application. In very technical CodeIgniter discussions, it may +be referred to as the *super object*. Like any php class, you refer to +it within your controllers as $this. Referring to $this is how you will +load libraries, views, and generally command the framework. + +Now you've created your first method, it's time to make some basic page +templates. We will be creating two "views" (page templates) that act as +our page footer and header. + +Create the header at application/views/templates/header.php and add the +following code. + +:: + + <html> + <head> + <title>CodeIgniter 2 Tutorial</title> + </head> + <body> + + <h1>CodeIgniter 2 Tutorial<h1> + +The header contains the basic HTML code that you'll want to display +before loading the main view, together with a heading. It will also +output the $title variable, which we'll define later in the controller. +Now create a footer at application/views/templates/footer.php that +includes the following code: + +:: + + <em>© 2011</em> + </body> + <html> + +Adding logic to the controller +------------------------------ + +Earlier you set up a controller with a view() method. The method accepts +one parameter, which is the name of the page to be loaded. The static +page templates will be located in the application/views/pages/ +directory. + +In that directory, create two files named home.php and about.php. Within +those files, type some text − anything you'd like − and save them. If +you like to be particularly un-original, try "Hello World!". + +In order to load those pages, you'll have to check whether the requested +page actually exists: + +:: + + <?php + public function view($page = 'home') + { + + if ( ! file_exists('application/views/pages/'.$page.'.php')) + { + // Whoops, we don't have a page for that! + show_404(); + } + + $data['title'] = ucfirst($page); // Capitalize the first letter + + $this->load->view('templates/header', $data); + $this->load->view('pages/'.$page, $data); + $this->load->view('templates/footer', $data); + + } + +Now, when the page does exist, it is loaded, including the header and +footer, and displayed to the user. If the page doesn't exist, a "404 +Page not found" error is shown. + +The first line in this method checks whether the page actually exists. +PHP's native file\_exists() function is used to check whether the file +is where it's expected to be. show\_404() is a built-in CodeIgniter +function that renders the default error page. + +In the header template, the $title variable was used to customize the +page title. The value of title is defined in this method, but instead of +assigning the value to a variable, it is assigned to the title element +in the $data array. + +The last thing that has to be done is loading the views in the order +they should be displayed. The second parameter in the view() method is +used to pass values to the view. Each value in the $data array is +assigned to a variable with the name of its key. So the value of +$data['title'] in the controller is equivalent to $title in the view. + +Routing +------- + +The controller is now functioning! Point your browser to +[your-site-url]index.php/pages/view to see your page. When you visit +index.php/pages/view/about you'll see the about page, again including +the header and footer. + +Using custom routing rules, you have the power to map any URI to any +controller and method, and break free from the normal convention: +``http://example.com/[controller-class]/[controller-method]/[arguments]`` + +Let's do that. Open the routing file located at +application/config/routes.php and add the following two lines. Remove +all other code that sets any element in the $route array. + +:: + + $route['default_controller'] = 'pages/view'; + $route['(:any)'] = 'pages/view/$1'; + +CodeIgniter reads its routing rules from top to bottom and routes the +request to the first matching rule. Each rule is a regular expression +(left-side) mapped to a controller and method name separated by slashes +(right-side). When a request comes in, CodeIgniter looks for the first +match, and calls the appropriate controller and method, possibly with +arguments. + +More information about routing can be found in the URI Routing +`documentation <../general/routing.html>`_. + +Here, the second rule in the $routes array matches **any** request using +the wildcard string (:any). and passes the parameter to the view() +method of the pages class. + +Now visit index.php/about. Did it get routed correctly to the view() +method in the pages controller? Awesome! |