Themes outside application - php

I read this post and I want to use similar solution, but with db.
In my site controller after():
$theme = $page->get_theme_name(); //Orange
Kohana::set_module_path('themes', Kohana::get_module_path('themes').'/'.$theme);
$this->template = View::factory('layout')
I checked with firebug:
fire::log(Kohana::get_module_path('themes')); // D:\tools\xampp\htdocs\kohana\themes/Orange
I am sure that path exists. I have directly in 'Orange' folder 'views' folder with layout.php file.
But I am getting: The requested view layout could not be found
Extended Kohana_Core is just:
public static function get_module_path($module_key) {
return self::$_modules[$module_key];
}
public static function set_module_path($module_key, $path) {
self::$_modules[$module_key] = $path;
}
Could anybody help me with solving that issue?
Maybe it is a .htaccess problem:
# Turn on URL rewriting
RewriteEngine On
# Put your installation directory here:
# If your URL is www.example.com/kohana/, use /kohana/
# If your URL is www.example.com/, use /
RewriteBase /kohana/
# Protect application and system files from being viewed
RewriteCond $1 ^(application|system|modules)
# Rewrite to index.php/access_denied/URL
RewriteRule ^(.*)$ / [PT,L]
RewriteRule ^(media) - [PT,L]
RewriteRule ^(themes) - [PT,L]
# Allow these directories and files to be displayed directly:
# - index.php (DO NOT FORGET THIS!)
# - robots.txt
# - favicon.ico
# - Any file inside of the images/, js/, or css/ directories
RewriteCond $1 ^(index\.php|robots\.txt|favicon\.ico|static)
# No rewriting
RewriteRule ^(.*)$ - [PT,L]
# Rewrite all other URLs to index.php/URL
RewriteRule ^(.*)$ index.php/$1 [PT,L]
Could somebody help?
What I am doing wrong?
Regards
[EDIT]
My controller code:
class Controller_Site extends Controller_Fly {
public static $meta_names = array('keywords', 'descriptions', 'author');
public function action_main() {
$this->m('page')->get_main_page();
}
public function action_page($page_title) {
$this->m('page')->get_by_link($page_title);
}
public function after() {
$page = $this->m('page');
$metas = '';
foreach(self::$meta_names as $meta) {
if (! empty($page->$meta)) {
$metas .= html::meta($page->$meta, $meta).PHP_EOL;
}
}
$theme = $page->get_theme_name();
Kohana::set_module_path('themes', Kohana::get_module_path('themes').'/'.$theme);
$menus = $page->get_menus();
$this->template = View::factory('layout')
->set('theme', $theme)
->set('metas', $metas)
->set('menus', $menus['content'])
->set('sections', $page->get_sections())
->set_global('page', $page);
if ($page->header_on) {
$settings = $this->m('setting');
$this->template->header = View::factory('/header')
->set('title', $settings->title)
->set('subtitle', $settings->subtitle)
->set('menus', $menus['header']);
}
if ($page->sidebar_on) {
$this->template->sidebar = View::factory('sidebar', array('menus' => $menus['sidebar']));
}
if ($page->footer_on) {
$this->template->footer = View::factory('footer');
}
parent::after();
}
}
and parent controller:
abstract class Controller_Fly extends Controller_Template {
protected function m($model_name, $id = NULL) {
if (! isset($this->$model_name)) {
$this->$model_name = ORM::factory($model_name, $id);
}
return $this->$model_name;
}
protected function mf($model_name, $id = NULL) {
return ORM::factory($model_name, $id);
}
}
[Edit 2]
Previous link to post was dead, link was:
http://forum.kohanaframework.org/comments.php?DiscussionID=5744&page=1#Item_0

My guess is that your controller has a __construct() method and you aren't calling parent::__construct
Actually, I think for kohana V3 __construct needs to also be passed the $request object as follows:
public function __construct(Request $request)
{
parent::__construct($request);
}

I realized that I need to init all modules once again:
$theme = $page->get_theme_name();
Kohana::set_module_path('themes', Kohana::get_module_path('themes').'/'.$theme);
Kohana::modules(Kohana::get_modules());
Now I don't have an error. Instead I am getting white screen of death:
$this->template is null
:(
[EDIT]
Now I know, I had:
$this->template = View::factory('layout')
->set('theme', $theme)
->set('metas', $metas)
->set('menus', $menus['content'])
->set('sections', $page->get_sections())
->set_gobal('page', $page);
Ofcourse I forgot that set_global doesn't return $this :D
Anyway everything working now :)
I have one more question about efficiency. I am calling Kohana::modules() second time in request flow. Is this a big deal according to efficiency?
Regards

Related

PHP 8 - Routing can't find requested URL

