I need to create a small application with a homepage where the user can fill a form with a unique field. The field will be used as the name of a room, and the user redirected to this page. Every other user who enter the same room name will be redirected to the same page, and will be able to chat with users in this room.
My problem is that I can't find a way with silex 2 to make this work.
I created the homepage, and it seems to work. I have a form and can enter the name of the room :
$app->match(
'/',
function (Request $request) use ($app) {
$data = array(
'room' => 'Name of the room',
);
$form = $app['form.factory']->createBuilder(FormType::class, $data)
->add('room', TextType::class)
->getForm();
$form->handleRequest($request);
if ($form->isValid()) {
$data = $form->getData();
$roomName = $data['room'];
//return $app->redirect('/room/' . $roomName);
$subRequest = Request::create($app['url_generator']->generate('/room/' . $roomName), 'GET');
return $app->handle($subRequest, \Symfony\Component\HttpKernel\HttpKernelInterface::SUB_REQUEST, false);
}
return $app['twig']->render('base.twig', array('form' => $form->createView()));
}
)->bind('home');
As you can see, I tried with redirect, and with a subrequest.
But both case don't work, as I receive a 404.
The code wich is suppose to catch the room is :
$app->match(
'/room/{name}',
function ($name) use ($app) {
return $app['twig']->render('room.twig', array('name' => $name));
}
)->bind('room');
Does anyone have an idea on how I could make this work ?
Thank you for reading. Any help will be appreciated.
I finally found the solution.
I had to add a .htaccess file in my web folder. The important part of this file was this, for anyone having the same problem:
<IfModule mod_rewrite.c>
Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [L]
</IfModule>
Related
I have a URL that looks like:
url.com/picture.php?id=51
How would I go about converting that URL to:
picture.php/Some-text-goes-here/51
I think WordPress does the same.
How do I go about making friendly URLs in PHP?
You can essentially do this 2 ways:
The .htaccess route with mod_rewrite
Add a file called .htaccess in your root folder, and add something like this:
RewriteEngine on
RewriteRule ^/?Some-text-goes-here/([0-9]+)$ /picture.php?id=$1
This will tell Apache to enable mod_rewrite for this folder, and if it gets asked a URL matching the regular expression it rewrites it internally to what you want, without the end user seeing it. Easy, but inflexible, so if you need more power:
The PHP route
Put the following in your .htaccess instead: (note the leading slash)
FallbackResource /index.php
This will tell it to run your index.php for all files it cannot normally find in your site. In there you can then for example:
$path = ltrim($_SERVER['REQUEST_URI'], '/'); // Trim leading slash(es)
$elements = explode('/', $path); // Split path on slashes
if(empty($elements[0])) { // No path elements means home
ShowHomepage();
} else switch(array_shift($elements)) // Pop off first item and switch
{
case 'Some-text-goes-here':
ShowPicture($elements); // passes rest of parameters to internal function
break;
case 'more':
...
default:
header('HTTP/1.1 404 Not Found');
Show404Error();
}
This is how big sites and CMS-systems do it, because it allows far more flexibility in parsing URLs, config and database dependent URLs etc. For sporadic usage the hardcoded rewrite rules in .htaccess will do fine though.
If you only want to change the route for picture.php then adding rewrite rule in .htaccess will serve your needs, but, if you want the URL rewriting as in Wordpress then PHP is the way. Here is simple example to begin with.
Folder structure
There are two files that are needed in the root folder, .htaccess and index.php, and it would be good to place the rest of the .php files in separate folder, like inc/.
root/
inc/
.htaccess
index.php
.htaccess
RewriteEngine On
RewriteRule ^inc/.*$ index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php [QSA,L]
This file has four directives:
RewriteEngine - enable the rewriting engine
RewriteRule - deny access to all files in inc/ folder, redirect any call to that folder to index.php
RewriteCond - allow direct access to all other files ( like images, css or scripts )
RewriteRule - redirect anything else to index.php
index.php
Because everything is now redirected to index.php, there will be determined if the url is correct, all parameters are present, and if the type of parameters are correct.
To test the url we need to have a set of rules, and the best tool for that is a regular expression. By using regular expressions we will kill two flies with one blow. Url, to pass this test must have all the required parameters that are tested on allowed characters. Here are some examples of rules.
$rules = array(
'picture' => "/picture/(?'text'[^/]+)/(?'id'\d+)", // '/picture/some-text/51'
'album' => "/album/(?'album'[\w\-]+)", // '/album/album-slug'
'category' => "/category/(?'category'[\w\-]+)", // '/category/category-slug'
'page' => "/page/(?'page'about|contact)", // '/page/about', '/page/contact'
'post' => "/(?'post'[\w\-]+)", // '/post-slug'
'home' => "/" // '/'
);
Next is to prepare the request uri.
$uri = rtrim( dirname($_SERVER["SCRIPT_NAME"]), '/' );
$uri = '/' . trim( str_replace( $uri, '', $_SERVER['REQUEST_URI'] ), '/' );
$uri = urldecode( $uri );
Now that we have the request uri, the final step is to test uri on regular expression rules.
foreach ( $rules as $action => $rule ) {
if ( preg_match( '~^'.$rule.'$~i', $uri, $params ) ) {
/* now you know the action and parameters so you can
* include appropriate template file ( or proceed in some other way )
*/
}
}
Successful match will, since we use named subpatterns in regex, fill the $params array almost the same as PHP fills the $_GET array. However, when using a dynamic url, $_GET array is populated without any checks of the parameters.
/picture/some+text/51
Array
(
[0] => /picture/some text/51
[text] => some text
[1] => some text
[id] => 51
[2] => 51
)
picture.php?text=some+text&id=51
Array
(
[text] => some text
[id] => 51
)
These few lines of code and a basic knowing of regular expressions is enough to start building a solid routing system.
Complete source
define( 'INCLUDE_DIR', dirname( __FILE__ ) . '/inc/' );
$rules = array(
'picture' => "/picture/(?'text'[^/]+)/(?'id'\d+)", // '/picture/some-text/51'
'album' => "/album/(?'album'[\w\-]+)", // '/album/album-slug'
'category' => "/category/(?'category'[\w\-]+)", // '/category/category-slug'
'page' => "/page/(?'page'about|contact)", // '/page/about', '/page/contact'
'post' => "/(?'post'[\w\-]+)", // '/post-slug'
'home' => "/" // '/'
);
$uri = rtrim( dirname($_SERVER["SCRIPT_NAME"]), '/' );
$uri = '/' . trim( str_replace( $uri, '', $_SERVER['REQUEST_URI'] ), '/' );
$uri = urldecode( $uri );
foreach ( $rules as $action => $rule ) {
if ( preg_match( '~^'.$rule.'$~i', $uri, $params ) ) {
/* now you know the action and parameters so you can
* include appropriate template file ( or proceed in some other way )
*/
include( INCLUDE_DIR . $action . '.php' );
// exit to avoid the 404 message
exit();
}
}
// nothing is found so handle the 404 error
include( INCLUDE_DIR . '404.php' );
this is an .htaccess file that forward almost all to index.php
# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteCond %{REQUEST_URI} !-l
RewriteCond %{REQUEST_FILENAME} !\.(ico|css|png|jpg|gif|js)$ [NC]
# otherwise forward it to index.php
RewriteRule . index.php
then is up to you parse $_SERVER["REQUEST_URI"] and route to picture.php or whatever
PHP is not what you are looking for, check out mod_rewrite
Although already answered, and author's intent is to create a front controller type app but I am posting literal rule for problem asked. if someone having the problem for same.
RewriteEngine On
RewriteRule ^([^/]+)/([^/]+)/([\d]+)$ $1?id=$3 [L]
Above should work for url picture.php/Some-text-goes-here/51. without using a index.php as a redirect app.
I'm trying to make my url look like this mysite.com/contact unfortunately it shows a 404 error on the contact page. the login page works tho. the file is located in protected/view/site/contact.php
'urlManager'=>array(
'urlFormat'=>'path',
//'urlSuffix'=>'.html',
'rules'=>array(
'<view:(about|terms|faq|privacy)>' => 'site/page',
'<action:(contact|login)>' => 'site/<action>',
'<action:(registration|create)>' => 'user/<action>',
'<controller:\w+>/<id:\d+>'=>'<controller>/view',
'<controller:\w+>/<action:\w+>/<id:\d+>'=>'<controller>/<action>',
'<controller:\w+>/<action:\w+>'=>'<controller>/<action>',
),
'showScriptName' => false,
),
make sure you have this in your SiteController.php
/**
* Displays the contact page
*/
public function actionContact()
{
$model=new ContactForm;
if(isset($_POST['ContactForm']))
{
$model->attributes=$_POST['ContactForm'];
if($model->validate())
{
$name='=?UTF-8?B?'.base64_encode($model->name).'?=';
$subject='=?UTF-8?B?'.base64_encode($model->subject).'?=';
$headers="From: $name <{$model->email}>\r\n".
"Reply-To: {$model->email}\r\n".
"MIME-Version: 1.0\r\n".
"Content-Type: text/plain; charset=UTF-8";
mail(Yii::app()->params['adminEmail'],$subject,$model->body,$headers);
Yii::app()->user->setFlash('contact','Thank you for contacting us. We will respond to you as soon as possible.');
$this->refresh();
}
}
$this->render('contact',array('model'=>$model));
}
I render mine like so
'contact' => array('site/contact'),
RewriteEngine on
# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# otherwise forward it to index.php
RewriteRule . index.php
Create .htaccess in your project folder with above code
I have designed a web application, It works for two different users say user1 and user2, and both of the users need the view in different languages.
I have studied about yii:t() but by that method we have to define language in main.config, which set the same language for both users.
How can I translate my view in different languages for both users?
I hope this can help you:
you need to edit urlmanager.php in your components, if there is no file, you need to create one.
Check this url: Multilingual
Thanks.
Put this in your SiteController.php:
public function actionChangeLocale($locale) {
// (OPTIONAL) if is registered user (not guest), save preferred locale in database
if (!Yii::app()->user->isGuest) {
// Update user settings
$uid = Yii::app()->user->id;
User::model()->updateByPk($uid, array('locale' => $locale));
}
// change locale
Yii::app()->user->setState('_locale', $locale);
// redirect to previous page, in the new locale
if(isset($_SERVER["HTTP_REFERER"]))
$referrer = $_SERVER["HTTP_REFERER"];
else
$referrer = Yii::app()->getBaseUrl(true) . '/';
$this->redirect($referrer);
}
Edit your main.php config url manager rules:
'urlManager' => array(
'urlFormat' => 'path',
'showScriptName' => false,
'caseSensitive' => false,
'rules' => array(
'lang/<id:\w+>' => 'site/changeLocale',
To change locale, create a link to point user to desired locale:
http://www.mysite.com/myapp/lang/en
http://www.mysite.com/myapp/lang/zh
http://www.mysite.com/myapp/lang/ja
http://www.mysite.com/myapp/lang/in
...
If you saved the logged-in user's preferred locale in database, add this to SiteController.php Login action:
$uid = Yii::app()->user->id;
$user = User::model()->findbypk($uid);
$userLocale = isset($user->locale) ? $model->locale : Yii::app()->language;
Yii::app()->user->setState('_locale', $userLocale);
Above usage is for those using htaccess rewrite. Make sure base .htaccess file is:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)/$ http://%{HTTP_HOST}/$1 [R=301,L] # Remove trailing slash
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php
Related Articles:
http://www.yiiframework.com/doc/guide/1.1/en/topics.i18n
Related Modules:
http://www.yiiframework.com/extension/ei18n/
I use this rule in our Apache webserver:
RewriteCond %{REQUEST_FILENAME} !-*\.jpg$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?req=$1 [QSA]
Can you help me, how can I migrate this to 1.4.20 lighttpd+url_rewrite-ifnotfile?
I found similar here and here, but I can't use it.
As per my response here please use the following: (i've amended the rewrite to fit your request):
url.rewrite-if-not-file = (
"^(.*)$" => "/index.php?req=$1"
)
Judging by the apache setup, your best option in this case would be to upgrade to 1.4.24+ otherwise these rewrite rules will start to get complex as you will need to direct to every file that exists. Something like this for example:
url.rewrite = (
"^/index.php$" => "/index.php",
"^/page1.php$" => "/page1.php",
"^/page2.php$" => "/page2.php",
.
.
.
"^/pageN.php$" => "/page.php",
.
.
.
"^/uploads/uploadedfile.pdf$" => "/uploads/uploadedfile.pdf",
.
.
.
"(.*)" => "/index.php?req=$1"
)
If your application doesn't have many files the user needs to access directly you could solve this problem as above. However once you start dealing with uploaded content or anything dynamic you will run into problems.
Personally i've always avoided such problems in the past by adding any content i don't want lighty to rewrite into a sub directory then you can use a wildcard (this may or may not work in your case) like so :
url.rewrite = (
"^/content/(.*)$" => "/content/$1",
"(.*)" => "/index.php?req=$1"
)
If neither of the above is any use, You could use a php script to serve all your dynamic content, but this comes with its own set of problems and inflexibility. For example:
<?php
$fullPath = '/path/to/files/' . $_GET['filename'];
if( file_exists($fullPath) ){
// Parse Info / Get Extension
$fsize = filesize($fullPath);
$path_parts = pathinfo($fullPath);
$ext = strtolower($path_parts["extension"]);
// Determine Content Type
switch ($ext) {
case "pdf": $ctype="application/pdf"; break;
case "exe": $ctype="application/octet-stream"; break;
case "zip": $ctype="application/zip"; break;
case "doc": $ctype="application/msword"; break;
case "xls": $ctype="application/vnd.ms-excel"; break;
case "ppt": $ctype="application/vnd.ms-powerpoint"; break;
case "gif": $ctype="image/gif"; break;
case "png": $ctype="image/png"; break;
case "jpeg":
case "jpg": $ctype="image/jpg"; break;
default: $ctype="application/force-download";
}
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false);
header("Content-Type: $ctype");
header("Content-Disposition: attachment; filename=\"".basename($fullPath)."\";" );
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".$fsize);
} else
exit('File Not Found');
?>
Hope that helps
UPD:
Solved. The problem was because we're using nginx as a frontend. So nginx doesn't pass the HTTP_HOST to apache.
Hi there!
I'm having a problem with getting subdomain parameter in my base controller on a production server while on the localhost it's ok. other parameters from url like controller, action returned as they should.
this returns null on production:
$agencyName = (string) $this->_getParam('agency');
no changes made to .htaccess:
RewriteEngine On
RewriteRule ^main - [L,NC]
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ index.php [NC,L]
and here's my vhost settings:
<VirtualHost *:8080>
ServerName agencies.domain.com
ServerAlias *.agencies.domain.com
ErrorLog /var/log/apache2/agencies.domain_errors.log
DocumentRoot /var/www/agencies.domain.com/public/
<Directory "/var/www/agencies.domain.com/public">
Options -Indexes FollowSymLinks Includes
DirectoryIndex index.shtml index.php
AllowOverride All
# Controls who can get stuff from this server.
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
Does anybody knows why it happenes?
upd:
routers in Bootstrap
public function run()
{
$frontController = Zend_Controller_Front::getInstance();
$router = $frontController->getRouter();
$plainPathRoute = new Zend_Controller_Router_Route(
':module/:controller/:action/*',
array(
'module' => 'default',
'controller' => 'index',
'action' => 'index',
)
);
$config = $this->getOptions();
$hostnameRoute = new Zend_Controller_Router_Route_Hostname(
':agency.' . $config['siteUri'],
NULL,
array(
'agency' => '([a-z0-9]+)'
)
);
$router->addRoute('subdomain', $hostnameRoute->chain($plainPathRoute));
parent::run();
}
and yes, I do have $config['siteUri'] defined and i also tried using :agency.domain.com getting the same problem again
Use the following :
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
protected function _initRoute()
{
$this->bootstrap('FrontController');
$router = $this->getResource('FrontController')->getRouter();
$router->removeDefaultRoutes();
$plainPathRoute = new Zend_Controller_Router_Route(
':module/:controller/:action/*',
array(
'module' => 'default',
'controller' => 'index',
'action' => 'index',
)
);
$router->addRoute('default', $plainPathRoute);
$config = $this->getOptions();
$hostnameRoute = new Zend_Controller_Router_Route_Hostname(
':agency.' . $config['siteUri'],
NULL,
array(
'agency' => '([a-z0-9]+)'
)
);
$router->addRoute('subdomain', $hostnameRoute->chain($plainPathRoute));
}
}
If you provide a valid subdomain (ie. only consisting of characters a-z0-9), it will be passed in agency, if not then agency will not be set. (At least it works for me using ZF 1.11.3 :p).
Solved. The problem was because we're using nginx as a frontend. So nginx doesn't pass the HTTP_HOST to apache.