I would like to cache my pages, which could be done by using:
$this->output->cache(n)
As in the documentation, i could use a custom output method in my controller, named _output.
The problem is, when I create this _output method in my controller, it doesn't create any cache file, only displays the output. I looked into the Output core class, and as I see if it's not find any method with _output, it just echo the content.
They have this in the documentation, to use in my _output:
if ($this->output->cache_expiration > 0)
{
$this->output->_write_cache($output);
}
But cache_expiration is not accessible...
You have 2 ways of solving this,
you can edit the core files and make it the cache_expiration to
public instead of protected and mess with the core files (DIRTY WAY)
or you can extend the CI_Output class (BETTER)
Create a file name it MY_Output.php in your application/core the MY_ prefix is found on the $config['subclass_prefix'] option in your application/config/config.php file.,
then put this little piece of code:
class MY_Output Extends CI_Output{
public $the_public_cache_expiration_ = 0;
public function get_cache_expiration()
{
$this->cache_expiration_ = $this->cache_expiration;
}
}
What we are doing is we are extending the CI_Output class and adding our very own method, when the method get_cache_expiration() is called it will assign the cache_expiration to the_public_cache_expiration_, use it on your _output.
test it using this:
public function _output($output)
{
$this->output->get_cache_expiration();
echo '<pre>';
print_r($this->output->the_public_cache_expiration_);//get only our cache expiration
echo '<hr>';
print_r($this->output);//print the whole Output class
}
benefits:
We did no mess with the core files.
we can add more functionality later to our child class.
here is the basic _output method in use
public function _output($output)
{
$this->output->get_cache_expiration();
if($this->output->cache_expiration_ > 0)
{
$this->output->_write_cache($output);
}
echo $output;
}
Related
here is my library file
libraray file name Commonlib
<?php
class Commonlib extends CI_Controller
{
public function __construct()
{
parent::__construct();
$ci=& get_instance();
$ci->load->database();
}
function getcountries()
{
return $ci->db->get("countries")->result();
}
}
in config file
$autoload['libraries'] = array('database','Commonlib');
here is my view
$a = new Commonlib();
$results=$a->getcountries();
foreach ($results as $row) {
// country_id
echo ''.$row->country .'<br>';
}
show this error Non-existent class:
where is trouble ? how to solve it ?
The problem is here of naming convention. Because Class names and file names must match.
<?php
class Commonlib {
public function __construct() {
parent::__construct();
$ci=& get_instance();
$ci->load->database();
}
function getcountries(){
return $ci->db->get("countries")->result();
}
}
In view
$a = new Commonlib();
$results=$a->getcountries();
foreach ($results as $row)
{ // country_id
echo ''.$row->country .'<br>';
}
Library name should be like this CI_Commonlib ... Please try.
go To your library and change it with this code.
<?php
class your_library_Name {
function getcountries(){
return $ci->db->get("countries")->result();
}
}
and this is how to call it
$rec= $this->your_library_Name->getcountries();
You can do any of a few things.
By default most people will just drop their library into system/libraries, and load it with either with the autoloader, or $this->load->library(). If you do this, you must prefix your class name with CI_ so that CodeIgniter will recognize it, since the system folder is intended for stock files. In your case, you would need:
class CI_Commonlib extends CI_Controller
{
}
This works, but it mixes your custom code into CodeIgniter system files, which can become very messy when you want to upgrade your installation.
My recommendation is to create a separate folder for your custom files, and then add that path to your loader object. You will not need to make any changes to the code if you move your Commonlib object to application/libraries/Commonlib.php.
People will often add custom objects to system when they want to share files between multiple CodeIgniter installations. Multiple applications can share the same BASEPATH, so it makes sense to put your code where the shared directory already exists.
The problem with this is the same issue with an upgrade path, where custom objects mix with stock code, and may get confusing. In this case defining your own shared folder can be very helpful. CodeIgniter lets you do that with $this->load->add_package_path() You can move your shared code into custom/libraries and be off to the races. In that case, you can update your controller (not view) accordingly.
https://www.codeigniter.com/user_guide/libraries/loader.html
$this->load->add_package_path('custom/libraries');
$this->load->library('commonlib');
In a Symfony3 project, which is using psr 4, I am storing configuration data by auto generating a php class in the 'var/cache/dev' folder.
Here is a simplified copy of the generated file:
<?php
use Project\Bundle\Metadata\AbstractMetadata;
class LocalizedMetadata extends AbstractMetadata
{
protected function populate ()
{
}
}
I know I can include or require the file, but the 'dev' directory changes between development and production, and I use the class in several places. Also, I'm hoping to use this bundle in other projects, so I don't want to hard code anything outside of the bundle. How are these files usually loaded? Is there anything within the Symfony core to assist?
Any classes created in the 'dev' directory cannot be auto loaded, at least not without configuring files outside of the bundle (eg. composer.yml).
I took a look into how Symfony manages it's router files, and the solution was actually quite simple.
I made a manager class which can be called from anywhere in the code. This class contains a method which returns an instance of the class in the cache folder.
public function getLocalizedRoutes ()
{
if ( null !== $this->localizedRoutes ) {
return $this->localizedRoutes;
}
$cache = $this->getConfigCacheFactory()->cache(
$this->options['cache_dir'].'/'.CachingMetadata::CACHE_FILE,
function (ConfigCacheInterface $cache) {
$content = CachingMetadata::getInstance()->dump();
$cache->write($content);
}
);
require_once $cache->getPath();
return $this->localizedRoutes = LocalizedMetadata::getInstance();
}
It uses Symfony's built in ConfigCache class, simply because it handles the file write and file permissions. Also, it will call the closure if the file doesn't exist. In this case the closure calls into the class which handles the loading of data and converting it into PHP code. The cache file is then loaded with require_once and an instance of LocalizedMetadata, which is the cached class name, is returned.
The above method can be modified to also pass resource files to ConfigCache, that way if one of your files is modified, the cache will be rewritten. In my case it wasn't required.
Making this work with a cache warmer simply requires a call to the above method:
class RouteCacheWarmer implements CacheWarmerInterface
{
private $_manager;
public function __construct ( LocaleManager $manager )
{
$this->_manager = $manager;
}
public function isOptional ()
{
return true;
}
public function warmUp ( $cacheDir )
{
$this->_manager->getLocalizedRoutes();
}
}
I would also like to note, it's possible to use namespaces within the cache file.
Can someone explain this code in Silverstripe:
public function init() {
RSSFeed::linkToFeed($this->Link() . "rss");
parent::init();
}
What exactly is init function?
what parent::init();
exactly do in code
in php classes when you overwrite a method of parent class you still can call the parent class with this code, it will help you to put some code at the beginning of the real method without removing it.
you can find out more about it at php documentation
The upmost init() method is defined in the Controller class.
Then ContentController extends Controller, which overrides the Controller class's init() method, but it's also calling parent::init() on the first line. Then usually you define all your page controller classes like this (for any new page type), in the example below for the default Page_Controller class:
class Page_Controller extends ContentController {
public function init() {
parent::init();
// do your own stuff here
}
}
So this is the traditional PHP based class extension mechanism, but Silverstripe also allows you to use Extensions and Data Extensions, which is basically extending the functionality of already existing controllers, data objects. I won't go into details with this... You can find out more about this here: https://docs.silverstripe.org/en/4/developer_guides/extending/extensions/
I usually have something like this in my controller classes:
class Page_Controller extends ContentController {
public function init() {
parent::init();
// do your own stuff here
$this->extend('updateInit');
}
}
Notice the $this->extend('updateInit'); line above.
I can have another extension defined for the Page_Controller class inside a YAML config file somewhere, and than have the updateInit() method defined in that class. Example:
class Page_Controller_Extension extends Extension {
public function updateInit() {
// do some more stuff here
}
}
...and in this case you would have something like this in a YAML config file:
---
Name: siteextensions
After:
- 'framework/*'
- 'cms/*'
---
Page_Controller:
extensions:
- Page_Controller_Extension
Note that this is not really the traditional way of extending classes, like in PHP, it's more like defining some decorators for a controller class. Also, to refer to the parent, or object being decorated, you can't use just $this, you'll need to use $this->owner. Example below:
class Page_Controller_Extension extends Extension {
public function updateInit() {
// do some more stuff here
if ($this->owner->IsFeatured) {
// do something here
}
}
}
You usually decorate controllers extending the Extension class, and you extend the DataExtension class if you want to decorate DataObjects - works the same way as explained above.
I simply do not mean how to define a global variable/constant in CodeIgniter.
Let me explain:
I have made a theme engine which is select-able from the current logged in user's control panel. This engine is not very complicated, but a simple folder. anyway, what I do across the application, is that I write one line of code to get the current theme selected by the user. I use a one line of code to get the name, and then store it in a variable:
$theme_name = $this->theme->get_theme_with_slash(false);
And then, I user $theme_name like this to get the proper view:
$this->load->view($theme_name.'result', $data);
And in all of my controllers that loads view I should repeat this process. What I need, is to call the function which gets the theme_name and store in the variable and then use the variable/session/function across the application. My approach currently is the helper's function which is a little less convenient compared to session/variable.
I got this from the manual and this what I have at the top of my config/config.php file: (i have a custom config set to paypal testing)
// HOW TO USE - For example if there's $config['foo'] = 'bar';
// in the config
// using $this- >config->item('foo') will be 'bar'.
// example for my paypal testing:
$config['paypaltest']=0;
http://ellislab.com/codeigniter%20/user-guide/libraries/config.html
and how to access in a controller:
$paypaltest = $this->config->item('paypaltest');
Create A core controller, since your process requires logical operations then you need a method for that.
application/core/MY_Controller.php
class MY_Controller Extends CI_Controller
{
protected $default_theme = 'theme';
public function __construct()
{
parent::__construct();
}
public function get_theme()
{
//your code for selecting the current theme selected from
//the database
$theme_from_db = '';
return $theme_from_db == NULL ? $this->default_theme : $theme_from_db;
}
}
Your Controller must extend MY_Controller
application/controller/view.php
class view extends MY_Controller
{
public function index()
{
$this->load->view($this->get_theme().'result', $data);
}
}
in code igniter global constants can be defined in
config->constants.php
even you no need to load it,it automatically autoloaded by CI automatically.
In Codeigniter all constant is defined inside application/config/constant.php.
like: define("CONSTANTNAME","value");
Constant degined here is accessible throughout all pages, ie; controllers, models and views
I'm currently on a Zend project, i create a controller named company, where i created many action.
Now i want to code some utils function, they will be only used in one action of my controller let's say nameAction.
Here is what i did :
class CompanyController extends Zend_Controller_Action {
public function nameAction( $name = null ) {
function get_inner_html( $node ) {
// Some code goes here
return $html;
}
function check_if_social_account($url) {
// Some code goes here
return $social_account;
}
// Here is the main code of my controller
}
}
This code works well, but out some function into a funvtion is a little weird no?
Where should i put these tools functions get_inner_html & check_if_social_account, in the CompanyController as private functions? In a separate files ?
If this functions will be used in other class, extract it to another class. If not create private methods in your controller class.