I have a problem with PHP 8 routing. I'm creating my MVC "framework" to learn more about OOP. I did routing, controller and view - it works, I'm happy. But I found out that I would test my creation. This is where the problem begins, namely if the path is empty (""), it returns the "Home" view as asked in the routing, but if I enter "/ test" in the URL, for example, I have a return message "404 Not Found - The requested URL was not found on this server. " even though the given route is added to the table. What is wrong?
.htaccess file
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)$ index.php [QSA,L]
index.php with routes
<?php
/*
* Require Composer
*/
require dirname(__DIR__) . '/vendor/autoload.php';
/*
* Routing
*/
$routes = new Core\Router();
$routes->new('', ['controller' => 'HomeController', 'method' => 'index']);
$routes->new('/test', ['controller' => 'HomeController', 'method' => 'test']);
$routes->redirectToController($_SERVER['QUERY_STRING']);
Router.php file
<?php
namespace Core;
class Router
{
/*
* Routes and parameters array
*/
protected $routes = [];
protected $params = [];
/*
* Add a route to the route board
*/
public function new($route, $params = [])
{
/*
* Converting routes strings to regular expressions
*/
$route = preg_replace('/\//', '\\/', $route);
$route = preg_replace('/\{([a-z]+)\}/', '(?P<\1>[a-z-]+)', $route);
$route = '/^' . $route . '$/i';
$this->routes[$route] = $params;
}
/*
* Get all routes from table
*/
public function getRoutesTable() {
return $this->routes;
}
/*
* Checking if the specified path exists in the route table
* and completing the parameters table
*/
public function match($url)
{
foreach($this->routes as $route => $params) {
if(preg_match($route, $url, $matches)) {
foreach($matches as $key => $match) {
if(is_string($key)) {
$params[$key] = $match;
}
}
$this->params = $params;
return true;
}
}
return false;
}
/*
* Get all params from table
*/
public function getParamsTable() {
return $this->params;
}
/*
* Redirection to the appropriate controller action
*/
public function redirectToController($requestUrl) {
$requestUrl = explode('?', $requestUrl);
$url = $requestUrl[0];
if ($this->match($url)) {
$controller = $this->params['controller'];
$controller = "App\\Controllers\\$controller";
if(class_exists($controller)) {
$controller_obj = new $controller($this->params);
$method = $this->params['method'];
if(method_exists($controller, $method)) {
$controller_obj->$method();
} else {
echo "Method $method() in controller $controller does not exists!";
}
} else {
echo "Controller $controller not found!";
}
} else {
echo "No routes matched!";
}
}
}
View.php file
<?php
namespace Core;
class View {
public static function view($file) {
$filename = "../App/Views/$file.php";
if(file_exists($filename)) {
require_once $filename;
} else {
echo "View $file is not exist!";
}
}
}
HomeController file
<?php
namespace App\Controllers;
use Core\Controller;
use Core\View;
class HomeController extends Controller {
public function index() {
return View::view('Home');
}
public function test() {
return View::view('Test');
}
}
Folder structure
Routes in web browser
I'm using XAMPP with PHP 8.0 and Windows 10.
First of all, choose one of the following two options to proceed.
Option 1:
If the document root is set to be the same as the project root, e.g. path/to/htdocs, in the config file of the web server (probably httpd.conf), similar to this:
DocumentRoot "/path/to/htdocs"
<Directory "/path/to/htdocs">
AllowOverride All
Require all granted
</Directory>
then create the following .htaccess in the project root, remove any .htaccess file from the directory path/to/htdocs/Public and restart the web server:
<IfModule dir_module>
DirectoryIndex /Public/index.php /Public/index.html
</IfModule>
Options FollowSymLinks
RewriteEngine On
RewriteBase /Public/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [QSA,L]
Option 2:
If the document root is set to be the directory path/to/htdocs/Public in the config file of the web server (probably httpd.conf), similar to this:
DocumentRoot "/path/to/htdocs/Public"
<Directory "/path/to/htdocs/Public">
AllowOverride All
Require all granted
</Directory>
then create the following .htaccess in the directory path/to/htdocs/Public, remove any other .htaccess file from the project root (unless it, maybe, contains some relevant settings, other than DirectoryIndex) and restart the web server::
Options FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [QSA,L]
After you decided and proceeded with one of the options above, edit the page index.php as shown bellow:
<?php
//...
/*
* NOTE: A route pattern can not be an empty string.
* If only the host is given as URL address, the slash
* character (e.g. "/") will be set as value of the
* URI path, e.g. of $_SERVER['REQUEST_URI']. Therefore,
* the route pattern should be set to "/" as well.
*/
$routes->new('/', [
'controller' => 'HomeController',
'method' => 'index',
]);
//...
/*
* In order to get the URI path, you must use the server
* parameter "REQUEST_URI" instead of "QUERY_STRING".
*/
$routes->redirectToController(
$_SERVER['REQUEST_URI']
);
Notes:
In regard of changing $_SERVER['QUERY_STRING'] to $_SERVER['REQUEST_URI'], the credits go to #MagnusEriksson, of course.
There can't be an "MVC framework", but a "web framework for MVC-based application(s)". This is, because a framework is just a collection of libraries (not at all correlated with MVC), which, in turn, is used by one or more applications implementing the MVC pattern.
For any further questions, don't hesitate to ask us.

