Scenario: As you know, StackOverflow checks the title in the question. I mean when you open this URL:
http://stackoverflow.com/questions/38839016/should-i-store-the-result-of-an-function
automatically it will be replaced with this:
http://stackoverflow.com/questions/38839016/should-i-store-the-result-of-an-function-into-an-array
That replacement is because of being incomplete the first URL.
Ok well, I'm trying to make such a system by PHP. Here is my attempt:
// getting this from the URL
$id = '38839016';
// fetching this from database based on that id (38839016)
$real_title = $result['title'];
//=> Should I store the result of an function into an array
$real_title = str_replace("-"," ",strtolower($real_title));
//=> should-i-store-the-result-of-an-function-into-an-array
// getting whole uri
$current_uri = $_SERVER["REQUEST_URI"];
//=> /questions/38839016/should-i-store-the-result-of-an-function
What I want to do: I need to compare $real_title with title-part of the $current_uri. How can I determine "title-part"? It is everything which is after $id.'/' until / or ? or $ (end of string). How can I do that comparison?
And then:
if ( preg_match("//", $current_uri) ) {
// all fine. continue loading the page
continue;
} else {
// replace title-part of the $current_uri with $real_title
preg_replace("//", $real_title, $current_uri);
// redirect to this post with correct slug
header('Location: '.$_SERVER["HTTP_HOST"].);
}
briefly, I want to complete these:
if ( preg_match("//", $current_uri) ) {
preg_replace("//", $real_title, $current_uri);
Ok, in simple words, there is a good url and a requested url
if the requested url not equal the good url
redirect the visitor to the good one
<?
$id = '38839016';
$good_url = '/questions/'.$id.'/'.str_replace("-"," ",strtolower($result['title']));
preg_match( '/\/[0-9]+\/([a-z0-9-]+)\/.*/', $_SERVER[REQUEST_URI], $matches);
if ($matches[1] != str_replace("-"," ",strtolower($result['title'])))
header('Location: '.$good_url);
Related
i have the need to break down a REQUEST_URI to perform a few functions for each string between the slashes
the request that is passed from the url looks something like the below url however i cannot assign them static variables as the url could get longer or shorter per different pages
https://www.domain.com/accounts/customers/details
what im looking to do is capture the "accounts/customers/details" section which i have done by this variable on the page
$requested_url = $_SERVER['REQUEST_URI']; // this outputs /accounts/customers/details
i wish to create a for loop extracting the information from between the brackets and displaying it on page like
accounts
customers
details
how can this be achieved
try this
$requested_url = $_SERVER['REQUEST_URI'];
$seperate = explode("/",$requested_url); //this will explode in to array with "/" seperator
foreach($seperate as $seprt) {
echo $seprt."<br/>"; //it echo's each array variable seperately
}
$requested_url = $_SERVER['REQUEST_URI'];
$seperate = explode("/",$requested_url);
$count = 0;
foreach($seperate as $seprt) {
$count++;
if($count == count($seperate)){
echo $seprt;
}
}
there is an external page, that passes a URL using a param value, in the querystring. to my page.
eg: page.php?URL=http://www.domain2.com?foo=bar
i tried saving the param using
$url = $_GET['url']
the problem is the reffering page does not send it encoded. and therefore it recognizes anything trailing the "&" as the beginning of a new param.
i need a way to parse the url in a way that anything trailing the second "?" is part or the passed url and not the acctual querystring.
Get the full querystring and then take out the 'URL=' part of it
$name = http_build_query($_GET);
$name = substr($name, strlen('URL='));
Antonio's answer is probably best. A less elegant way would also work:
$url = $_GET['url'];
$keys = array_keys($_GET);
$i=1;
foreach($_GET as $value) {
$url .= '&'.$keys[$i].'='.$value;
$i++;
}
echo $url;
Something like this might help:
// The full request
$request_full = $_SERVER["REQUEST_URI"];
// Position of the first "?" inside $request_full
$pos_question_mark = strpos($request_full, '?');
// Position of the query itself
$pos_query = $pos_question_mark + 1;
// Extract the malformed query from $request_full
$request_query = substr($request_full, $pos_query);
// Look for patterns that might corrupt the query
if (preg_match('/([^=]+[=])([^\&]+)([\&]+.+)?/', $request_query, $matches)) {
// If a match is found...
if (isset($_GET[$matches[1]])) {
// ... get rid of the original match...
unset($_GET[$matches[1]]);
// ... and replace it with a URL encoded version.
$_GET[$matches[1]] = urlencode($matches[2]);
}
}
As you have hinted in your question, the encoding of the URL you get is not as you want it: a & will mark a new argument for the current URL, not the one in the url parameter. If the URL were encoded correctly, the & would have been escaped as %26.
But, OK, given that you know for sure that everything following url= is not escaped and should be part of that parameter's value, you could do this:
$url = preg_replace("/^.*?([?&]url=(.*?))?$/i", "$2", $_SERVER["REQUEST_URI"]);
So if for example the current URL is:
http://www.myhost.com/page.php?a=1&URL=http://www.domain2.com?foo=bar&test=12
Then the returned value is:
http://www.domain2.com?foo=bar&test=12
See it running on eval.in.
So, a lot of my form systems redirect back to the previous page, although, they display a message in the process. The way I display a message is by simply using ?message=messageCode in the URL.
However, if they use the form from a page that already has a query string, it adds a second query string, messing everything up.
Example:
if I were to login from the navigation bar, on the URL "mywebsite.com/something?message=1", it would log in, but redirect to "mywebsite.com/something?message=1?message=2"
This results in no message being displayed.
What I am asking here is, how could I change all of the question marks AFTER the first question mark, to and signs?
Example:
From: mywebsite.com/page?blah=1?something=2?hi=3
To: mywebsite.com/page?blah=1&something=2&hi=3
I have searched around, as well as tried some methods of my own, but nothing seems to work properly.
What you should be doing is build a proper URL, appending ? or & when appropriate.
$url = 'mywebsite.com/something?message=1';
$new_url = sprintf('%s%s%s',
$url,
strpos($url, '?') === false ? '?' : '&',
http_build_query(['message' => 2])
);
Or, first parse the previous URL and merge the query string.
Use it like below:-
<?php
$str = 'mywebsite.com/something?message=1?message=2';
$pos = strpos($str,'?'); //check the last occurrence of ?
if ($pos !== false) {
$str = substr($str,0,$pos+1) . str_replace('?','&',substr($str,$pos+1));// replacement of ? to &
}
echo $str;
?>
Output:- https://eval.in/388308
I have a method of pulling Youtube video data from API links. I use Wordpress and ran into a snag.
In order to pull the thumbnail, views, uploader and video title I need the user to input the 11 character code at the end of watch?v=_______. This is documented with specific instructions for the user, but what if they ignore it and paste the whole url?
// the url 'code' the user should input.
_gXp4hdd2pk
// the wrong way, when the user pastes the whole url.
https://www.youtube.com/watch?v=_gXp4hdd2pk
If the user accidentally pastes the entire URL and not the 11 character code then is there a way I can use PHP to grab either the code or whats at the end of this url (11 characters after 'watch?v='?
Here is my PHP code to pull the data:
// $url is the code at the end of 'watch?v=' that the user inputs
$url = get_post_meta ($post->ID, 'youtube_url', $single = true);
// $code is a variable for placing the $url in a youtube link so I can output it to an API link
$code = 'http://www.youtube.com/watch?v=' . $url;
// $code is called at the end of this oembed code, allowing me to decode json data and pull elements from json to echo in my html
// echoed output returns json file. example: http://www.youtube.com/oembed?url=http://www.youtube.com/watch?v=_gXp4hdd2pk
$json = file_get_contents('http://www.youtube.com/oembed?url='.urlencode($code));
Im looking for something like...
"if user inputs code, use this block of code, else if user inputs whole url use a different block of code, else throw error."
Or... if they use the whole URL can PHP only use a specific section of that url...?
EDIT: Thank you for all the answers! I am new to PHP, so thank you all for your patience. It is difficult for graphic designers to learn PHP, even reading the PHP manual can give us headaches. All of your answers were great and the ones ive tested have worked. Thank you so much :)
Try this,
$code = 'https://www.youtube.com/watch?v=_gXp4hdd2pk';
if (filter_var($code, FILTER_VALIDATE_URL) == TRUE) {
// if `$code` is valid url
$code_arr = explode('?v=', $code);
$query_str = explode('&', $code_arr[1]);
$new_code = $query_str[0];
} else {
// if `$code` is not a valid url like '_gXp4hdd2pk'
$new_code = $code;
}
echo $new_code;
Here's a simple option for you to do, unless you want to use regex like Nisse Engström's Answer.
Using the function parse_url() you could do something like this:
$url = 'https://www.youtube.com/watch?v=_gXp4hdd2pk&list=RD_gXp4hdd2pk#t=184';
$split = parse_url('https://www.youtube.com/watch?v=_gXp4hdd2pk&list=RD_gXp4hdd2pk#t=184');
$params = explode('&', $split['query']);
$video_id = str_replace('v=', '', $params[0]);
now $video_id would return:
_gXp4hdd2pk
from the $url supplied in the above code.
I suggest you read the parse_url() documentation to ensure you understand and grasp it all :-)
Update
for your comment.
You'd use something like this to make sure the parsed value is a valid URL:
// this will check if valid url
if (filter_var($code, FILTER_VALIDATE_URL)) {
// its valid as it returned true
// so run the code
$url = 'https://www.youtube.com/watch?v=_gXp4hdd2pk&list=RD_gXp4hdd2pk#t=184';
$split = parse_url('https://www.youtube.com/watch?v=_gXp4hdd2pk&list=RD_gXp4hdd2pk#t=184');
$params = explode('&', $split['query']);
$video_id = str_replace('v=', '', $params[0]);
} else {
// they must have posted the video code as the if check returned false.
$video_id = $url;
}
Just try as follows ..
$url =" https://www.youtube.com/watch?v=_gXp4hdd2pk";
$url= explode('?v=', $url);
$endofurl = end($url);
echo $endofurl;
Replace $url variable with input .
I instruct my users to copy and paste the whole youtube url.
Then, I do this:
$video_url = 'https://www.youtube.com/watch?v=_gXp4hdd2pk'; // this is from user input
$parsed_url = parse_url($video_url);
parse_str($parsed_url['query'], $query);
$vidID = isset($query['v']) ? $query['v'] : NULL;
$url = "http://gdata.youtube.com/feeds/api/videos/". $vidID; // this is used for the Api
$m = array();
if (preg_match ('#^(https?://www.youtube.com/watch\\?v=)?(.+)$#', $url, $m)) {
$code = $m[2];
} else {
/* No match */
}
The code uses a Regular Expression to match the user input (the subject) against a pattern. The pattern is enclosed in a pair of delimiters (#) of your choice. The rest of the pattern works like this:
^ matches the beginning of the string.
(...) creates a subpattern.
? matches 0 or 1 of the preceeding character or subpattern.
https? matches "http" or "https".
\? matches "?".
(.+) matches 1 or more arbitrary charactes. The . matches any character (except newline). + matches 1 or more of the preceeding character or subpattern.
$ matches the end of the string.
In other words, optionally match an http or https base URL, followed by the video code.
The matches are then written to $m. $m[0] contains the entire string, $m[1] contains the first subpattern (base URL) and $m[2] contains the second subpattern (code).
I dont wan't reinvent wheel, but i couldnt find any library that would do this perfectly.
In my script users can save URLs, i want when they give me list like:
google.com
www.msn.com
http://bing.com/
and so on...
I want to be able to save in database in "correct format".
Thing i do is I check is it there protocol, and if it's not present i add it and then validate URL against RegExp.
For PHP parse_url any URL that contains protocol is valid, so it didnt help a lot.
How guys you are doing this, do you have some idea you would like to share with me?
Edit:
I want to filter out invalid URLs from user input (list of URLs). And more important, to try auto correct URLs that are invalid (ex. doesn't contains protocol). Ones user enter list, it should be validated immediately (no time to open URLs to check those they really exist).
It would be great to extract parts from URL, like parse_url do, but problem with parse_url is, it doesn't work well with invalid URLs. I tried to parse URL with it, and for parts that are missing (and are required) to add default ones (ex. no protocol, add http). But parse_url for "google.com" wont return "google.com" as hostname but as path.
This looks like really common problem to me, but i could not find available solution on internet (found some libraries that will standardize URL, but they wont fix URL if it is invalid).
Is there some "smart" solution to this, or I should stick with my current:
Find first occurrence of :// and validate if it's text before is valid protocol, and add protocol if missing
Found next occurrence of / and validate is hostname is in valid format
For good measure validate once more via RegExp whole URL
I just have feeling I will reject some valid URLs with this, and for me is better to have false positive, that false negative.
I had the same problem with parse_url as OP, this is my quick and dirty solution to auto-correct urls(keep in mind that the code in no way are perfect or cover all cases):
Results:
http:/wwww.example.com/lorum.html => http://www.example.com/lorum.html
gopher:/ww.example.com => gopher://www.example.com
http:/www3.example.com/?q=asd&f=#asd =>http://www3.example.com/?q=asd&f=#asd
asd://.example.com/folder/folder/ =>http://example.com/folder/folder/
.example.com/ => http://example.com/
example.com =>http://example.com
subdomain.example.com => http://subdomain.example.com
function url_parser($url) {
// multiple /// messes up parse_url, replace 2+ with 2
$url = preg_replace('/(\/{2,})/','//',$url);
$parse_url = parse_url($url);
if(empty($parse_url["scheme"])) {
$parse_url["scheme"] = "http";
}
if(empty($parse_url["host"]) && !empty($parse_url["path"])) {
// Strip slash from the beginning of path
$parse_url["host"] = ltrim($parse_url["path"], '\/');
$parse_url["path"] = "";
}
$return_url = "";
// Check if scheme is correct
if(!in_array($parse_url["scheme"], array("http", "https", "gopher"))) {
$return_url .= 'http'.'://';
} else {
$return_url .= $parse_url["scheme"].'://';
}
// Check if the right amount of "www" is set.
$explode_host = explode(".", $parse_url["host"]);
// Remove empty entries
$explode_host = array_filter($explode_host);
// And reassign indexes
$explode_host = array_values($explode_host);
// Contains subdomain
if(count($explode_host) > 2) {
// Check if subdomain only contains the letter w(then not any other subdomain).
if(substr_count($explode_host[0], 'w') == strlen($explode_host[0])) {
// Replace with "www" to avoid "ww" or "wwww", etc.
$explode_host[0] = "www";
}
}
$return_url .= implode(".",$explode_host);
if(!empty($parse_url["port"])) {
$return_url .= ":".$parse_url["port"];
}
if(!empty($parse_url["path"])) {
$return_url .= $parse_url["path"];
}
if(!empty($parse_url["query"])) {
$return_url .= '?'.$parse_url["query"];
}
if(!empty($parse_url["fragment"])) {
$return_url .= '#'.$parse_url["fragment"];
}
return $return_url;
}
echo url_parser('http:/wwww.example.com/lorum.html'); // http://www.example.com/lorum.html
echo url_parser('gopher:/ww.example.com'); // gopher://www.example.com
echo url_parser('http:/www3.example.com/?q=asd&f=#asd'); // http://www3.example.com/?q=asd&f=#asd
echo url_parser('asd://.example.com/folder/folder/'); // http://example.com/folder/folder/
echo url_parser('.example.com/'); // http://example.com/
echo url_parser('example.com'); // http://example.com
echo url_parser('subdomain.example.com'); // http://subdomain.example.com
It's not 100% foolproof, but a 1 liner.
$URL = (((strpos($URL,'https://') === false) && (strpos($URL,'http://') === false))?'http://':'' ).$URL;
EDIT
There was apparently a problem with my initial version if the hostname contain http.
Thanks Trent