I am new to php, new to mvc, new to yii, and new to url-rewriting. So, I am sorry, if I am asking something very basic.
I have hide the index.php (from the htaccess method discussed in yii forums)
In my urlmanager, I have this,
'urlFormat'=>'path',
'rules'=>array(
'<controller:\w+>/<id:\d+>'=>'view',
'<controller:\w+>/<action:\w+>/<id:\d+>'=>'<controller>/<action>',
'<controller:\w+>/<action:\w+>'=>'<controller>/<action>'
),
'showScriptName'=>false,
I have 3 files in view/site folder.
'journey',
'invite',
'linkedin'
Now, my home page should redirect to 'journey' action (i.e. should open the 'site/journey.php')
So, I guess, this would be
'/' => 'site/journey'
It works too.
Now, I want 'journey/invite' should invoke the 'invite' action i.e. should open 'site/invite.php'
And, 'journey/linkedin' should invoke the 'linkedin' action i.e. 'site/linkedin.php'.
but,
'journey/invite' => 'site/invite',
'journey/linkedin' => 'site/linkedin'
is not working.
Also, can someone help me understand this,
<controller:\w+>/<id:\d+>
i.e. what is controller in url and what does 'w+' mean ?
A reference to guide will help too.
Edited after bool.dev's suggestion:
Changed the code , as you said (I tried that earlier too, removing all default rules).
Now my url manager is like,
'/' => 'site/journey',
'journey/invite' => 'site/invite',
'journey/linkedin' => 'site/linkedin',
'<controller:\w+>/<id:\d+>'=>'view',
'<controller:\w+>/<action:\w+>/<id:\d+>'=>'<controller>/<action>',
'<controller:\w+>/<action:\w+>'=>'<controller>/<action>',
But it throws an error
"Warning: require_once(): open_basedir restriction in effect.
File(/var/xyz.com/../yii/framework/yii.php) is not within the allowed
path(s):
(/usr/share/php:/usr/share/pear:/usr/share/php/libzend-framework-php:/var/*/tmp:/var/xyz.com)
in /var/xyz.com/journey.php on line 12 Warning:
require_once(/var/xyz.com/../yii/framework/yii.php): failed to open
stream: Operation not permitted in /var/xyz.com/journey.php on line 12
Fatal error: require_once(): Failed opening required
'/var/xyz.com/../yii/framework/yii.php'
(include_path='.:/usr/share/php:/usr/share/php/libzend-framework-php')
in /var/xyz.com/journey.php on line 12'
when I do xyz.com/journey/invite or even xyz.com/journey
Edit:
It was a permission issue, #bool.dev's suggestion to put specific rules on top worked :)
These two:
'journey/invite' => 'site/invite',
'journey/linkedin' => 'site/linkedin'
are not working because the url is being matched by a previous rule:
'<controller:\w+>/<action:\w+>'=>'<controller>/<action>'
To prevent that from happening just make sure that rule is mentioned last, before any specific(i.e not matched by regular expressions) rewrites, so your rules can look somewhat like this :
'journey/invite' => 'site/invite',
'journey/linkedin' => 'site/linkedin',
'<controller:\w+>/<action:\w+>'=>'<controller>/<action>'
This : \w+ means match any string with one or more occurrences of any “word” character (a-z 0-9 _) and \d+ means match any string with one or more occurrences of any digits (0-9) . Check out php regex.
Edit
Hadn't read your question thoroughly before, the controller in the rule is simply a name for the matched expression, so you could have had '<contr:\w+>/<act:\w+>'=>'<contr>/<act>'.
Edit2
After reading your edited question with the rules array, afaik you could use ''=>'site/journey' instead of '/'=>'site/journey'.
Related
I'm trying to use trans_choice() to simply format a string to either "comment" or "comments" depending on the number of them. It should be fairly straightforward, like this.
In my view:
{{ trans_choice('posts.num comments', $post->comments->count()) }}
In the posts localisation file:
return [
'num comments' => 'comment|comments',
];
However, every single one returns just "comment". And if I go into tinker:
>>> trans_choice('posts.num comments', 1);
=> "comment"
>>> trans_choice('posts.num comments', 2);
=> "comment"
>>> trans_choice('posts.num comments', 4);
=> "comment"
I'm sure I'm missing something obvious but it looks to me as if I've followed the documentation perfectly.
Edit: The problem seems to lie somewhere in Symfony\Component\Translation\MessageSelector, but I haven't yet figured the cause out.
Finally found the answer. Apparently, if the locale isn't available in Symfony's PluralizationRules class, the translator defaults to the first pick - that is, always index zero. By changing the locale name (I didn't even realise it was misspelled...), I got it working.
I know this post is old, but I ran into this issue, so hoping my solution helps someone if Joel's solution doesn't work.
I'm working with Laravel 7.x, and am using localization on a project for differences between US an CA English, (i.e. Center vs. Centre).
I have my localization folders set up with en being the default folder and en_ca as the Canadian English folder, where en is also the fallback language.
When using trans_choice() I found I had to specifically set the the counts in my translation strings, otherwise the translation engine would just spit back the singular when viewing pages in the non-default locale.
Once the changes were made, trans_choice() worked, no matter what locale was set.
For example, wherever I had:
'general.posts' => 'Posts|Posts',
I changed it to:
'general.posts' => '{1} Post|[2,*] Posts',
After that everything worked.
If you're brazilian that's probably your answer!
I just had the same problem and found out it was because of my locale option (and lang folder).
Instead of 'br' we must use 'xbr' in order to Symphony find it in PluralizationRules (vendor/symphony/translation/PluralizationRules).
In that file there's an array with all languages available, so may check it out.
P.S. I'm using Laravel 5.3
I'm very new to Watir.
I have a bit of Ruby/Watir code that is supposed to detect if an element, exists, and if so, click it, if not, click a different element. Both elements, show up, every time. Unfortunately nothing I've tried works.
if browser.contains_text("/media/images/icons/reviewertools/editreview.jpg")
then browser.image(:src => "/media/images/icons/reviewertools/editreview.jpg").click
else browser.image(:src => "/media/images/icons/reviewertools/savereview.jpg").click
end
This eventually fails with "Unable to locate element, using {:src=>"/media/images/icons/reviewertools/savereview.jpg"} (Watir::Exception::UnknownObjectException)"
It should have clicked /editreview.jpg, which was visible.
I have also tried:
if browser.image("/media/images/icons/reviewertools/savereview.jpg").exists
then browser.image(:src => "/media/images/icons/reviewertools/savereview.jpg").click
as well as:
if browser.image("/media/images/icons/reviewertools/savereview.jpg").exists?
Note that NONE of these cases detect the element, or failing to do that, execute the else clause.
Please, if you respond, provide specific code examples for your suggestions.
There are only methods "exist?" and "exists?". So "exist" won't work. Consult here.
Can you try to identify existence of a different element, such as a link. Does it work for you? There shouldn be no exception. Watir needs to return False in this case.
You need to use the same syntax with both the click and the exists? methods. This has also been pointed out by Kat and Chuck and Kinofrost.
if browser.image(:src => "/media/images/icons/reviewertools/editreview.jpg").exists?
then browser.image(:src => "/media/images/icons/reviewertools/editreview.jpg").click
else browser.image(:src => "/media/images/icons/reviewertools/savereview.jpg").click
end
I'd recommend checking the DOM to double check the src for your image matches what you're putting. Press F12 in IE8, or use whatever tool is relevant to your browser. You could try using IRB to connect to the browser and try and find the image.
If these fail then I'd try locating the image another way. If the image is in a form this can cause problems and you'll have to locate the form before the image.
Or try another way to locate it, just to make sure that it's possible.
browser.image(:index => 3).click
browser.image(:id => 'an_image').click
browser.div(:id => 'image_container').image(:index => 2).click
You can use this link to see what ways you can identify an image, and don't forget that you can use more than one identifier at a time, eg. (:class => /regexofaclass/, :index => 2)
There's nothing wrong with your code as it is (apart from the ? at the end of "exists", and the last line which doesn't contain what you're looking for).
Presuming that this thing really is an 'image' as defined by it's HTML tag, your attempt to identify if the object is there is failing because
you are not using the right method, in Ruby, methods that return a bool end in a question mark
it's not text,
and in the other attempt you provided only a 'what' and not a how, and still used the wrong method.
try this
if browser.image(:src, "/media/images/icons/reviewertools/savereview.jpg").exists?
then browser.image(:src, "/media/images/icons/reviewertools/savereview.jpg").click
Otherwise have a good look at the HTML, are you actually looking at a 'button' perhaps?
I have an address on my site like so:
http://www.example.com/lookup?q=http%3A%2F%2Fgigaom.com%2F2010%2F10%2F10%2Fangry-birds-for-windows7-phone-dont-count-on-it%2F
In this example, the dot in the 'gigaom.com' part of the query string is screwing with lighttpd and my rewrite rules. I get a 404 with the dot in, no 404 if I take the dot out. My rewrite rules are below. In case it makes a difference, I'm using symfony 1.4.
If anyone could shed some light on this problem it would be much appreciated!
url.rewrite-once = (
"^/(.*\..+)$" => "$0",
"^/(.*)\.(.*)" => "/index.php",
"^/([^.]+)$" => "/index.php/$1",
"^/$" => "/index.php"
)
For anyone having trouble with lighttpd and symfony (I know you're out there, cause there are plenty of unresolved threads on the issue) I ended up solving and answering it below.
OK so after much debugging with the help of:
debug.log-request-handling = "enable"
^^ This is a lifesaver for when you're trying to debug rewrite rules in lighttpd! (it logged everything for me to /var/log/lighttpd/error.log)
I've figured it out. For all those people having trouble getting symfony to work with lighttpd (including the dot problem!) here's a working set of rules:
url.rewrite-once = (
"^/(js|images|uploads|css|sf)/(.*)" => "$0", # we want to load these assets as is, without index.php
"^/[a-zA-Z_-]+\.(html|txt|ico)$" => "$0", # for any static .html files you might be calling in your web root, we don't want to put the index.php controller in front of them
"^/sf[A-z]+Plugin.*" => "$0", # don't want to mess with plugin routes
"^/([a-z_]+)\.php(.*)\.(.*)$" => "/$1.php$2.$3", # same concept as rules below, except for other applications/environments (backend.php, backend_dev.php, etc)
"^/([a-z_]+)\.php([^.]*)$" => "/$1.php$2", # see comment right above this one
"^/(.*)\.(.*)$" => "/index.php/$1.$2", # handle query strings and the dot problem!
"^/([^.]+)$" => "/index.php/$1", # general requests
"^/$" => "/index.php" # the home page
)
If anyone has more trouble, post here. Thanks!
I am using PHP, MySQL, and .htaccess file for rewriting rules. Just sharing so others can also benefit.
My previous rule:
RewriteRule ^([^/\.]+)/([^/\.]+).html$ detail.php?name=$1&id=$2 [L]
It was working with this result: http://www.sitecliff.com/Yahoo-UK/4.html
I wanted the website name instead of the title in the url. After surfing the net, I figured out that the dot is causing the problem as you mentioned above.
"^/(.*)\.(.*)$" => "/index.php/$1.$2", # handle query strings and the dot problem!
So I changed the rule to:
RewriteRule ^([^/]+)$ detail.php?url=$1 [L]
After this, I got my desired result: http://www.sitecliff.com/yahoo.com
I'm looping over a series of URLs and want to clean them up. I have the following code:
# Parse url to remove http, path and check format
o_url = URI.parse(node.attributes['href'])
# Remove www
new_url = o_url.host.gsub('www.', '').strip
How can I extend this to remove the subdomains that exist in some URLs?
I just wrote a library to do this called Domainatrix. You can find it here: http://github.com/pauldix/domainatrix
require 'rubygems'
require 'domainatrix'
url = Domainatrix.parse("http://www.pauldix.net")
url.public_suffix # => "net"
url.domain # => "pauldix"
url.canonical # => "net.pauldix"
url = Domainatrix.parse("http://foo.bar.pauldix.co.uk/asdf.html?q=arg")
url.public_suffix # => "co.uk"
url.domain # => "pauldix"
url.subdomain # => "foo.bar"
url.path # => "/asdf.html?q=arg"
url.canonical # => "uk.co.pauldix.bar.foo/asdf.html?q=arg"
This is a tricky issue. Some top-level domains do not accept registrations at the second level.
Compare example.com and example.co.uk. If you would simply strip everything except the last two domains, you would end up with example.com, and co.uk, which can never be the intention.
Firefox solves this by filtering by effective top-level domain, and they maintain a list of all these domains. More information at publicsuffix.org.
You can use this list filter out everything except the domain right next to the effective TLD. I don't know of any Ruby library that does this, but it would be a great idea to release one!
Update: there are C, Perl and PHP libraries that do this. Given the C version, you could create a Ruby extension. Alternatively, you could port the code to Ruby.
For posterity, here's an update from Oct 2014:
I was looking for a more up-to-date dependency to rely on and found the public_suffix gem (RubyGems) (GitHub). It's being actively maintained and handles all the top-level domain and nested-subdomain issues by maintaining a list of the known public suffixes.
In combination with URI.parse for stripping protocol and paths, it works really well:
❯❯❯ 2.1.2 ❯ PublicSuffix.parse(URI.parse('https://subdomain.google.co.uk/path/on/path').host).domain
=> "google.co.uk"
The regular expression you'll need here can be a bit tricky, because, hostnames can be infinitely complex -- you could have multiple subdomains (ie. foo.bar.baz.com), or the top level domain (TLD) can have multiple parts (ie. www.baz.co.uk).
Ready for a complex regular expression? :)
re = /^(?:(?>[a-z0-9-]*\.)+?|)([a-z0-9-]+\.(?>[a-z]*(?>\.[a-z]{2})?))$/i
new_url = o_url.host.gsub(re, '\1').strip
Let's break this into two sections. ^(?:(?>[a-z0-9-]*\.)+?|) will collect subdomains, by matching one or more groups of characters followed by a dot (greedily, so that all subdomains are matched here). The empty alternation is needed in the case of no subdomain (such as foo.com). ([a-z0-9-]+\.(?>[a-z]*(?>\.[a-z]{2})?))$ will collect the actual hostname and the TLD. It allows either for a one-part TLD (like .info, .com or .museum), or a two part TLD where the second part is two characters (like .oh.us or .org.uk).
I tested this expression on the following samples:
foo.com => foo.com
www.foo.com => foo.com
bar.foo.com => foo.com
www.foo.ca => foo.ca
www.foo.co.uk => foo.co.uk
a.b.c.d.e.foo.com => foo.com
a.b.c.d.e.foo.co.uk => foo.co.uk
Note that this regex will not properly match hostnames that have more than two "parts" to the TLD!
Something like:
def remove_subdomain(host)
# Not complete. Add all root domain to regexp
host.sub(/.*?([^.]+(\.com|\.co\.uk|\.uk|\.nl))$/, "\\1")
end
puts remove_subdomain("www.example.com") # -> example.com
puts remove_subdomain("www.company.co.uk") # -> company.co.uk
puts remove_subdomain("www.sub.domain.nl") # -> domain.nl
You still need to add all (root) domains you consider root domain. So '.uk' might be the root domain, but you probably want to keep the host just before the '.co.uk' part.
Detecting the subdomain of a URL is non-trivial to do in a general sense - it's easy if you just consider the basic ones, but once you get into international territory this becomes tricky.
Edit: Consider stuff like http://mylocalschool.k12.oh.us et al.
Why not just strip the .com or .co.uk and then split on '.' and get the last element?
some_url.host.sub(/(\.co\.uk|\.[^.]*)$/).split('.')[-1] + $1
Have to say it feels hacky. Are there any other domains like .co.uk?
I've wrestled with this a lot in writing various and sundry crawlers and scrapers over the years. My favorite gem for solving this is FuzzyUrl by Pete Gamache: https://github.com/gamache/fuzzyurl . Its available for Ruby, JavaScript and Elixir.
STILL NOT RESOLVED :( [Feb 11th]
I have a large text file full of random data and want to pull out all the email addresses from it.
I would like to do this in Ruby, with pseudo code like this:
monster_data_string = "asfsfsdfsdfsf sfda **joe#example.com** sdfdsf"
monster_data_string.match(EMAIL_REGEX)
Does anyone know what Ruby email regular expression I would use to accomplish this?
Please keep in mind that I'm looking for a Ruby answer to this. I have already tried numerous regex found by googling but most of them cause Ruby runtime errors stating that characters like "+" and "" are invalid/unrecognized.*
What I have already tried is:
monster_data_string.match(/^([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})$/i)
but I receive Ruby errors stating that "+" is an invalid character
Thanks in advance
Watch this...
f = File.open("content.txt")
content = f.read
r = Regexp.new(/\b[a-zA-Z0-9._%+-]+#[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}\b/)
emails = content.scan(r).uniq
puts YAML.dump(emails)
If you're getting an error message about + or * being invalid in regexes, you're doing something very wrong. This is a valid regex in Ruby, although it's not the one you want:
/^([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
For one thing, you don't want to anchor the regex to the start and end of lines (^ and $) if you're trying to pluck the addresses from "random" text. But once you've gotten rid of the anchors, your regex will match **joe#example.com in your test string, which I presume you don't want. This regex from Regular-Expressions.info does a better job, but read that page for tips on tweaking it to meet your particular needs.
/\b[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}\b/i
Finally (and you may already know this), you won't want to use the match() method because that will only find the first match. Try scan() instead.
Given that it is not possible to parse every valid email address using a regexp you are left with two choices:
Make a regexp that matches as many valid email addresses as possible and live with the the fact that some valid but rarely used forms of email address might get overlooked.
or
Make a regexp that Matches anything that "might be" an email address and then live with the false positives
I use the second approach to weed out obviously wrong email addresses when validating user sign up email addresses on a web page
Gleaned from Ruby Cookbook which has a very good section on email address validation:
valid = '[^ #]+'
/^#{valid}##{valid}\.#{valid}/
Apparently there is a 6343 character Perl regexp written by Paul Warren that does a very good job and also works in Ruby, but even that is not foolproof (I think it might also have some performance implications).
What kind of runtime error messages are you gettting? Is it regarding the regexps as invalid, or is it breaking due to the target string being too large?
To try and help you get there (though not very elegantly, I admit):
I think the start and end anchors (^ and $) aren't helping. You may also want to filter the asterisks?:
irb(main):001:0> mds = "asfsfsdfsdfsf sfda **joe#example.com** sdfdsf"
=> "asfsfsdfsdfsf sfda **joe#example.com** sdfdsf"
irb(main):003:0> mds.match(/^([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})$/i)
=> nil
irb(main):004:0> mds.match(/([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})/i)
=> #<MatchData "**joe#example.com" 1:"**joe" 2:"example.com">
irb(main):005:0> mds.match(/([^#\s*]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})/i)
=> #<MatchData "joe#example.com" 1:"joe" 2:"example.com">
Even better,
require 'yaml'
content = "asfsfsdfsdfsf sfda **joe#example.com.au** sdfdsf cool_me#example.com.fr"
r = Regexp.new(/\b([a-zA-Z0-9._%+-]+)#([a-zA-Z0-9.-]+?)(\.[a-zA-Z.]*)\b/)
emails = content.scan(r).uniq
puts YAML.dump(emails)
will give you
---
- - joe
- example
- .com.au
- - cool_me
- example
- .com.au