Use add_package_path for Code Igniter controllers - codeigniter

I am trying to use $this->load->add_package_path to add a new sub-application to my CI app. I can see how to use this for views and such: just put
$this->load->add_package_path("/mypackage");
in the controller ctor. Unfortunately, that doesn't help, because I want to find controllers from the package path: it seems like a chicken-and-egg problem. Is there somewhere else I can put a add_package_path call (such as index.php)?

Figured it out by tracing through CI. Turns out you can't do this. You can put your own controllers in a subdirectory of /application/controllers, but you cannot put them someplace else: in particular, as http://codeigniter.com/user_guide/libraries/loader.html implies,
These elements can be libraries (classes) View files, Helpers, Models, or your own files.
"Your own files" not including controllers. I ended up being able to get it to look to the ENVIRONMENT setting in addition to APPPATH by making changes to CodeIgniter.php and Router.php. I don't like making this kind of change, however, so I backed out the changes. I'll put this here in case somebody else can benefit from it.
Router.php change:
function _validate_request($segments)
{
...
// Does the requested controller exist in the root folder?
if (file_exists(APPPATH.'controllers/'.$segments[0].'.php')
|| file_exists(ENVIRONMENT.'/controllers/'.$segments[0].'.php')) // New bit here
{
return $segments;
}
....
}
CodeIgniter.php change, 'round about line 246:
if ( ! file_exists(APPPATH.'controllers/'.$RTR->fetch_directory().$RTR->fetch_class().'.php'))
{
// New bit here
if ( ! file_exists(ENVIRONMENT.'/controllers/'.$RTR->fetch_directory().$RTR->fetch_class().'.php'))
{
show_error('Unable to load your default controller. Please make sure the controller specified in your Routes.php file is valid.');
}
include(ENVIRONMENT.'/controllers/'.$RTR->fetch_directory().$RTR->fetch_class().'.php');
} else {
include(APPPATH.'controllers/'.$RTR->fetch_directory().$RTR->fetch_class().'.php');
}

Related

How to render a cms page with default theme AND variables from controllers in OctoberCMS?