Changing default Access to a function in a php file under the subdirectory in .htaccess

I want to run my activeIndex() function in GuestsController.php file under a subdirectory as the first default page when the user enters the url.
For this reason, I have written such a script in my .htaccess file:
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/controllers/GuestsController.php/.*
RewriteRule ^/mvc/(.*) /controllers/GuestsController.php?method=$actionList?page=$1 [QSA,L]
And my GuestsController.php file is:
<?php
class GuestsController
{
public function actionIndex()
{
echo "start";
sleep(1);
include(dirname(__FILE__) . '/../views/guests/index.php' );
}
public function actionList()
{
$guests = Guests::findAll();
echo json_encode( $guests );
}
}
I still could not manage to achieve my goal.
How I should modify .htaccess file to run actionIndex() function directly?
Thanks,

could not unset url after display the MVC page

i am new to MVC i have created a routing class below, it is working fine but when i go to the index page the navigation anchor href are correct. but when i move to other controller the url first string which is url-0 , is still the previous controller, which change all navigation href address base+previous controller, for e.g if i am on indexController/index which will display all the pages froom database. and when i want to call logincontroller through navigation anchor the logincontroller href change it becomes indecontroller/loginController/login. the correct login href address is loginController/login. my htaccess and routing class is below.and folder structure.
mvc app controllers indexcontroller.php userController.php
model user.php page.php
lib
core App.php Controller.php
includes navigation.php
style style.css
images
js javscript
index.php
I hope some one can help me, i tried but so success yet Please Help Thanks in advance.
RewriteEngine On
RewriteBase /socialNetwork
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteRule ^([a-zA-Z0-9\/\-_]+)\.?([a-zA-Z]+)?$ index.php?url=$1&extension=$2 [QSA,L]
class App
{
protected $controller = 'indexController';
protected $method = 'index';
protected $params = array();
public function __construct()
{
$url = $this->parseUrl();
//print_r($url);
if (isset($url[0]))
{
if (file_exists('app/controllers/'.$url[0].'.php'))
{
//$url = ('../app/controllers/'.$url[0].'.php');
$this->controller = $url[0];
//echo ($this->controller);
unset($url[0]);
}
}
require_once('app/controllers/'.$this->controller.'.php');
$this->controller = new $this->controller;
if (isset($url[1]))
{
if (method_exists($this->controller,$url[1]))
{
$this->method = $url[1];
unset($url[1]);
}
}
$this->params = $url ? array_values($url) : array();
call_user_func_array(array($this->controller,$this->method),$this->params);
}
public function parseUrl()
{
if (isset($_GET['url']))
{
return $url =explode('/',filter_var(rtrim($_GET['url'],'/'),FILTER_SANITIZE_URL));
}
}
}
this is my index page.
<header>
<img width="960" height="100" src="http://localhost/socialNetwork/images/bgheader.png">
</header>
<?php
include_once("include/navigation.php");?>
<section class="content">
<?php
require_once('app/init.php');
$app = new App;
?>
</section>
You should not have relative url's in your view files (html-files). Check out some common MVC-like PHP frameworks like Laravel or Symfony. They all have methods which provides you the full qualified url for you vew-files like: http://domain.tld/controller/param/... instead of /cobntroller/..
Implementing this should solve your problem.
For example check out Laravel. It's very easy to understand and pretty flexible. There you have access to all your route with functions like Redirect::route('your-route-name'). The routing engine will then translate this into the full url!
EDIT: Just to be more precise, laravel is not a real mvc by definition. But in some parts it acts like a mvc.
Hope this helps

Getting $_GET variable when using mod_rewrite

