I have been working on a fancy router/dispatcher class for weeks now trying to decide how I wanted it, I got it perfect IMO except performance is not what I am wanting from it. It uses a route map arrap = /forums/viewthread/:id/:page => 'forums/viewthread/(?\d+)' and loops through my map array with regex to get a match, I am trying to get something better on a high traffic site, here is a start...
$uri = "forum/viewforum/id-522/page-3";
$parts = explode("/", $uri);
$controller = $parts['0'];
$method = $parts['1'];
if($parts['2'] != ''){
$idNumber = $parts['2'];
}
if($parts['3'] != ''){
$pageNumber = $parts['3'];
}
Where I need help is sometime an id and a page will not be present sometime one or the other and sometimes both, so obvioulsy my above code would not cover that, it assumes array item 2 is always the id and 3 is always the page, could someone show me a practical way of matchting up the page and id to a variable only if they exist in the URI and without using regular expressions?
You can see what I have so far on my regular expressions versions in this question Is this a good way to match URI to class/method in PHP for MVC
This seems more extendable:
$parts = explode("/", $uri);
$parts_count=count($parts);
//set default values
$page_info=array('id'=>0,'page'=>0);
for($i=2;$i<$parts_count;$i++) {
if(strpos($parts[$i],'-')!==FALSE) {
list($info_type,$info_val)=explode('-',$parts[$i],2);
if(isset($page_info[$info_type])) {
$page_info[$info_type]=(int)$info_val;
}
}
}
then just use $page_info values. You can easily add other values this way and more levels of '/'.
if ( ! empty($parts['2']))
{
if (strpos($parts['2'], 'id-') !== FALSE)
{
$idNumber = str_replace('id-', '', $parts['2']);
}
elseif (strpos($parts['2'], 'page-') !== FALSE)
{
$pageNumber = str_replace('id-', '', $parts['2']);
}
}
And do the same for $part[3]
Related
I'm using below function to redirect a specific url to a specific php script file:
add_action('wp', function() {
if ( trim(parse_url(add_query_arg(array()), PHP_URL_PATH), '/') === 'pagename' ) {
include(locate_template('give_some.php'));
exit();
}});
it works only for the specified url and i want to make it work for multiple urls. Suppose a file urls.txt contain numbers of url and for which above code have to be triggered. Any idea how to do this?
I’m a long-time WordPress developer, and one of the best responses to a WordPress problem is “that’s not a WordPress problem, just simple PHP (or JavaScript)” one. That’s a really good thing because it makes it really easy to talk about.
Your problem, as I understand it, is that you want to compare the current URL to a “file” of possible paths. You’ve got the WordPress equivalent of “current URL”, so I’ll take that for granted, and I’ll also assume you can take a file and convert it into an array. But once you do that, you are parsing a URL (which you already did) and seeing if it is in the array:
$url = 'https://www.example.com/pagename?a=b&c=d';
$paths = [
'gerp',
'pagename',
'cheese',
];
$path = trim(parse_url($url, PHP_URL_PATH), '/');
if ( in_array($path, $paths )) {
echo 'yes';
} else {
echo 'no';
}
Demo: https://3v4l.org/NOmpk
You can use different hook request. Which allow you to manipulate request.
add_filter( 'request', function( $request ){});
My simple example ( not tested ).
add_filter( 'request', function( $request ){
$data = file_get_contents("database.txt"); //read the file
$rows = explode("\n", $data); //create array separate by new line
$rows = array_map("trim", $rows); // for removing any unwanted space
$rowCount = count($rows); // Count your database rows
for ($i=0; $i < $rows ; $i++) {
if( isset( $request['pagename'] ) && $rows[$i] == $request['pagename'] ){
include(locate_template('give_some.php'));
}
}
return $request;
});
My advice, don't use .txt files, save your data into database, and then use it, or create wp_option field, and manage from Settings page.
I'm writing a code what compares a links from imdb and tmdb.
The code matches link to imdb and then transforms it for the tmdb link, if was inserted.
The links look like:
https://www.imdb.com/title/tt0848228
https://www.themoviedb.org/movie/24428
I want to ask if these regexs are correct for movies links.
For ex.
$imdb_url = https://www.imdb.com/title/tt0848228
if (strpos($imdb_url, 'themoviedb.org') == true) {
preg_match_all('/\\d*-/', $imdb_url, $tmdb_id);
$tmdb_id = $tmdb_id[0];
$tmdb_id = str_replace('-', '', $tmdb_id);
$tmdb_id = $tmdb_id[0];
$request_url = amy_movie_provider_build_query_url('tmdb', $tmdb_id, $api_key);
$the_data = wp_remote_get($request_url, array(
'timeout' => $timeout,
));
if (!is_wp_error($the_data) && !empty($the_data)) {
$movie_data = json_decode($the_data['body'], true);
$result = amy_movie_add_tmdb_movie_data($movie_data);
echo $result;
exit;
} else {
$result = esc_html__('Provider TMDB being error!', 'amy-movie-extend');
echo $result;
exit;
}
exit;
}
And else for imdb link:
else if (strpos($imdb_url, 'www.imdb.com') == true) {
preg_match_all('/tt\\d{7}/', $imdb_url, $imdb_id);
$imdb_id = $imdb_id[0];
$imdb_id = $imdb_id[0];
}
I think it's not working because something may be wrong with not existing /movie prefix in the link, but I tried changing that and it still catches error 404.
Why not combining the domain part with the rest of the URI? Why once omitting the subdomain and once making it mandatory?
$sURI= 'whatever';
if( preg_match( '#imdb\\.com/title/tt(\\d{7})#i', $sURI, $aMatch ) ) {
echo 'IMDb, movie #'. $aMatch[1];
} else
if( preg_match( '#themoviedb.org/movie/(\\d+)($|-)#i', $sURI, $aMatch ) ) {
echo 'TMDb, movie #'. $aMatch[1];
} else {
echo 'Unrecognized';
}
This way it doesn't matter if the IMDb URI comes with www. or not. Since the movie IDs have a fixed length we don't even need to expect/care a slash following. Your mistake was expecting a slash without any need.
Same for TMDb, which either ends right away (but we want to get all digits to the end, not just the first) or is followed by a dash. i is for really distorted URIs for whichever reason. Your mistake was to expect a dash and to make digits entirely optional (when at least one should be needed, as in https://www.themoviedb.org/movie/9)
Side note: Using \\d in a PHP string for a regular expression is the correct way, as you first have to deal with the string context - there an effective backslash has to be escaped by the backslash itself. And only after that the scope of the regular expression is encountered. \d only also works because unknown string escapings are silently ignored.
I'm creating an API with PHP and am having difficulty with the URL, it gets this URL to me http://localhost/api/index/Peoples/3
The idea is that I want to use the Peoples Class and I want to get the Person with code 3, is there any way I can get Peoples and number 3?
The idea I made was this, I retrieve the URL from the browser and I'm going to explode on it. While I do not need to pass parameters through the url this works perfectly
public function getClass(){
$params = explode("/api/index/", $this->currentUrl);
if(count($params) == 1)
return "no have class !";
else
{
$params = explode('/', $params[1]);
$this->callClass($params[0]);
return "Classe : ".$params[0];
}
}
with this code I can recover Peoples and then know which class I will use. now I want to pass the parameter of the code, as for example 3. I could pass as follows ../Peoples?id=3 but I would have to break even more my string, have a better way to do this?
What's the difference between passing ../Peoples?id=3 or ../Peoples/3 and how can I recover?
you can try something like this
public function getClass()
{
$path = explode('/', parse_url($this->currentUrl, PHP_URL_PATH));
if(count($path) !== 5){
return 'not valid url';
}
$id = array_pop($path);
$class = array_pop($path);
//$this->callClass($class);
$newPath = $class.'?id='.$id;
return $newPath;
}
and regarding your question about /Peoples?id=3 or ../Peoples/3
the second one is easier if you are working with a framework such as symfony or laravel where you can define controllers and the first one you can easily fetch you data from the URL with $_GET['id']
Hope that was what you are looking for.
Is there any predefined method in PHP to get sub-domain from url if any?
url pattern may be:
http://www.sd.domain.com
http://domain.com
http://sd.domain.com
http://domain.com
where sd stands for sub-doamin.
Now method must return different values for every case:
case 1 -> return sd
case 2 -> return false or empty
case 3 -> return sd
case 4 -> return false or empty
I found some good links
PHP function to get the subdomain of a URL
Get subdomain from url?
but not specifically apply on my cases.
Any help will be most appreciable.
Thanks
Okay, here I create a script :)
$url = $_SERVER['HTTP_HOST'];
$host = explode('.', $url);
if( !empty($host[0]) && $host[0] != 'www' && $host[0] != 'localhost' ){
$domain = $host[0];
}else{
$domain = 'home';
}
So, there are several possibilities...
First, regular expressions of course:
(http://)?(www\.)?([^\.]*?)\.?([^\.]+)\.([^\.]+)
The entry in the third parenthesis will be your subdomain. Of course, if your url would be https:// or www2 (seen it all...) the regex would break. So this is just a first draft to start working with.
My second idea is, just as yours, explodeing the url. I thought of something like this:
function getSubdomain($url) {
$parts = explode('.', str_replace('http://', '', $url));
if(count($parts) >= 3) {
return $parts[count($parts) - 3];
}
return null;
}
My idea behind this function was, that if an url is splitted by . the subdomain will almost always be the third last entry in the resulting array. The protocol has to be stripped first (see case 3). Of course, this certainly can be done more elegant.
I hope I could give you some ideas.
Try this.
[update] We have a constant defined _SITE_ADDRESS such as www.mysite.com you could use a literal for this.
It works well in our system for what seems like that exact purpose.
public static function getSubDomain()
{
if($_SERVER["SERVER_NAME"] == str_ireplace('http://','',_SITE_ADDRESS)) return ''; //base domain
$host = str_ireplace(array("www.", _SITE_ADDRESS), "", strtolower(trim($_SERVER["HTTP_HOST"])));
$sub = preg_replace('/\..*/', '', $host);
if($sub == $host) return ''; //this is likely an ip address
return $sub;
}
There is an external note on that function but no link, So sorry to any original developer who's code this is based on.
I am trying to make a user submit link box. I've been trying all day and can't seem to get it working.
The goal is to make all of these into example.com... (ie. remove all stuff before the top level domain)
Input is $url =
Their are 4 types of url:
www.example.com...
example.com...
http://www.example.com...
http://example.com...
Everything I make works on 1 or 2 types, but not all 4.
How one can do this?
You can use parse_url for that. For example:
function parse($url) {
$parts = parse_url($url);
if ($parts === false) {
return false;
}
return isset($parts['scheme'])
? $parts['host']
: substr($parts['path'], 0, strcspn($parts['path'], '/'));
}
This will leave the "www." part if it already exists, but it's trivial to cut that out with e.g. str_replace. If the url you give it is seriously malformed, it will return false.
Update (an improved solution):
I realized that the above would not work correctly if you try to trick it hard enough. So instead of whipping myself trying to compensate if it does not have a scheme, I realized that this would be better:
function parse($url) {
$parts = parse_url($url);
if ($parts === false) {
return false;
}
if (!isset($parts['scheme'])) {
$parts = parse_url('http://'.$url);
}
if ($parts === false) {
return false;
}
return $parts['host'];
}
Your input can be
www.example.com
example.com
http://www.example.com
http://example.com
$url_arr = parse_url($url);
echo $url_arr['host'];
output is example.com
there's a few steps you can take to get a clean url.
Firstly you need to make sure there is a protocol to make parse_url work correctly so you can do:
//Make sure it has a protocol
if(substr($url,0,7) != 'http://' || substr($url,0,8) != 'https://')
{
$url = 'http://' . $url;
}
Now we run it through parse_url()
$segments = parse_url($url);
But this is where it get's complicated because the way domain names are constructed is that you can have 1,2,3,4,5,6 .. .domain levels, meaning that you cannot detect the domain name from all urls, you have to have a pre compiled list of tld's to check the last portion of the domain, so you then can extract that leaving the website's domain.
There is a list available here : http://mxr.mozilla.org/mozilla-central/source/netwerk/dns/effective_tld_names.dat?raw=1
But you would be better of parsing this list into mysql and then select the row where the tld matches the left side of the domain string.
Then you order by length and limit to 1, if this is found then you can do something like:
$db_found_tld = 'co.uk';
$domain = 'a.b.c.domain.co.uk';
$domain_name = substr($domain,0 - strlen($db_found_tld));
This would leave a.b.c.domain, so you have removed the tld, now the domain name would be extracted like so:
$parts = explode($domain_name);
$base_domain = $parts[count($parts) - 1];
now you have domain.
this seems very lengthy but I hope now you know that its not easy to get just the domain name without tld or sub domains.