I'm wondering how I can render a view, or display a page with my default theme in OctoberCMS, via a route that executes a function in a controller.
If I have the following route:
Route::get('bransje', [
'uses' => 'Ekstremedia\Cityportal\CPController#bransje'
]);
And in my controller CPController ive tried several things, like I used to with Laravel:
public function bransje() {
$stuff = Stuff::with('info');
return View::make('cms::bransje')->with('stuff',$stuff);
}
But I cannot seem to get it to work, and I've tried to search the web, but it's hard to find answers. I have found a workaround, and that is to make a plugin component, then I can include that component and do:
public function onRun()
{
$this->eventen = $this->page['stuff'] = $this->stuff();
}
protected function stuff()
{
return ...
}
Is there any way so I can make pages without using the Cms, and that are wrapped in my default theme? I've tried
return View::make('my-theme-name::page');
and a lot of variants but no luck.
I know I can also do a:
==
public function onRun()
{
}
in the start of my page in the cms, but I'm not sure how to call a function from my plugin controller via there.
You can bypass frontend routing by using routes.php file in your plugin.
Full example in this video turotial.
If this answer can still be useful (Worked for October v434).
I have almost the same scenerio.
What I want to achieve is a type of routing like facebook page and profile.
facebook.com/myprofile is the same url structure as facebook.com/mypage
First I create a page in the CMS for each scenario (say catchpage.htm)
Then a created a catchall route at the buttom of routes.php in my plugin that will also not disturb the internal working of octobercms.
if (!Request::is('combine/*') && !Request::is('backend/*') && !Request::is('backend')) {
// Last fail over for looking up slug from the database
Route::get('{slug}/{slug2?}', function ($slug, $slug2 = null) {
//Pretend this are our routes and we can check them against the database
$routes = ["bola", "sade", "bisi", "ade", "tayo"];
if(in_array($slug, $routes)) {
$cmsController = new Cms\Classes\Controller;
return $cmsController->render("/catchpage", ['slug' => $slug]);
}
// Some fallback to 404
return Response::make(View::make('cms::404'), 404);
});
}
The if Request::is check is a list of all the resource that october uses under the hood, please dont remove the combine as it is the combiner route. Remove it and the style and script will not render. Also the backend is the url to the backend, make sure to supply the backend and the backend/*.
Finally don't forget to return Response::make(View::make('cms::404'), 404); if the resource is useless.
You may put all these in a controller though.
If anyone has a better workaround, please let us know.

Laravel 4.2- How to Route to files in a Subfolder

This is my first time using stackoverflow. I am really stuck on a seemingly simple problem in Laravel 4.2, how to route to a bunch of files(.php view files in a subdirectory.
I have about forty .blade.php files in a subdirectory called mechanics.
When the clicks on the link
action('PagesController#mechanicspages') (Note: I don't know how to pass a value from here). The route is
Route::get('/mechanics/{id}', 'PagesController#mechanicspages');
The function at the PagesController is:
public function mechanicspages($id)
{
return View::make('/mechanics/{$id}');
}
Can I show a view with this logic?
To do this you need to use the find the object and send it to the view...
To access a view in a subfolder you just use a period "."
Here is what I would do:
Route file:
Route::get('/mechanics/{id}', 'PagesController#mechanicspages');
Controller File:
public function mechanicspages($id) {
$mechanic = Mechanics::find($id);
if($mechanic)
return View::make('mechanics.subview')->with($mechanic);
}
For more on this see:
How to pass data to view.
http://laravel.com/docs/4.2/responses (half way down. Search for "with")

Calling string in separate file in CodeIgniter

I'm building a profanity/racial slur filter for my website. I have it working, but my preg_match string is quite long. I'm just wondering if there is some way to host this long string in a separate file in CodeIgniter and then call it when I need to in the preg_match.
I have googled this and I couldn't find anything, so I thought I would ask here.
What I'm doing now is hosting my string in the model and then calling this:
if(preg_match($filterRegex)){
databaseStuffHere();
}
Here are a few options. Depending on how and where you are using this string and function, one may be better than the others.
Config
You could store the value as a config, in application/config/config.php
$config['filter_regex'] = 'yourReallyLongString';
The primary config is auto-loaded by CodeIgniter, so you can use it like so:
$filterRegex = $this->config->item('filter_regex');
if(preg_match($filterRegex, $subject))
{
databaseStuffHere();
}
Constant
If you're using this long string in several places and it would be useful to have global access, you could define it as as constant in application/config/constants.php. It will also prevent you from accidentally redefining the value.
define('FILTER_REGEX', 'yourReallyLongString');
Then use it with your function like this:
$filterRegex = FILTER_REGEX;
if(preg_match($filterRegex, $subject))
{
databaseStuffHere();
}
Helper
Finally, you could use a helper. You can load the helper when required, or auto-load it. You can create your own helper in application/helpers/. It could look something like this:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
if ( ! function_exists('filter_slurs'))
{
function filter_slurs($subject = '')
{
$filter_regex = 'yourReallyLongString';
if (preg_match($filter_regex, $subject))
{
return FALSE;
}
else
{
return TRUE;
}
}
}
Having a function to handle this may make your code easier to follow and more meaningful, for example, in your controller, you could use it like this:
$this->load->helper('slur_filter_helper'); //assumes the helper file is: slur_filter_helper.php
if(filter_slurs($subject))
{
//do something
}
else
{
//do something else
}
You can use it with config file (system/application/config/config.php) to set configuration related variables.
====================== DEFINE WHAT YOU WANT in config.php ===========================
$config['REQUIRED_SRTING'] = 'YOUR_REQUIRED_LONG_STRING_OR_WHAT_YOU_WANT_STORE';
But best place to set constant is
(system/application/config/constants.php) to store site preference constants.
===================DEFINE WHAT YOU WANT in constants.php=========================
define('CONSTANT_STRING','YOUR_REQUIRED_LONG_STRING_OR_WHAT_YOU_WANT_STORE');

CodeIgniter page caching with a exception

I like to use CodeIgniters page caching. But I've got a views counter in the controller, something like:
$this->db->query("UPDATE tb_product SET popularity=popularity+1 WHERE product_id=".$this->db->escape($this->uri->segment(2))."");
Is it possible to use page caching but make a exception to run this query only?
Yes. You could try to implement a hook. This would have to be the 'cache_override' hook. You could do the DB call from the hook.
http://ellislab.com/codeigniter/user-guide/general/hooks.html
Your hook method will have to call the original caching itself after doing the DB call.
function your_hook( )
{
// your DB code here
// Use some CI globals for this, see /system/core/Codeigniter.php
if ($OUT->_display_cache($CFG, $URI) == TRUE)
{
exit;
}
}
You could write a custom Output.php class and override (decorate) the original _display_cache method. Place your MY_Ouput.php in the /application/core directory and CI will use it automatically.
http://ellislab.com/codeigniter/user-guide/general/core_classes.html
Put something like this in it:
class MY_Output extends CI_Output
{
function _display_cache( &$CFG, &$URI )
{
// your DB call
// The original call
return parent::_display_cache( $CFG, $URI );
}
}
I didn't try this myself, but it should help you on your way. One of these will probably work. Good luck!
Thanks for your answer, but I've striped the counter out and wrote a cronjob which will get statistics from Google Analytics trough GAPI.

Codeigniter 2.0.x - Controller subdirectories default controller needs to be in URL

I recently upgraded a site from CodeIgniter 1.7.x to 2.0.3. About the same time someone in my organization requested we add some pages to the site. Underneath a section. In the old version of the site I used some workarounds in the controller to break up a longer URL. But in version 2 I see that I should be able to use subdirectories in the controllers folder to do it in a more proper way. After looking all over the place I've tried all sorts of routing declarations and fiddled with all sorts of things. Hopefully I'm doing something simple, wrong, or perhaps someone has seen a similar issue stemming from the upgrade.
I'm trying to get the URL from something like:
/about/locations
Which used to work with a controller named about.php. To something more like:
/about/social_responsibility/commitment
Where about is now a aub-directory.
Funny thing is, currently it does sorta work. That second URL displays correctly. However my old pages, that first URL, now do not function... My new structure uses a base.php (default_controller) in the about directory. Thus if I write:
/about/base/locations
It does work. But I thought the whole routing thing (default controller) and using subdirectories is supposed to clean the URL up.
My info is as follows...
Current Routing (it's changed a bunch over the last few hours)
$route['default_controller'] = "base";
$route['404_override'] = '';
$route['about'] = "about/base";
Directories and Files
/controllers/about/base.php
/controllers/about/social_responsibility.php
Chunk of base.php
class Base extends MY_Controller
{
public function __construct()
{
parent::__construct();
$this->data['parent'] = "About";
$this->load->model('mnav');
}
public function index()
{
}
public function locations()
{
}
}
I also have a MY_Controller that extends CI_Controller, but all it does is enable FirePHP for me in the development environment.
Anyone have any clues? Or need some more info to help? Thanks!
I just tested on my system, with CI 2.0.2 and it seems that the default controller setting works for subdirectories as well, without any other routes.
// so in your config file, whatever your default_controller is set to...
// you would just use that as the name of the `base` controller in about
// for example, if your default_controller is 'welcome'
// in /application/config.php
$route['default_controller'] = "welcome";
$route['404_override'] = '';
// then, it should work for the subdirectory where there is a controller
// named 'welcome'
// application/controllers/about/base.php
class Welcome extends MY_Controller
{
public function __construct()
{
parent::__construct();
}
public function index()
{
echo "I can be reached with /about";
}
}
So, all you should have to do is remove all of the routes for about
// remove this
$route['about'] = "about/base";
Important
This will only work when accessing /about -- anything in additional segments will be looking for additional controllers. So you'd have to think about how you'd like to access the base controller (whether or not you name it something else).
I'd assume that /about/locations is looking for an actual "locations" controller in your about folder, rather than being the method for your base controller. As far as CI knows, you're trying to execute one of two functions:
About controller's "locations" method
about/Locations controller's index method (obviously doesn't exist)
It follows that any 3-segment or greater URI will work with this scheme, but 2-segment URI's will confuse it. I don't think letting CI fallback to the default controller is going to work here. Try this:
$route['default_controller'] = "base";
$route['404_override'] = '';
$route['([^\/]*)'] = '$1/base';
$route['([^\/]*)/([^\/]*)'] = '$1/base/$2';

Resources