<p>The more redirects you have, the better off you’re going to be having them managed <em>outside</em> of your .htaccess file, and in a database table.</p>

<p>Each redirect in your .htaccess file comes with a slight performance hit, since mod_rewrite needs to parse and evaluate each one individually, for every single request.</p>

<p>If you have them managed in an indexed database table, the performance hit will be trivial – just the time it takes to make a very simple DB query.</p>

<p>I haven’t used <a href="https://github.com/davist11/craft-reroute" rel="nofollow">Reroute</a>, but it looks like that’s just storing redirects in a DB table, so it’s probably going to be your best bet for managing hundreds of redirects. (Not sure how scalable the UI is, though.)</p>

CC BY-SA 3.0
2014-07-03T15:25:01.123Z
Interesting, didn't know about potential performance hits. Looking at potentially pasting the old and new urls into the db. Each new one generates a code in the db under a uid column which need to do some homework on.
Simon Clayson
CC BY-SA 3.0
2014-07-02T14:02:56.143Z
2014-07-02T14:02:56.143Z
Brandon Kelly
<p>If I understand what you're looking for, it's not so much dangerous as it is not possible. Apache looks at the filesystem and parses the .htaccess file directly, and this is done long before Apache starts to process any PHP.</p>

<p>A route you could take is writing the .htaccess file each time an entry is saved (or having a button that does it so you're not wasting resources). So long as PHP has the write access, this should be doable. Plus, you can still render the file via the template service.</p>

<pre><code>$htaccess = craft()-&gt;templates-&gt;render('PluginHandle/path/to/template');
</code></pre>

CC BY-SA 3.0
2014-07-03T07:37:26.423Z
I like the idea of exporting a fresh .htaccess file rather than cached db lookup.
Luke Holder
CC BY-SA 3.0
2014-07-03T15:22:31.967Z
Thanks for this. We're a bit stuck in the middle of this in that we have a lot of legacy entries transferred with urls, but future legacy one will be added as-you-go by the client. Suspect Reroute plugin best bet here.
Simon Clayson
CC BY-SA 3.0
2014-07-02T13:19:03.977Z
2014-07-02T13:19:03.977Z
Bryan Redeagle
<p>For a case like yours, my <a href="https://github.com/nystudio107/retour" rel="nofollow">Retour</a> plugin would work well, because it has a FieldType that you can attach to existing Entries, and do the redirect based on data from the entries.  </p>

<p>So you can set up a rule in the FieldType like <code>.*RecipeID={recipeid}</code> as the default Legacy URL Pattern, and it'll pull the value from the <code>{recipeid}</code> field in each entry, and create a redirect for it to the new entry.</p>

<p>It also doesn't do anything unless a 404 exception actually occurs.</p>

CC BY-SA 3.0
2016-04-25T20:27:36.937Z
2016-04-25T20:27:36.937Z
andrew.welch
<p>I'm not sure how safe it is but I have just imported 301 redirects into Craft-Reroute by exporting the old &amp; new url slugs to a csv file. </p>

<p>I then imported that using Sequel Pro and set default values for <code>method</code>, <code>date_created</code> &amp; <code>date_updated</code>. <code>Id</code> is auto incremental but <code>uid</code> isnt set unfortunately.</p>

CC BY-SA 3.0
2014-07-24T18:50:18.600Z
Yes, this is what I've done as well, but seems to work ok. I've set the uid so my cdv code looks like this

`id,"oldUrl","newUrl",method,"dateCreated","dateUpdated","uid"
{% set redirects = craft.entries.order('title').limit(1000) %}
{% for entry in redirects %}{% if entry.urllegacy|length %}{{loop.index}},"{{ entry.urllegacy }}","/{{ entry.uri }}","301","2014-07-24 15:00:00","2014-07-24 15:00:01","{{ entry.id }}"
{% endif %}{% endfor %}`
Simon Clayson
CC BY-SA 3.0
2014-07-15T08:35:14.030Z
2014-07-15T08:35:14.030Z
Seán O'Grady
<p>The <a href="https://github.com/davist11/craft-reroute" rel="nofollow">Reroute plugin</a> is great for a handful of 301 redirects, but we have hundreds of entries and each entry has a legacy URL. Dumping this into a template as normal works fine, but thinking about if it could work with the .htaccess file directly. Has anyone tried, or would be a dangerous path?</p>

<p>Thinking along the lines of NSM htaccess for EE.</p>

<templating><redirect>
.htaccess as a Craft template for 301 redirects?
# .htaccess as a Craft template for 301 redirects?

(Asked by: username_0 on 2014-07-02)

The [Reroute plugin](https://github.com/davist11/craft-reroute) is great for a handful of 301 redirects, but we have hundreds of entries and each entry has a legacy URL. Dumping this into a template as normal works fine, but thinking about if it could work with the .htaccess file directly. Has anyone tried, or would be a dangerous path?

Thinking along the lines of NSM htaccess for EE.

**Tags:** templating, redirect

---

## 4 answers

### Answer by username_1 on 2014-07-02. Score: 1 | Accepted answer

The more redirects you have, the better off you’re going to be having them managed *outside* of your .htaccess file, and in a database table.

Each redirect in your .htaccess file comes with a slight performance hit, since mod\_rewrite needs to parse and evaluate each one individually, for every single request.

If you have them managed in an indexed database table, the performance hit will be trivial – just the time it takes to make a very simple DB query.

I haven’t used [Reroute](https://github.com/davist11/craft-reroute), but it looks like that’s just storing redirects in a DB table, so it’s probably going to be your best bet for managing hundreds of redirects. (Not sure how scalable the UI is, though.)

> **Comments:**
> **username_0**: Interesting, didn't know about potential performance hits. Looking at potentially pasting the old and new urls into the db. Each new one generates a code in the db under a uid column which need to do some homework on.  

---

### Answer by username_2 on 2014-07-02. Score: 1

If I understand what you're looking for, it's not so much dangerous as it is not possible. Apache looks at the filesystem and parses the .htaccess file directly, and this is done long before Apache starts to process any PHP.
A route you could take is writing the .htaccess file each time an entry is saved (or having a button that does it so you're not wasting resources). So long as PHP has the write access, this should be doable. Plus, you can still render the file via the template service.
$htaccess = craft()->templates->render('PluginHandle/path/to/template');

> **Comments:**
> **username_3**: I like the idea of exporting a fresh .htaccess file rather than cached db lookup.  
> **username_0**: Thanks for this. We're a bit stuck in the middle of this in that we have a lot of legacy entries transferred with urls, but future legacy one will be added as-you-go by the client. Suspect Reroute plugin best bet here.  

---

### Answer by username_4 on 2016-04-25. Score: 1

For a case like yours, my [Retour](https://github.com/nystudio107/retour) plugin would work well, because it has a FieldType that you can attach to existing Entries, and do the redirect based on data from the entries.

So you can set up a rule in the FieldType like `.*RecipeID={recipeid}` as the default Legacy URL Pattern, and it'll pull the value from the `{recipeid}` field in each entry, and create a redirect for it to the new entry.

It also doesn't do anything unless a 404 exception actually occurs.


---

### Answer by username_5 on 2014-07-15. Score: 1

I'm not sure how safe it is but I have just imported 301 redirects into Craft-Reroute by exporting the old & new url slugs to a csv file.

I then imported that using Sequel Pro and set default values for `method`, `date_created` & `date_updated`. `Id` is auto incremental but `uid` isnt set unfortunately.

> **Comments:**
> **username_0**: Yes, this is what I've done as well, but seems to work ok. I've set the uid so my cdv code looks like this  `id,"oldUrl","newUrl",method,"dateCreated","dateUpdated","uid" {% set redirects = craft.entries.order('title').limit(1000) %} {% for entry in redirects %}{% if entry.urllegacy|length %}{{loop.index}},"{{ entry.urllegacy }}","/{{ entry.uri }}","301","2014-07-24 15:00:00","2014-07-24 15:00:01","{{ entry.id }}" {% endif %}{% endfor %}`  

---

