WordPress – exclude posts from query/loop

June 27th, 2011

If you want to exclude some posts (ID) from your query/loops this is simple solution.

single post with ID #2:

1
query_posts('post__not_in' => array(2));

or more posts (with IDs 5, 7 and 8):

1
query_posts('post__not_in' => array(5, 7, 8));

bug: Modular Extensions – HMVC with CI 2.0

February 12th, 2011

There is a bug in a /MX/Router.php witch produce redirect to 404 page when default_controller not found in /controllers folder.
Variable $config[‘uri_protocol’] is set to “AUTO” or to “REQUEST_URI”, otherwise it working fine.
That has something to do with new URL protocol auto detection.

How to reproduce:
1. clean CI (from bitbucket)
2. HMVC (https://bitbucket.org/wiredesignz/codeigniter-modular-extensions-hmvc)
3. move /controllers/welcome.php to /modules/welcome/controllers/
4. move /views/welcome_message.php to same modules folder /modules/welcome/…

Call: http://your_url.dev (you’ll get 404)
But if you call: http://your_url.dev/index.php/welcome everything will be fine.

my correction…
/third_party/MX/Router.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public function _validate_request($segments) {
 
        /*  correction */
        if (count($segments) == 0)
        {
            return $segments;
        }
        /*  end correction */
 
 
        /* locate module controller */
        if ($located = $this->locate($segments)) return $located;
 
        /* use a default 404_override controller */
        if (isset($this->routes['404_override']) AND $segments = explode('/', $this->routes['404_override'])) {
            if ($located = $this->locate($segments)) return $located;
        }
 
        /* no controller found */
        show_404();
    }

Database driven routes (no caching, MySQL version)

February 1st, 2011

If you need database driven routes then you may consider this simple solution.

You need to create following table.

1
2
3
4
5
6
7
8
9
10
CREATE TABLE `ci_routes` (
   `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
   `src` VARCHAR(255) NOT NULL,
   `dest` VARCHAR(255) NOT NULL,
   PRIMARY KEY (`id`,`src`),
   UNIQUE KEY `src` (`src`)
) ENGINE=InnoDB
 
INSERT INTO `routes` (`id`, `src`, `dest`) VALUES(0, 'default_controller', 'welcome');
INSERT INTO `routes` (`id`, `src`, `dest`) VALUES(1, '404_override', '');

And just put MY_Router.php to your /application/core folder.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
<?php
 
class MY_Router extends CI_Router{
 
	var $routes_table	= 'ci_routes'; // mysql routes table name
	var $config;
	var $routes			= array();
	var $error_routes	= array();
	var $class			= '';
	var $method			= 'index';
	var $directory		= '';
	var $default_controller;
 
	function __construct()
	{
		$this->config =& load_class('Config', 'core');
		$this->uri =& load_class('URI', 'core');
		log_message('debug', "Router Class Initialized");
	}
 
	/*
	   CREATE TABLE `routes` (
	   `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
	   `src` varchar(255) NOT NULL,
	   `dest` varchar(255) NOT NULL,
	   PRIMARY KEY (`id`,`src`),
	   UNIQUE KEY `src` (`src`)
	   ) ENGINE=InnoDB
	*/
 
	function get_db_routes()
	{
		//connect to database
		include(APPPATH.'config/database'.EXT);
		$conn = mysql_connect($db['default']['hostname'],$db['default']['username'],$db['default']['password']);
		mysql_select_db($db['default']['database'],$conn);
 
		// get saved routes
		$sql = "SELECT * FROM `{$this->routes_table}`";
		$query = mysql_query($sql);
		mysql_close($conn);
 
		while ($row = mysql_fetch_assoc($query)) {
			$routes[$row['src']] = $row['dest'];
		}
 
		if(count($routes)>0){
			return $routes;
		}
		return FALSE;
	}
 
	function _set_routing()
	{
		$segments = array();
		if ($this->config->item('enable_query_strings') === TRUE AND isset($_GET[$this->config->item('controller_trigger')]))
		{
			if (isset($_GET[$this->config->item('directory_trigger')]))
			{
				$this->set_directory(trim($this->uri->_filter_uri($_GET[$this->config->item('directory_trigger')])));
				$segments[] = $this->fetch_directory();
			}
 
			if (isset($_GET[$this->config->item('controller_trigger')]))
			{
				$this->set_class(trim($this->uri->_filter_uri($_GET[$this->config->item('controller_trigger')])));
				$segments[] = $this->fetch_class();
			}
 
			if (isset($_GET[$this->config->item('function_trigger')]))
			{
				$this->set_method(trim($this->uri->_filter_uri($_GET[$this->config->item('function_trigger')])));
				$segments[] = $this->fetch_method();
			}
		}
 
		// load routes from DB
		$this->routes_db = $this->get_db_routes();
 
		// Load the routes.php file.
		@include(APPPATH.'config/routes'.EXT);
		$this->routes = ( ! isset($route) OR ! is_array($route)) ? array() : $route;
		unset($route);
 
		// what to load first
		if (@$route_override) { // this is setup in
			$this->routes = array_merge($this->routes_db, $this->routes);
		} else {
			$this->routes = array_merge($this->routes, $this->routes_db);
		}
 
		$this->default_controller = ( ! isset($this->routes['default_controller']) OR $this->routes['default_controller'] == '') ? FALSE : strtolower($this->routes['default_controller']);
 
		if (count($segments) > 0)
		{
			return $this->_validate_request($segments);
		}
 
		$this->uri->_fetch_uri_string();
 
		if ($this->uri->uri_string == '')
		{
			return $this->_set_default_controller();
		}
 
		$this->uri->_remove_url_suffix();
		$this->uri->_explode_segments();
		$this->_parse_routes();
		$this->uri->_reindex_segments();
	}
 
}

