I am trying to enable clean urls with Angular JS inside my Laravel 4 app. When I tried the required thing normally without laravel 4 refering to this url.
http://www.yearofmoo.com/2012/11/angularjs-and-seo.html, I was able to get the thing to work. Even ?_escaped_fragment_= was changed to snapshot/* folder and picked the content.
But I am not able to do the same in Laravel 4. I am not sure how to do this.
I am trying to define a route like ?_escaped_fragment_=/* and redirect it to some controller but that doesn't work.
Can anyone please help.
Escaped fragment is a query parameter, not a route, there for, in the root route Route::get('/', 'RootCtrl');, you can check for $_GET['_escaped_fragment'] presence, and if it is there, return an HTTP 302 redirect to the corresponding file in the snapshots dir.
While this will work, it is not the perfect solution, since some bots might index the path of the snapshots file instead of the original one, and since doing it using the Laravel framework is not correct in the first place.
The best choice of course, is to rewrite any request that contains an _escaped_fragment_
query parameter to it's corresponding path, in the nginx\apache configuration, prior to the configuration of your Laravel app, this way those requests won't event reach the Laravel router.
I have co-authored an Angular SEO plug-and-play solution, using PhantomJS & Mongoose integrated web server, to pre-render any Async JS code, and server it as raw HTML.
The server configuration aspects are also explained in the README.md file, please note that if you would like to use static snapshots, just change proxy-pass to rewrite(in order for the right URL to get indexed by the bots).
Hope that helps.
Example using simple rewrites with nginx:
if ($args ~* "^_escaped_fragment_=(.+)") {
set $path $1
set $args '';
rewrite ^.*$ /snapshots/$path last;
}
EDIT:
Apache, for your request (some words of advice: move to nginx).
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{QUERY_STRING} ^_escaped_fragment=(.+)$
RewriteRule ^.*$ /snapshots/%1 [QSA,L]
</IfModule>
Related
I have looked around and attempted my own research on this topic but to no avail just yet.
I have a dynamic webpage set up to look for a ID from a database to retrieve elements required. This results in of course the web page looking like www.site.com/page?id=1
My desired outcome would be like a title for this page to be called.
Such as say I had a fruit product it and user went to my site and went to the address /fruit it would it would be the content of ?id=1 just as an example.
I have seen this used on many a site but not sure how this is programmed or works. Is this something to do with a htaccess document?
Thanks in advance. Appreciate all the help.
While this has been asked and answered many times, I know many people find it difficult to search for this since there are so many common "noise" words related to it. For that reason, I believe it's worth answering again.
If you're using Apache as your webserver (which I'm assuming you are since you mention .htaccess), what you're looking for to create those "clean URLs" is mod_rewrite, which takes a set of rules and rewrites the URL requested by the browser to another path or script.
You would typically enable this in your Apache config or in .htaccess, and in a simple form (a one-to-one mapping) at it would look something like this (provided mod_rewrite is installed):
RewriteEngine On
RewriteRule ^fruit$ index.php?type=1 [L]
Now obviously that doesn't scale well if you have a bunch of dynamic pages you want to create, so what you can do is tell all pages that aren't a really file or directory to be passed to a file for processing, like so:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php [L]
In this case we're rewriting any request that doesn't resolve to a real file or directory to index.php, and then using the "last" flag [L] to stop processing other rules. Then in our PHP script, we can access the virtual path (in this case /fruit) by using $_SERVER['PATH_INFO'] and doing whatever conditional logic we want with that. If you don't get anything in that variable, ensure that the AcceptPathInfo On directive is set in your Apache config or .htaccess.
A way to test the basic concept/logic without having any rewrite rules would be to use a URL like https://example.com/index.php/fruit. You'll then see that in index.php $_SERVER['PATH_INFO'] will contain the string /fruit. You can rewrite URLs to files in other directories, chain rewrite rules, redirect the browser to other URLs, or even edit environment variables.
There are many good tutorials around using mod_rewrite for clean URLs, so I won't attempt to cover all the nuances here. Just know that it's a very powerful tool, but it's also pretty easy to break your rules if you aren't very comfortable with regular expressions or get lost in the many rules that are commonly in a configuration.
Note that if this is an existing site, you'll also want to use mod_rewrite or mod_redirect to redirect the old URLs to the new ones so they don't break (and for the benefit of having a single URL for search rankings).
I have a problem with a project I'm doing with PHP and it's in the URLs.
When I load a script like index.php everything works fine, the problem is when I load a script that is located within two or more directories.
In the URL the scripts with the routes begin to be enmeshed
Here is an example of the problem I have
I need to load a script, even if it is in several levels of nesting, make its functionality and in the url is reflected as:
I need to have something like this
1:
I thank you in advance.
Regards
You can't use PHP to achieve this. PHP is not responsible for determining if PHP (let along a particular PHP script) will handle any given URL.
You have to configure your webserver to do it. Since you mention .htaccess but provide no further information about your server, I'm going to assume you are using Apache HTTPD.
For Apache, that means using mod_rewrite, Alias or something similar. You can put the configuration for those tools in .htaccess, but you don't want to and the documentation advises not to use them.
So put your mod_rewrite or Alias configuration in the main Apache configuration.
You're going to need an htaccess rule no matter what. However, it doesn't have to be a mod_rewrite rule. The reason you need this rule is because PHP is not responsible for the routing - it is merely responsible for the execution of your script.
The point of the rule is to direct apache and instruct it to execute the right script (in your case, script32.php) while keeping the request uri as intact as possible.
There are two ways around it, basically.
Way 1 (cleaner): mod_rewrite
This is pretty straightforward, the set of rules you need are as follows:
# If the requested file name is a valid file/inode
RewriteCond %{REQUEST_FILENAME} -f [OR]
# ...or a directory
RewriteCond %{REQUEST_FILENAME} -d
# ...then throw them straight on it
RewriteRule (.*) - [L]
# ...otherwise, redirect to script32.php with the full content of the request in query string
RewriteRule (.*) /welcome/script32.php?$1 [L]
The requested URL is now in $_SERVER['QUERY_STRING'] and you can now do whatever you like with it in PHP
Way 2: catchall
This does not rely on mod_rewrite and may therefore be slightly faster. However, technically, it's a cheap hack. The way around it is as follows:
ErrorDocument 404 /welcome/script32.php
The requested URL can now be found in $_SERVER['REQUEST_URI'] and is available for parsing in PHP. However, with this, you've also disabled "legit" 404 errors from being generated through apache - and should make sure to obey proper behaviour in PHP to compensate.
I am confused about how a php framework works with a web server like apache. Now if there wasn't a framework and if it was using classic php, then I understand how it works(if a php file is requested, the php parser executes it and returns the htm to the server).
When a framework like cakePHP is used, I have noticed that no matter which url the client requests, the index.php in the root folder gets executed first. How is this possible? if we were using pure php then, only the file we requested will get executed. So how does cakePHP make each and every request to go through the /index.php file?
CakePHP, and many other websites, leverage mod_rewrite which is an Apache module that "Provides a rule-based rewriting engine to rewrite requested URLs on the fly".
To do so, the web framework will use a .htaccess file with specific rules defined. These rules, in the case you're asking about, point any URL matching a specific pattern to to a real index.php file (this file can be named anything really, but index.php is a good "default" name).
Per CakePHP's URL Rewriting outline, a base rule is defined as:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /path/to/cake/app
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php [QSA,L]
</IfModule>
What the above does is:
Turns on the rewrite module
Sets two conditions for rewriting the current URL
a. Only if the requested file is not a real directory (!-d)
b. Only if the requested file is not a real file (!-f)
Sends the full requested URL, (.*) to index.php
Sometimes, you'll see the RewriteRule line as:
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
This will set the requested url into the $_GET['url'] parameter instead of forcing the application to process the $_SERVER['REQUEST_URI']. Other times, there will be a lot of rewrite rules, some complicated, some basic.
There are a lot of good resources online, and in books, regarding mod_rewrite. Check out Introduction to URL Rewriting for one (it's one I have bookmarked, has a lot of good basic rules / formats).
That's a pretty simple one (https://github.com/gilbitron/PIP).
Read the files in the System folder.
Basically it goes like this:
All requests are sent to the index file (with mod_rewrite, or like a plain get parameter).
The index file includes configuration files and definitions of constants.
Then it loads the main class for the framerwork.
The main class does some configurations, initiates a database connection and so on.
Depending on how it is implemented, there might be a router but it's possible there isn't.If there is one the main class checks what controller should be loaded against the request in the router.
Then the main class loads the controller that should be loaded with that particular request.
PIP is not that good and the main class is actually not a class but you can get the point in it.
You can also read about the following things:
Object oriented programming: http://php.net/manual/en/language.oop5.php
Scopes: http://php.net/manual/en/language.variables.scope.php
Autoloading classes: http://php.net/manual/en/language.oop5.autoload.php
You mentioned
"I have noticed that no matter which url the client requests, the index.php in the root folder gets executed first."
This is what front controllers do. You can have a front controller with a framework or if coding from scratch using the .htaccess file. Front controllers enable rendering of pages using PHP functions/methods, such as $app->get($uri, $callback); in Lumen.
I want to map URL in my localhost XAMPP into custom files.
For example:
localhost/index.php --> d:\xampp\htdocs\index.php (default)
localhost/normal/data.php --> d:\xampp\htdocs\normal\data.php (default)
localhost/view/userinfo.php --> d:\xampp\htdocs\view.php?p=userinfo (custom)
localhost/view/welcome.php --> d:\xampp\htdocs\view.php?p=welcome (custom)
So, basically, all URL that goes into inside view path will be mapped to view.php files with the filename.php (minus the .php) as its query parameter. There's actually no physical folder view, and no physical files userinfo.php and welcome.php inside the folder.
The reason that I need to do this is that so I can pass all the pages that viewing data into an "application frame" that will wrap the page with header, menu, and footer, and I don't need to give header, menu, and footer call in each page. I might have the actual files userinfo.php that I can $include_once, or I might not (I can just generate it from within the view.php), but hey, that's one of the power of this kind of framework, right? And, if someday I need to change this structure, I can change it from just within one file (view.php), not all.
Can I do this in PHP and XAMPP? How? I've noticed that some website seems to used this practice (URL which have no actual files or even path at all), but when I try to read tutorial for it, I got confused.
URL mapping in PHP?
The accepted answer listed 3 links to learn about URL rewriting. Mostly they're written for Apache in Linux, and mostly they pull all the possible scenario and configuration that I got confused which one I really need with all those long documents and technical jargon. I need just the practical step of my specific problem, and then, I will be able to start from there to explore myself if I have more advanced needs. Please help.
if you do want to go down the mod rewrite route adding the following to an .htaccess file in the site root should do it. You will need to make sure mod rewrite is on for XAMPP and I can't help you there I'm afraid. As you can see it rewrites the url, not the windows filename - so it would work on any OS.
The ([a-z]*) means it will take any filename.php with lowercase letters and redirect to /view.php?p=$1 where the $1 will be replaced by filename.
the [L,R] (L means last rule so stop processing if any more are reached, and the R means redirect (it will change the url in the browser). Use P instead to reverse Proxy (the user will still see the url they requested but the server will serve the correct file) - This will require mod_proxy as well.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_URI} ^view/
RewriteRule ^view/([a-z]*).php$ /view.php?p=$1 [L,R]
</IfModule>
XAMPP uses apache so the rewrites would work the same in Windows as they do in Linux. You could place a .htaccess in the site root directory with some rewrite rules.
However, using PHP
in d:\xampp\htdocs\view\userinfo.php you could include the line
<?php
header('Location: http://localhost/view.php?p=userinfo');
?>
But this must be before any thing is echoed to the screen (even whitespace).
You can use the Apache module mod_rewrite to edit requests before they hit PHP. You want to put something like the following in a .htaccess file in your htdocs directory.
RewriteEngine on
RewriteCond %{REQUEST_URI} ^view/
RewriteRule ^view/(.*)\.php.*$ view.php?p=$1 [L,QSA]
QSA means Query String Append. This means that if there are any GET parameters set on the original request they will be appended to the end of the new request too.
Note that this assumes that Apache is configured with AllowOverride enabled and the mod_rewrite module loaded.
I am restyiling my own php mvc framework.
I have every request handled by /index.php by default, which triggers the mvc process of routing, executing the request and returing a proper view. Each request is routed according to a single 'q' GET parameter, drupal style, like
/index.php?q=anApplication/aController/theAction/arg1/.../moreArguments
This works pretty good, and makes the clean url thing easy via mod_rewrite. Ok.
I have a directory tree like this:
/public
|----themeName
|--------|
|----page.tpl
|----content.tpl
|----etc.
/private
|----sourceDirectory
|----moreSources
What i dont want is files stored in private and public directories to be served directly like an HTTP request: i dont want something like
mySrv/public/themeName/page.tpl
to show a dead template, or any resource that is not an image, bypassing my core handler - index.php.
I think i could achieve something with a rewrite configuration like this
RewriteEngine on
RewriteBase /
RewriteRule ^(.*)$ index.php?q=$1 [QSA,L]
but then the framework would only work on mod_rewrite-enabled sites, because this will rewrite all existing and non-existing resources.
What i am asking for is: is there another way to make EVERY request served by a resource (such an index.php) of my choice, existing or non-existing ones?
Thank you
Just store all your templates etc outside of the public_html folder.
This will allow PHP to have access, but the outside world cannot get to the file.
The easiest and more portable way would be to pull everything except your index.php out of the document root. PHP can still include files and do everything else.
I have not tried this, but if you put an index.php outside the old document tree
---/ app / new-index.php
|
/ public /
|
/ private / ...
|
index.php
and then add at the beginning of new-index.php
<?php
chdir('..');
require 'index.php';
?>
and finally reconfigure Apache so that the DocumentRoot actually becomes /app, then everything should work as before -- except that any URLs but '/' stop making sense for Apache, and all can be made to land on a suitable ErrorDocument 404.
Note: "everything should work", except HTTP redirections. You can read a non-interpreted PHP file from the FS, but you can no longer get its interpreted content from, say, Apache on localhost. Also, you ought to verify that any existing code does not make use of the DOCUMENT_ROOT global variable; if necessary you may overwrite it.