So basically, I have two fast questions about kohana urls.
1) With default .htaccess that comes with Kohana, after loading another view, it add's .php to index file. So, for example if I load product view, it looks something like this - http://mysite.com/index.php/products , but I would love it to look http://mysite.com/index/products .
.htaccess code -
# Turn on URL rewriting
RewriteEngine On
# Installation directory
RewriteBase /
# Protect hidden files from being viewed
<Files .*>
Order Deny,Allow
Deny From All
</Files>
# Protect application and system files from being viewed
RewriteRule ^(?:application|modules|system)\b.* index.php/$0 [L]
# Allow any files or directories that exist to be displayed directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Rewrite all other URLs to index.php/URL
RewriteRule .* index.php/$0 [PT]
2) I have two controlles - home and products. Home is default page, but when I load products page, as described above, it shows without design. Both page layouts are same (files are different, I just copied, and I'm testing if it's working).
Controller code -
<?php defined('SYSPATH') or die('No direct script access.');
class Controller_Records extends Controller {
public function action_index()
{
$records_view = View::factory('products');
$records = $records_view->render();
$this->response->body($records);
}
}
It loads just a plane html code, I'm not sure if I'm really doing it correctly.
I really hope you will help me find out solution for this, since I checked some Kohana tutorials and it seems I'm doing it fine, also in documentation it's the same thing. I've came to Kohana from CodeIgniter, which was a little bit bigger documentation, and easier to understood, but as far as I found out, many programmers say that Kohana are alot better than CodeIgniter.
Thank you very much for reading this ;)!
2) you should setup your template controller, try this:
Kohana template $content variable shows nothing
And then extends Records from template controller and bind content variable to the view and echo content in template file.
And for the first question, I'd simply advice you to set your index_file to false in init method in bootstrap.php and create index controller if you need it so much.
Related
I am attempting to implement an oembed provider using the Silverstripe framework but have come across an issue.
I have a controller routed from the url /omebed.json and it works fine if I call something like /omebed.json?mediaurl=mymovie.mp4.
However the Oembed standard states it should be /omebed.json?url=mymovie.mp4
But Silverstripe internally checks the $_GET['url'] variable and will attempt to route to that page/controller.
So SilverStripe is trying to route to /mymovie.mp4 skipping my controller and hitting the ErrorPage_Controller creating a 404.
I'm thinking im going to have to extend the ErrorPage_Controller and rejig it if the url is oembed.json, but this seems a little hackish.
Any suggestions?
Cheers
Extending on #Stephen's answer, here is a way to get around that issue without duplicating main.php and without modifying it directly.
What I did was create a _ss_environment.php file which is added early on in the loading process of Silverstripe.
_ss_environment.php
global $url;
$url = $_GET['raw_url'];
if (isset($_GET['url']))
{
unset($_GET['url']);
}
// IIS includes get variables in url
$i = strpos($url, '?');
if($i !== false)
{
$url = substr($url, 0, $i);
}
.htaccess
RewriteCond %{REQUEST_URI} ^(.*)$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !\.php$
RewriteRule .* framework/main.php?raw_url=%1 [QSA]
So here is what is happening:
The .htaccess is now using raw_url instead of url
_ss_environment.php is being called early in the loading process, setting the global $url variable that main.php normally sets. This is set with raw_url rather than url.
To prevent main.php to just override it again when it sees your url query string parameter, it is unset (Silverstripe seems to reset this later as far as my test is concerned).
Lastly is a little block of code that main.php would normally run if $_GET['url'] is set, copied as-is for apparent support in IIS. (If you don't use IIS, you likely won't need it.)
This has a few benefits:
No update to main.php allows upgrading Silverstripe slightly easier in the future
Runs the minimal amount of code needed to "trick" Silverstripe into thinking it is running normally.
The one obvious drawback to any solution for changing away form the url query string parameter is if anything looks at the parameter directly. With how Silverstripe works, it is more likely that code uses the $url global variable or the Director class rather than looking at the query string for the current URL.
I tested this on a 3.1 site by doing the changes I mentioned and:
Creating a controller called TestController
In the init function of the controller, I am running the following:
var_dump($_GET['url']);
var_dump($this->getRequest()->getVars());
Visited /TestController?url=abc123, saw the value of both dumps have "abc123" as the value for the URL parameter.
Navigated to a few other custom pages on the site to make sure they were still working (no issues that I saw)
Unfortunately, I haven't been able to find documentation for the order of inclusion in regards to _config.php and _ss_environment.php. However, after browsing through the code, I have worked out it is this:
main.php runs, first main task is to require core/Constants.php
Constants.php's first task is to search for _ss_environment.php in the base folder and potential parent folders. If it finds it, it will be included.
Going back to main.php (and after the $_GET['url'] check is done in main.php), it will start an ErrorControlChain which it internally does another require for core/Core.php
Inside Core.php, it performs calls for the config manifest
ConfigManifest.php exposes the functions to actually add _config.php files and for them to be required.
I could probably go on however I think this gives a pretty good picture of what is going on. I don't really see a way around not using the _ss_environment.php file. Nothing else gets included early enough that you can hook into without modifying core code.
I had a quick play with this the other day. And looking at what main.php does it might be best to hack away at it rather than ErrorPage_controller.
For startes SS's default .htaccess file does this:
<IfModule mod_rewrite.c>
SetEnv HTTP_MOD_REWRITE On
RewriteEngine On
# RewriteBase /silverstripe
RewriteCond %{REQUEST_URI} ^(.*)$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* framework/main.php?url=%1&%{QUERY_STRING} [L]
</IfModule>
Note the ?url changing that to something else and then changing main.php's usage as well may/should help or will cause a heap of extra errors and sadness.
To avoid hacking the core/framework, you could change the .htaccess to target a copy of main.php in mysite (with appropriate include changes).
I have a userprofile system in which a dynamic page (profile.php) changes as the id of user changes..
For eg. profile.php?id=2 displays the profile of user having id=2.. But i want the address to be as user/user_name.php. So providing each user a unique profile-page address..
Is it possible without creating a seperate page for each user?
Thnx
Ok, let´s talk about apache´s mod_rewrite. Basically what people usually do is that they setup one php page eg. index.php and redirect all the requests there (except those that request existent files and directories) and index.php then routes these requests to proper files/presenters/controllers, etc.
I´m gonna show you a very simple example how can this be done, it´s just to give you the idea how it works in basics and ofc there are better ways to do this (for example take a look at some framework).
So here is the very simple .htaccess file, placed in the same directory as index.php:
<IfModule mod_rewrite.c>
RewriteEngine On
# prevents files starting with dot to be viewed by browser
RewriteRule /\.|^\. - [F]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php?query=$1 [L]
</IfModule>
And here is the index.php:
<?php
$request = explode("/", $_GET["query"]);
// now you have your request in an array and you can do something with it
// like include proper files, passing it to your application class, whatever.
// for the sake of simplicity let me just show you the example of including a file
// based on the first query item
// first check it´s some file we want to be included
$pages = array("page1", "page2", "page3");
if(!in_array($request[0], $pages)) $request[0] = $pages[0];
include "pages/".$request[0];
But I highly recommend you not to reinvent the wheel and take a look at some existing php framework. You´ll find out that it saves you a lot of work, once you learn how to use it ofc. To mention some - Zend Framework, Symfony and the one I´m using - Nette Framework. There are many more, so choose whatever suits your needs.
I am trying to create my own PHP MVC framework for learning purpose. I have the following directory structure:
localhost/mvc:
.htaccess
index.php
application
controller
model
view
config/
routes.php
error/
error.php
Inside application/config/routes.php I have the following code:
$route['default_controller'] = "MyController";
Now what I am trying to achieve is when any user visits my root directory using browser I want to get the value of $route['default_controller'] from route.php file and load the php class inside the folder controller that matches with the value .
And also if any user tries to visit my application using an url like this: localhost/mvc/cars, I want to search the class name cars inside my controller folder and load it. In case there is no class called cars then I want to take the user to error/error.php
I guess to achieve the above targets I have to work with the .htaccess file in the root directory. Could you please tell me what to code there? If there is any other way to achieve this please suggest me.
I have tried to use the .htaccess codes from here, but its not working for me
It all sounds well and good from a buzzword standpoint, but to me this is all a little confusing because I see PHP's model as an MVC model already. It's providing the API for you to program with and deliver your content to your web server Apache and your database (something like MySQL). It translates the code(model) for you into HTML(view) ... provided that's what you intend, and you're supplying code as the user input (control). Getting too wrapped up in the terminologies gets a little distracting and can lead to chaos when you bring someone in to collaborate who isn't familiar with your conventions. (This should probably never be used in a production environment for a paying gig.)
I can tell you that on the page that you referenced they guy's .htaccess file needs a little work. The [L] flag tells mod_rewrite that this is the last command to process when the rule returns true. So you would either need to do this:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule ^(.*)$ public/$1 [L]
</IfModule>
Or the following... but he was using a passthru flag which means that he is implying there are other things that could be processed prior to the last rule (eg. might be rewrite_base or alias), but that's not actually the case with his .htaccess file since it's a little bare. So this code would work similar to the code above but not exactly the same. They can't be used together though, and really there would be no need to:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*) index.php?url=$1
</IfModule>
The difference is the in the way it's processed. On the first .htaccess example you're passing any file to index.php regardless of whether it exists or not. You can [accidentally] rewrite a path that has a real file so that the real file is never accessed using this method. An example might be you have a file called site.css that can't be accessed because it's being redirected back to index.php.
On the second ruleset he's at least checking to see if the server doesn't have a file or a directory by the name being requested, then they're forwarding it to index.php as a $_GET variable (which seems a little pointless).
The way I typically write these (since I know mod_rewrite is already loaded in the config) is to to this:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^mydomain.com
RewriteRule (.*) http://www.mydomain.com/$1 [R=301,L]
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule .* index.php
In my PHP code I pull the $_SERVER['REQUEST_URI'] and match it against a list of URIs from the database. If there's a match then I know it's a real page (or at least a record existed at some point in time). If there's not a match, then I explode the request_uri and force it through the database using a FULLTEXT search to see what potentially might match on the site.
Note: if you blindly trust the request_uri and query the database directly without cleaning it you run the risk of SQL injection. You do not want to be pwnd.
<?php
$intended_path = $_SERVER['REQUEST_URI'];
if(in_array($intended_path,$uris_from_database)){
//show the page.
} else {
$search_phrase = preg_replace('!/!',' ',$intended_path);
$search_phrase = mysqli_real_escape_string($search_phrase);
$sql = "SELECT * FROM pages WHERE MATCH (title,content) AGAINST ('$search_phrase');"
}
Sorry if this sounds a bit pedantic, but I've had experience managing a couple of million dollar (scratch) website builds that have had their hurdles with people not sticking to a standard convention (or at least the agreed upon team consensus).
I am having issues with the urls. I took the .htaccess code from the user guide to remove the index.php from the url and I have removed it from the config as well. Now here is the problem. I have a controller named “main” and a function inside called “join” which simply display the view. Now if I go to http://localhost/myfolder it loads the index view just fine. However if I try to go to http://localhost/myfolder/main/join or http://localhost/myfolder/join it gives me a 404 error. But http://localhost/myfolder/index.php/main/join works however without loading any css from my header file, but the footer is still loaded. Which I am very confused about. How can I possibly fix it so it just works with main/join? I will use routing later to make it just /join however I need the css to load like it does with my “index” view but not with my “join” view. Also localhost/myfolder/main gives me a 404 error as well. All I did was take the code from the user guide and paste it in .htaccess Any help guys?
Question is little confusing but let me try to answer what I got.
Question 1. Make 'localhost/myfolder/main/join' working.
You mainly need to remove index.php. Do the following:
a. (Very important) Make sure apache's rewrite module is enabled. IF you are using wamp, go to 'Apache'>'Apache modules' and make sure 'rewrite_module' is checked.
b. In code igniter, open file application>config>config.php. Search the line:
$config['index_page'] = 'index.php';
Remove index.php from there. Line must be
$config['index_page'] = '';
c. on myfolder, make a file .htaccess and add following code there:
RewriteEngine on
RewriteCond $1 !^(index\.php|resources|robots\.txt)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L,QSA]
Now URL 'localhost/myfolder/main/join' must be working.
Question 2: Load CSS
To load css, user following code under head section of your view:
<?php echo link_tag('style/style.css');?>
Make sure style/style.css is present in root folder; 'myfolder' in your case.
Hope this helps,
Kapil.
I am working on creating page links from DB like the following example.
Current page:
www.example.com/page.php?pid=7
In the DB it is saved as title "contact-us" under category "Company Info"
I want it to be like:
www.example.com/company-info/contact-us.html
I have tried different solution and answers but did not got any luck. I am not sure, where will be the PHP part and which rules to write for .htaccess files.
In apache (or .hataccess) do something like this:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /proxy.php?_url=$1 [QSA,L]
So in a nutshell, if the resource being requested doens't exist, redirect it to a proxy.php file. From there $_REQUEST['_url'] will be the url the user was requesting.
Then create proxy.php in your home directory and add whatever logic you'd like to load the correct content.
If you use this from .htaccess, then you may need to add RewriteBase / to your config.
If you want to find this page by url, you will probably do this through php and .htaccess. Make a .htaccess that calls page.php for each and every request. You don't need the pid=7, because, well, how should the .htaccess know it is 7, right? :)
In page.php, you take the original url and split it on the slashes, so you get the category (company-info) and the page itself (contact-us.html). Then, you can look these up in the database. This is in a nutshell how many software works, including Wikipedia (MediaWiki) and CodeIgnitor.
Mind that 'company-info' isn't the same as 'Company Info'. You'll have to specify the url-version in the database to be able to use it for look-up.