If you want to have control what is loaded first you need to put this var to /config/route.php

// file route.php WILL OVERRIDE DB routes setting if TRUE
// (db settings will be loaded first)
$route_override = TRUE;

bugfix: $_GET params cause errors when loading default controller

February 1st, 2011

CodeIgniter 2.0.0 Reactor has been released but width some small bug. :)
If you try to reach somedomain.com/?a=1 or somedomain.com/index.php?a=1 you’ll got

404 Page Not Found

So until EllisLab or CI Reactor community release bug fix here it is my own.

In your config.php you can leave:

$config['uri_protocol']	= 'AUTO';

And just put MY_URI.php to /application/core folder.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
 
 
class MY_URI extends CI_URI{
 
	var	$keyval			= array();
	var $uri_string;
	var $segments		= array();
	var $rsegments		= array();
 
 
	function __construct()
	{
		$this->config =& load_class('Config', 'core');
		log_message('debug', "URI Class Initialized");
	}
 
	function _fetch_uri_string()
	{
		if (strtoupper($this->config->item('uri_protocol')) == 'AUTO')
		{
			// Is the request coming from the command line?
			if (defined('STDIN'))
			{
				$this->uri_string = $this->_parse_cli_args();
				return;
			}
 
			// Let's try the REQUEST_URI first, this will work in most situations
			if ($uri = $this->_detect_uri())
			{
				$this->uri_string = $uri;
				return;
			}
 
			// Is there a PATH_INFO variable?
			// Note: some servers seem to have trouble with getenv() so we'll test it two ways
			$path = (isset($_SERVER['PATH_INFO'])) ? $_SERVER['PATH_INFO'] : @getenv('PATH_INFO');
			if (trim($path, '/') != '' && $path != "/".SELF)
			{
				$this->uri_string = $path;
				return;
			}
 
			// No PATH_INFO?... What about QUERY_STRING?
			$path =  (isset($_SERVER['QUERY_STRING'])) ? $_SERVER['QUERY_STRING'] : @getenv('QUERY_STRING');
			if (trim($path, '/') != '')
			{
				$this->uri_string = $path;
				return;
			}
 
			// As a last ditch effort lets try using the $_GET array
			if (is_array($_GET) && count($_GET) == 1 && trim(key($_GET), '/') != '')
			{
				$this->uri_string = key($_GET);
				return;
			}
 
			// We've exhausted all our options...
			$this->uri_string = '';
		}
		else
		{
			$uri = strtoupper($this->config->item('uri_protocol'));
 
			if ($uri == 'REQUEST_URI')
			{
				$this->uri_string = $this->_detect_uri();
				return;
			}
			elseif ($uri == 'CLI')
			{
				$this->uri_string = $this->_parse_cli_args();
				return;
			}
 
			$this->uri_string = (isset($_SERVER[$uri])) ? $_SERVER[$uri] : @getenv($uri);
		}
 
		// If the URI contains only a slash we'll kill it
		if ($this->uri_string == '/')
		{
			$this->uri_string = '';
		}
	}
 
 
	private function _detect_uri()
	{
 
		if ( ! isset($_SERVER['REQUEST_URI']))
		{
			return '';
		}
 
	 	$uri = $_SERVER['REQUEST_URI'];
		if (strpos($uri, $_SERVER['SCRIPT_NAME']) === 0)
		{
			$uri = substr($uri, strlen($_SERVER['SCRIPT_NAME']));
		}
		elseif (strpos($uri, dirname($_SERVER['SCRIPT_NAME'])) === 0)
		{
			$uri = substr($uri, strlen(dirname($_SERVER['SCRIPT_NAME'])));
		}
 
		// This section ensures that even on servers that require the URI to be in the query string (Nginx) a correct
		// URI is found, and also fixes the QUERY_STRING server var and $_GET array.
		if (strncmp($uri, '?/', 2) === 0)
		{
			$uri = substr($uri, 2);
		}
		$parts = preg_split('#\?#i', $uri, 2);
		$uri = $parts[0];
		if (isset($parts[1]))
		{
			$_SERVER['QUERY_STRING'] = $parts[1];
			parse_str($_SERVER['QUERY_STRING'], $_GET);
		}
		else
		{
			$_SERVER['QUERY_STRING'] = '';
			$_GET = array();
		}
 
		// bug fix
		if ($uri=='/' || empty($uri)) return '/';
 
 
		$uri = parse_url($uri, PHP_URL_PATH);
 
		// Do some final cleaning of the URI and return it
		return str_replace(array('//', '../'), '/', trim($uri, '/'));
	}
 
}
// EOF