I am having issues getting $_GET variables with mod_rewrite enabled. I have the following .htaccess:
RewriteEngine On
RewriteRule ^/?Resource/(.*)$ /$1 [L]
RewriteRule ^$ /home [redirect]
RewriteRule ^([a-zA-Z]+)/?([a-zA-Z0-9/]*)$ /app.php?page=$1&query=$2 [L]
and app.php is:
<?php
require("controller.php");
$app = new Controller();
and controller.php is:
<?php
require("model.php");
require("router.php");
class Controller{
//--------Variables------------
private $model;
private $router;
//--------Functions------------
//Constructor
function __construct(){
//initialize private variables
$this->model = new Model();
$this->router = new Router();
$page = $_GET['page'];
//Handle Page Load
$endpoint = $this->router->lookup($page);
if($endpoint === false) {
header("HTTP/1.0 404 Not Found");
}else {
$this->$endpoint($queryParams);
}
}
private function redirect($url){
header("Location: /" . $url);
}
//--- Framework Functions
private function loadView($view){
require("views/" . $view . ".php");
}
private function loadPage($view){
$this->loadView("header");
$this->loadView($view);
$this->loadView("footer");
}
//--- Page Functions
private function indexPage(){
$this->loadPage("home");
}
private function controlPanel(){
echo "Query was " . $code;
/*
if($this->model->set_token($code)){
$user = $this->model->instagram->getUser();
}else{
echo "There was an error generating the Instagram API settings.";
}
*/
$this->loadPage("controlpanel");
}
private function autoLike(){
$this->loadPage("autolike");
}
private function about(){
$this->loadPage("about");
}
}
So an example of a URL that I might have is /app.php?page=controlpanel&query=null which would be rewritten as /controlpanel. The problem I have is that I have another page which sends a form to /controlpanel resulting in a URL like /controlpanel?code=somecode.
What I am trying to do is get $_GET['code'] and I cannot seem to do this. Can anyone help? Apologies in advance for a bit of a code dump.
Change
RewriteRule ^([a-zA-Z]+)/?([a-zA-Z0-9/]*)$ /app.php?page=$1&query=$2 [L]
to
RewriteRule ^([a-zA-Z]+)/?([a-zA-Z0-9/]*)$ /app.php?page=$1&query=$2 [L,QSA]
QSA is to append the query string
From the docs
"When the replacement URI contains a query string, the default behavior of RewriteRule is to discard the existing query string, and replace it with the newly generated one. Using the [QSA] flag causes the query strings to be combined."

RewriteRule: trying to get rid of dashes

I'm trying to rewrite dashes in URL so that they don't exist internally. For example this URL
localhost/mysite/about-me
"about-me" should be rewritten to "aboutme". I need this because the controller class name depends on this route string, and I obviously can't use dashes for this.
This is the condition and rule I found which I thought should fit my needs:
# Condition is to avoid rewrite on files within specified subdirs
RewriteCond $1 !^(css|img|ckeditor|scripts)
RewriteRule ^([^-]+)-([^-]+)$ $1$2 [L]
However it seems that it's not working, since the controller class Aboutme is not instanciated. I get a 404 error instead, and I don't have any problem with similar controller classes without a dash in their names.
Could you please give me a hand on this?
Why not go with routes?
$route['about-me'] = 'aboutme/index';
Try removing ^ and $
# Condition is to avoid rewrite on files within specified subdirs
RewriteCond $1 !^(css|img|ckeditor|scripts)
RewriteRule ([^-]+)-([^-]+) $1$2 [L]
You can extend the Router class.
In /application/core create a file called MY_Router.php (MY is the default prefix) and copy this into it;
<?php if (! defined('BASEPATH')) exit('No direct script access allowed');
class MY_Router extends CI_Router {
function set_class($class) {
$this->class = str_replace('-', '_', $class);
}
function set_method($method) {
$this->method = str_replace('-', '_', $method);
}
function _validate_request($segments) {
// Does the requested controller exist in the root folder?
if (file_exists(APPPATH.'controllers/'.str_replace('-', '_', $segments[0]).'.php')) {
return $segments;
}
// Is the controller in a sub-folder?
if (is_dir(APPPATH.'controllers/'.$segments[0])) {
// Set the directory and remove it from the segment array
$this->set_directory($segments[0]);
$segments = array_slice($segments, 1);
if (count($segments) > 0) {
// Does the requested controller exist in the sub-folder?
if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().str_replace('-', '_', $segments[0]).'.php')) {
show_404($this->fetch_directory().$segments[0]);
}
} else {
$this->set_class($this->default_controller);
$this->set_method('index');
// Does the default controller exist in the sub-folder?
if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$this->default_controller.'.php')) {
$this->directory = '';
return array();
}
}
return $segments;
}
// Can't find the requested controller...
show_404($segments[0]);
}
}
This will automatically rewrite - to _ for you.
If you don't want underscores change the code to replace them with nothing;
all occurences of str_replace('-', '_', to str_replace('-', '',
Here is a way to do it with mod-rewrite:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} ^/(.*)([\w]*)-([\w]*)(.*)/?$ [NC]
RewriteRule .* %1%2%3%4 [L,DPI]
Won't redirect but can do it adding R=301 like this [R=301,DPI,L].
Does not have to be about-me. Can be any words pair at any position. i.e.
localhost/mysite/about-me = .../aboutme or
localhost/mysite/folder1/folder2/folder3/my-folder = .../myfolder or
localhost/mysite/folder1/folder2/my-folder/folder3 = .../myfolder/...

Categories