I know what is the use of this method.
The third parameter of view method TRUE or FALSE how it works internally because want to make same method in core php which would be very usefull in core php. Not only in core in other framworks as well such as cake php too.
Thanks.
This is the main function that is called :
public function view($view, $vars = array(), $return = FALSE)
{
return $this->_ci_load(array('_ci_view' => $view, '_ci_vars' => $this->_ci_object_to_array($vars), '_ci_return' => $return));
}
Now the first protected function _ci_load()
protected function _ci_load($_ci_data)
{
// Set the default data variables
foreach (array('_ci_view', '_ci_vars', '_ci_path', '_ci_return') as $_ci_val)
{
$$_ci_val = isset($_ci_data[$_ci_val]) ? $_ci_data[$_ci_val] : FALSE;
}
$file_exists = FALSE;
// Set the path to the requested file
if (is_string($_ci_path) && $_ci_path !== '')
{
$_ci_x = explode('/', $_ci_path);
$_ci_file = end($_ci_x);
}
else
{
$_ci_ext = pathinfo($_ci_view, PATHINFO_EXTENSION);
$_ci_file = ($_ci_ext === '') ? $_ci_view.'.php' : $_ci_view;
foreach ($this->_ci_view_paths as $_ci_view_file => $cascade)
{
if (file_exists($_ci_view_file.$_ci_file))
{
$_ci_path = $_ci_view_file.$_ci_file;
$file_exists = TRUE;
break;
}
if ( ! $cascade)
{
break;
}
}
}
if ( ! $file_exists && ! file_exists($_ci_path))
{
show_error('Unable to load the requested file: '.$_ci_file);
}
// This allows anything loaded using $this->load (views, files, etc.)
// to become accessible from within the Controller and Model functions.
$_ci_CI =& get_instance();
foreach (get_object_vars($_ci_CI) as $_ci_key => $_ci_var)
{
if ( ! isset($this->$_ci_key))
{
$this->$_ci_key =& $_ci_CI->$_ci_key;
}
}
/*
* Extract and cache variables
*
* You can either set variables using the dedicated $this->load->vars()
* function or via the second parameter of this function. We'll merge
* the two types and cache them so that views that are embedded within
* other views can have access to these variables.
*/
if (is_array($_ci_vars))
{
foreach (array_keys($_ci_vars) as $key)
{
if (strncmp($key, '_ci_', 4) === 0)
{
unset($_ci_vars[$key]);
}
}
$this->_ci_cached_vars = array_merge($this->_ci_cached_vars, $_ci_vars);
}
extract($this->_ci_cached_vars);
/*
* Buffer the output
*
* We buffer the output for two reasons:
* 1. Speed. You get a significant speed boost.
* 2. So that the final rendered template can be post-processed by
* the output class. Why do we need post processing? For one thing,
* in order to show the elapsed page load time. Unless we can
* intercept the content right before it's sent to the browser and
* then stop the timer it won't be accurate.
*/
ob_start();
// If the PHP installation does not support short tags we'll
// do a little string replacement, changing the short tags
// to standard PHP echo statements.
if ( ! is_php('5.4') && ! ini_get('short_open_tag') && config_item('rewrite_short_tags') === TRUE)
{
echo eval('?>'.preg_replace('/;*\s*\?>/', '; ?>', str_replace('<?=', '<?php echo ', file_get_contents($_ci_path))));
}
else
{
include($_ci_path); // include() vs include_once() allows for multiple views with the same name
}
log_message('info', 'File loaded: '.$_ci_path);
// Return the file data if requested
if ($_ci_return === TRUE)
{
$buffer = ob_get_contents();
#ob_end_clean();
return $buffer;
}
/*
* Flush the buffer... or buff the flusher?
*
* In order to permit views to be nested within
* other views, we need to flush the content back out whenever
* we are beyond the first level of output buffering so that
* it can be seen and included properly by the first included
* template and any subsequent ones. Oy!
*/
if (ob_get_level() > $this->_ci_ob_level + 1)
{
ob_end_flush();
}
else
{
$_ci_CI->output->append_output(ob_get_contents());
#ob_end_clean();
}
return $this;
}
second protected function _ci_object_to_array :
protected function _ci_object_to_array($object)
{
return is_object($object) ? get_object_vars($object) : $object;
}
And that's it. If you know your php, you can easily make out what it does :) Cheers
Related
i am having this erro clicking in on the menu (Build) so i dont understand. someone can help me please? Why this is happining in this line below?
public function run($url = null)
{
$params = RouterHelper::segmentizeUrl($url);
// Handle NotFoundHttpExceptions in the backend (usually triggered by abort(404))
Event::listen('exception.beforeRender', function ($exception, $httpCode, $request) {
if (!$this->cmsHandling && $exception instanceof \Symfony\Component\HttpKernel\Exception\NotFoundHttpException) {
return View::make('backend::404');
}
}, 1);
/*
* Database check
*/
if (!App::hasDatabase()) {
return Config::get('app.debug', false)
? Response::make(View::make('backend::no_database'), 200)
: $this->passToCmsController($url);
}
the erro start happining at this line---------->
$controllerRequest = $this->getRequestedController($url);
if (!is_null($controllerRequest)) {
return $controllerRequest['controller']->run(
$controllerRequest['action'],
$controllerRequest['params']
);
}
/*
* Fall back on Cms controller
*/
return $this->passToCmsController($url);
}
To make a View you don't need to make Response. Instead of
Response::make(View::make('backend::no_database'), 200)
use
return View::make('backend::no_database');
or this for custom page
return View::make('author.plugin::backend.file'); # htm is on views/backend/file.htm
By the way check above on same file, it has return View::make('backend::404');
I have a problem with router.php
I cannot found an error in public function parse(&$segments)
The url generated as i want but it doesn't work with sef correct
the parse function gets correctly the view and the id_tsi parameters but id_tsi parameter seems to be not working
Version of joomla 3.7
the url of the component looks like
www.ktopoverit.ru/index.php?option=com_helloworld&view=reestr_si&id_tsi=1
url with switched on sef looks like
www.ktopoverit.ru/poverka/reestr_si/1
$vars looks like
Array (
[view] => reestr_si
[id_tsi] => 1
)
and my router is
class helloworldRouter extends JComponentRouterBase
{
public function build(&$query)
{
$segments = array();
if (isset($query['view']))
{
$segments[] = $query['view'];
unset($query['view']);
}
if (isset($query['id_tsi']))
{
$segments[] = $query['id_tsi'];
unset($query['id_tsi']);
};
return $segments;
}
public function parse(&$segments)
{
$vars = array();
switch($segments[0])
{
case 'reestr_si':
$vars['view'] = 'reestr_si';
$id = explode(':', $segments[0]);
$vars['id_tsi'] = (int) $id[1];
break;
}
return $vars;
}
}
Since your build() method creates the right URLs, it makes sense to take it as the base for some assumptions.
$query contains max. two values, a view (string) and an id (int). One or both of them may be omitted.
So. independent from the actual number of segments, we can just assume that an int represents the id and a string (i.e., everything else) represents the view.
/**
* Parse URL
*
* This method is meant to transform the human readable URL back into
* query parameters. It is only executed when SEF mode is switched on.
*
* #param array &$segments The segments of the URL to parse.
*
* #return array The URL attributes to be used by the application.
*/
public function parse(&$segments)
{
while (!empty($segments))
{
$segment = array_pop($segments);
if (is_numeric($segment))
{
// It's the ID
$vars['id_tsi'] = (int) $segment;
}
else
{
// It's the view
$vars['view'] = $segment;
}
}
return $vars;
}
This is my controller structute:
controllers
|
|__ posts
|
|__post.php
i have removed directory name from the url by changing in the routes.php file
$route['post/posts_controller'] = 'posts/post/posts_controller';
but now i want if anybody hits the complete url with the directory name i.e. http://localhost/url_routing/posts/post/posts_controller
then the page not found should appear.
This is a real problem with CodeIgniter, which can result in a LOT of duplicate content for search engine. The only workaround I found is to overwrite the Router to only use the routes.php and not folders / controllers names.
application/core/MY_Router.php
class MY_Router extends CI_Router {
/**
* Parse Routes
*
* Matches any routes that may exist in the config/routes.php file
* against the URI to determine if the class/method need to be remapped.
*
* #return void
*/
protected function _parse_routes()
{
// Turn the segment array into a URI string
$uri = implode('/', $this->uri->segments);
// Get HTTP verb
$http_verb = isset($_SERVER['REQUEST_METHOD']) ? strtolower($_SERVER['REQUEST_METHOD']) : 'cli';
// Loop through the route array looking for wildcards
foreach ($this->routes as $key => $val)
{
// Check if route format is using HTTP verbs
if (is_array($val))
{
$val = array_change_key_case($val, CASE_LOWER);
if (isset($val[$http_verb]))
{
$val = $val[$http_verb];
}
else
{
continue;
}
}
// Convert wildcards to RegEx
$key = str_replace(array(':any', ':num'), array('[^/]+', '[0-9]+'), $key);
// Does the RegEx match?
if (preg_match('#^'.$key.'$#', $uri, $matches))
{
// Are we using callbacks to process back-references?
if ( ! is_string($val) && is_callable($val))
{
// Remove the original string from the matches array.
array_shift($matches);
// Execute the callback using the values in matches as its parameters.
$val = call_user_func_array($val, $matches);
}
// Are we using the default routing method for back-references?
elseif (strpos($val, '$') !== FALSE && strpos($key, '(') !== FALSE)
{
$val = preg_replace('#^'.$key.'$#', $val, $uri);
}
$this->_set_request(explode('/', $val));
return;
}
}
return;
}
}
This will result in CodeIgniter only using your routes.php, so I you still want to use CI routing, then don't use it.
I am trying to update the popularity count of Magento's Tag module by interacting with this core function in Mage_Tag_Model_API
public function update($tagId, $data, $store)
{
$data = $this->_prepareDataForUpdate($data);
$storeId = $this->_getStoreId($store);
/** #var $tag Mage_Tag_Model_Tag */
$tag = Mage::getModel('tag/tag')->setStoreId($storeId)->setAddBasePopularity()->load($tagId);
if (!$tag->getId()) {
$this->_fault('tag_not_exists');
}
// store should be set for 'base_popularity' to be saved in Mage_Tag_Model_Resource_Tag::_afterSave()
$tag->setStore($storeId);
if (isset($data['base_popularity'])) {
$tag->setBasePopularity($data['base_popularity']);
}
if (isset($data['name'])) {
$tag->setName(trim($data['name']));
}
if (isset($data['status'])) {
// validate tag status
if (!in_array($data['status'], array(
$tag->getApprovedStatus(), $tag->getPendingStatus(), $tag->getDisabledStatus()))) {
$this->_fault('invalid_data');
}
$tag->setStatus($data['status']);
}
try {
$tag->save();
} catch (Mage_Core_Exception $e) {
$this->_fault('save_error', $e->getMessage());
}
return true;
}
In my controller I have this :
public function clickAction()
{
$tagString = $this->getRequest()->getParam('tag');
$tagByName = Mage::getModel('tag/tag')->loadByName($tagString);
$tagId = $tagByName->getTagId();
$basePopularity = ['base_popularity' => '13']; // hard coding while testing
Mage::getModel('tag/api')->update($tagId, $basePopularity, 1);
}
If I put a log statement in this part of the update function :
try {
// log stuff
$tag->save();
}
I can see it makes it to that try but there is no change in the data. What did I screw up? Any other ideas on how I can update the popularity of a tag through a controller? Using this same method and adding 'name' => 'blah' to that $data array parameter works fine..
I also found in Mage_Tag_Model_Indexer_Summary.php this method defined in the PHPdoc * #method Mage_Tag_Model_Indexer_Summary setPopularity(int $value) Maybe that is what I need... can someone provide an example showing how I could use that magic setter?
Try adding Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID); at the start of your clickAction function. base_popularity can only be updated from admin store.
I want both these urls:
/admin/users/add
and
/admin/users/3/edit
to point to edit($user_id = 0) function in my users controller. The number 3 in the second url has to be passed to the $user_id parameter.
How can I do this in a smooth way?
By setting up a route in application/config/routes.php:
$route['admin/users/add'] = "users/edit";
$route['admin/users/(:num)/edit'] = "users/edit/$1";
If you want this to work for other controller too, you can do this:
$route['admin/(:any)/add'] = "$1/edit";
$route['admin/(:any)/(:num)/edit'] = "$1/edit/$2";
Or the same, using regular expressions:
$route['admin/([a-z]+)/add'] = "$1/edit";
$route['admin/([a-z]+)/(\d+)/edit'] = "$1/edit/$2";
As an alternative to separate your logic.
I generally have two controllers that both speak to the same view.
admin/user/add
admin/user/edit/3
Both point to the view
admin/user_form.php
Which then access a save_user() method when the form has been posted.
But as Mischa said, by setting up routes you can point pretty much any url to any method.
Can you do this
public function users ($type, $id = null)
{
if ($type === 'edit')
{
// do edit stuff
}
else
{
// ad add stuff
}
}
Sulotion:
function _remap($method)
{
$param_offset = 2;
// No method, point to...
if (!method_exists($this, $method))
{
if (is_numeric($method) || $method == 'add')
{
// Show single
$param_offset = 1;
$method = 'show';
}
else
{
// Index
$param_offset = 1;
$method = 'index';
}
}
// Since all we get is $method, load up everything else in the URI
$params = array_slice($this->uri->rsegment_array(), $param_offset);
// Call the determined method with all params
call_user_func_array(array($this, $method), $params);
}