July 2, 2013

htaccess rule cannot override previous rule

MrN’s Question:

I have a bunch of htaccess rule setup on website.

RewriteEngine On
RewriteBase /
RewriteRule ^google73947f9bfca52abe.html$    google73947f9bfca52abe.html [L]
RewriteRule ^page/(.*)$ index.php?title=page&r=$1 [L]
RewriteRule ^media/(.*)$ index.php?title=page&r=$1 [L]

RewriteRule ^admin/$    admin/php [L]
RewriteRule ^index.html$    index.php [L]
RewriteRule ^crons/$    crons/ [L]

#I did this to forward request to directory    
RewriteRule ^sites/$    sites/ [L]

#This  is the rule creating problem
#RewriteRule ^sites/([^.]+)$    sites/$1 [L]


RewriteRule ^([^.]+).html$   /index.php?title=$1
RewriteRule ^(.*).htm       index.php?action=$1 [L]RewriteRule ^([^.]+)$   /index.php?title=$1

I want to override every rule for those that start with site.com/sites to go the directory instead of going to index.php as it configured to do so.

Whenever I go to site.com/sites the sites takes me to site.com/site/?title=sites but I can still browse it as folder but Whenever I open a html file like lets say test.html it takes me directly to index.php on earlier directory as it is suppose to.

How to write rule which lets me browse a directly freely?

You have to configure to omit all the rules when the line sites is encountered.

Here is your solution:

RewriteEngine On
RewriteRule ^(sites) - [L]

#Rest of your rules
August 6, 2012

Zend Framework: Fatal error on the server

Question by Guilhem Soulas

I’m trying to put a ZF website on the Internet which works well on my local machine (WAMP).

But on the Linux server, only the main page can be properly displayed. For the other pages, I’ve got a fatal error:

Fatal error: Uncaught exception
‘Zend_Controller_Dispatcher_Exception’ with message ‘Invalid
controller specified (error)’ in
/var/www/staging/library/Zend/Controller/Dispatcher/Standard.php:248
Stack trace: #0
/var/www/staging/library/Zend/Controller/Front.php(954):
Zend_Controller_Dispatcher_Standard->dispatch(Object(Zend_Controller_Request_Http),
Object(Zend_Controller_Response_Http)) #1
/var/www/staging/library/Zend/Application/Bootstrap/Bootstrap.php(97):
Zend_Controller_Front->dispatch() #2
/var/www/staging/library/Zend/Application.php(366):
Zend_Application_Bootstrap_Bootstrap->run() #3
/var/www/staging/public/index.php(26): Zend_Application->run() #4
{main} Next exception ‘Zend_Controller_Exception’ with message
‘Invalid controller specified (error)#0
/var/www/staging/library/Zend/Controller/Front.php(954):
Zend_Controller_Dispatcher_Standard->dispatch(Object(Zend_Controller_Request_Http),
Object(Zend_Contr in
/var/www/staging/library/Zend/Controller/Plugin/Broker.php on line
336.

I activated the URL rewriting. I’m using modules. The index.php and application.ini are very basic, we didn’t custumize it.

I suppose that there is something wrong with the configuration… Thanks.

Answer by Starx

When deploying application from windows platform to Linux, most typical type of error that can be encountered is due to the filename cases. Linux system are very strict about file name and cases.

The error you are encountering is also probably one of these cases. Check the name of ErrorContainer.php and try to match the name you specify in your route and file system.

March 3, 2012

SEO URL based on category name without have a category id in URL

Question by Unknown Error

I have two table posts & categories

post_id | post_title  | post_content   | post_cat
--------------------------------------------------
1         Hello World  welcome to my..   1
.         ..           ..                ..

categories table

cat_id | cat_name | cat_parent
-----------------------------
1        News       NULL
2        Sports     1
.        ...        .. 

Let’s say current category link for news is http://domain.com/category/1/

MySQL statment

SELECT posts.post_id,
       posts.post_id,
       posts.post_title,
       posts.post_content,
       posts.post_cat,
       categories.cat_id,
       categories.cat_name,
       categories.cat_parent
FROM   posts
       INNER JOIN categories
         ON posts.post_cat = categories.cat_id  
       WHERE posts.post_cat = (int)$_GET['cat_id']

So we can get a result for post_cat = 1

According to my current database structure, how do I remove the ID but change it to be a nice slug? Example :-

Main category - http://domain.com/category/news/
Sub category  - http://domain.com/category/news/sports/

Let me know a clue how script will tell News is equal 1 on post_cat column?

Answer by Lix

You can use an .htaccess file to rewrite the URL’s for you.

The entry in the .htaccess file would look something like this :

RewriteEngine on
RewriteCond $1 ^category 
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ parseCategoryUrl.php?q=$1 [L,QSA]

I’ll break down the lines here to help understand whats going on and what each line means :

  1. Turn the RewriteEngine on.
  2. This rewrite will only occur on URL’s where the first word after the host name is category – all URL’s starting with that word will be processed by the lines below.
  3. The rule will exclude URL’s that point to actual files !-f
  4. The rule will exclude URL’s that point to actual directories !-d
  5. The actual rule will capture the entire request_uri and pass it to the parseCategoryUrl.php file with the entire request as a parameter called q (query) in the $_GET array. The flags at the end of the rule (L,QSA) do two things.
    • L – This is the last rule. After processing this line the .htaccess file will stop performing actions on the current URL.
    • QSA – Append the query string to the rewritten URL (so that we can parse it later).

Your parseCategoryUrl.php file could contain something similar to the following :

$request = explode('/',$_GET['q'] );
array_shift($request);

The first line will split the request by slashes into an array – and the second line removes the word category from the beginning of the array (because we know that we are parsing a category URL).

The final $request array, with a URL example such as :
http://example.domain.com/category/news/sports
Will be this :

Array
(
    [0] => news
    [1] => sports
)

So you see here that you have now successfully split the URL into an array; All you have to do now is query your database and and provide the user with the correct page.
Because the parseCategoryUrl.php page in fact has no output, you could just use an include() function to insert the correct page according to the URL that was provided.


SEO is about making your pages and their URL’s more informative to search engines so that a user searching the internet will be able to receive page results that are related to their search query. A search engine looking at the URL :
http://domain.com/category/1/2
will not be able to extract much information. However if your URL contains (as your question requires), category information, then a search engine will be able to deduct that the specific URL is related to :

  • http://domain.com/category/news/ – news
  • http://domain.com/category/news/sports – sports news
  • http://domain.com/category/blog/ – blog
  • etc…

Answer by Starx

It is not as different as generate an url with id. Use the same logic to generate the url with title. However they way I see it, there is only one thing, you need to remember.

The category name has to be unique at all cost.

Place a .htaccess to ensure the titles are properly redirected you the page

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /category.php?title=$1 [L]

Then, instead of using id in the query use the title

SELECT posts.post_id,
       posts.post_id,
       posts.post_title,
       posts.post_content,
       posts.post_cat,
       categories.cat_id,
       categories.cat_name,
       categories.cat_parent
FROM   posts
       INNER JOIN categories
         ON posts.post_cat = categories.cat_id  
Where 
      categories.cat_name = 'News'

As for the subcategory also, the above query should work, since all the categories are placed in same table.

...

Please fill the form - I will response as fast as I can!