How to convert a function from PHP Procedural to PHP MVC? - php

I have this function on my View Page, which truncates some data to present it on my table.
function truncate($mytext) {
//Number of characters to show
$chars = 100;
$mytext = substr($mytext,0,$chars);
$mytext = substr($mytext,0,strrpos($mytext,' '));
return $mytext;
}
I set a local variable for my dynamic text:
$mydescription = $value['PROBLEM_DESCRIPTION']
On the same page, I have this:
echo '<td><p>' .truncate($mydescription). '; ?></p><</td>
And it works perfect, so my question is how can apply this on an MVC architecture using Codeigniter?
If somebody has an idea let me know, thanks!!!

You should at least define this function as a method of your model (where you take this description from).
class TextModel extends CI_Model {
...
public function getShortDescription(){
$chars = 100;
$mytext = substr($this->mytext,0,$chars);
$mytext = substr($mytext,0,strrpos($mytext,' '));
return $mytext;
}
}
And the in your controller smth along the lines of:
class Blog extends Controller {
function index()
{
$this->load->model('TextModel');
$data['short_description'] = $this->TextModel->getShortDescription();
$this->load->view('blogview', $data);
}
}
And at last, in your view:
echo '<td><p>'.$short_description.'</p></td>';
I'm not familiar with CodeIgniter, but I guess any data manipulation should be done in models, thus you will keep your controllers 'thin' and won't violate MVC paradigm.

Since you already have a working code, all you need to decide is where in the MVC paradigm of CI should this be transferred to. I would suggest putting this inside a helper. Helpers in CI are just what the name suggests, a simple php file with a bunch of functions that help you to get certain tasks done. Suppose you put this inside a file called 'utility.php' You could then include this file wherever you need using
$this->load->helper('utility');
and then call the truncate function.
Now, if you have a bunch of related tasks which you want to neatly organize in a class based structure you could create your own CI library. Suppose you created a library named 'truncate', then similar to helpers these are loaded as
$this->load->library('truncate');
Personally, for a bunch of utilities I would just put them all into a helper instead of extending core CI classes or creating a custom library.

You could do it in the controller:
class Something extends CI_Controller{
public function index(){
$data['mytext'] = $this->_truncate('some text to truncate');
//truncated text will be available in the view as $mytext
$this->load->view('some_view', $data);
}
private function _truncate($text = NULL){
if($text){
$chars = 100;
$mytext = substr($text,0,$chars);
$mytext = substr($text,0,strrpos($text,' '));
return $mytext;
}
}
}
Edit:
You are calling db stuff in your view which is entirely not Codeigniter MVC.
This is what it might look like in MVC:
Controller
class Something extends CI_Controller{
public function index(){
$test_text = $this->my_model->get_text();
$data['test_text'] = $this->_truncate($test_text);
//truncated text will be available in the view as $test_text
$this->load->view('some_view', $data);
}
private function _truncate($text = NULL){
if($text){
$chars = 100;
$mytext = substr($mytext,0,$chars);
$mytext = substr($mytext,0,strrpos($mytext,' '));
return $mytext;
}
}
}
Model
class My_Model extends CI_Model{
public function get_text(){
//$this->db->get_where....or other db functions
return "testing text... this is only a test";
}
}
View
<html>
<body>
<b><?php echo $test_text; ?></b>
</body>

The current answers explain that you can add the method to the model and also the controller.
Functionally, this is no problem, as you said the function works perfectly wherever you place it.
What happens when you need to call the same method in another controller? Or with a different model?
It is most likley you will end up with some code duplication.
As a possible soultion, you could create a library of classes that allow you to keep all you string
manipulation in one place. Simply add more methods to your class...
// example/libary/path/TextFormatter.php
class TextFormatter
{
protected $_text = '';
public function __construct($text)
{
$this->_text = $text;
return $this;
}
public function truncate($maxChars = 100)
{
$truncated = substr($this->_text, 0, $maxChars);
$truncated = substr($truncated, 0, strrpos($truncated,' '));
return $truncated;
}
public function stripHtml()
{
///.....
}
public function doSomethingElseWithText()
{
}
}
Then in the controller...
// Controller.php
class SomeController extends Controller
{
public function index()
{
$formatter = new TextFormatter('Example text string');
$data['formattedText'] = $formatter->truncate();
}
}
The only caveat is the TextFormatter class needs to be autoloaded/callable from wherever you use it.

Controller: create a controller truncate.php.
<?php
Class Truncate extends CI_Controller {
function __construct() {
parent::__construct();
}
function truncate_text($mytext) {
//Number of characters to show
$chars = 100;
if(empty($mytext))
echo '$mytext is empty.';
$mytext = substr($mytext,0,$chars);
$data['mytext'] = substr($mytext,0,strrpos($mytext,' '));
$this->load->view('truncate_view',$data);
}
View: create a view file truncate_view.php
<?php
echo '<td><p>'.$mytext.'</p></td>';
//Write your other view code if any are present.
?>

Related

How to use other class methods inside of another class in same file?

I've a scenario where i have to use a Class that extends another class which is not a codeigniter class and inside of the method, i need to call another method to perform Database operation.
How can i achieve?
<?php
require_once(APPPATH.'third_party/OauthPhirehose.php');
class Get extends CI_Controller
{
function __construct()
{
parent::__construct();
$this->load->model('tweets_model');
}
public function getall()
{
$tags = $this->tags_model->get();
$result = $tags->row();
$first = $result->first_tag;
$second = $result->second_tag;
return array($first, $second);
}
public function insert_raw_tweet($raw_tweet, $tweet_id)
{
$this->tweets_model->save_raw($raw_tweet, $tweet_id);
}
}
class Consume extends OauthPhire {
public function enqueueStatus($status) {
$tweet_object = #json_decode($status);
if (!(isset($tweet_object->id_str))) { return;}
$tweet_id = $tweet_object->id_str;
$raw_tweet = base64_encode(serialize($tweet_object));
echo $tweet_object->text . "\r\n";
// here i need to use top class method to insert data
//$this->tasks->insert_raw_tweet($tweet_object, $tweet_id);
}
}
$get_track = new Get();
$list = $get_track->getall();
$stream = new Consume(OAUTH_TOKEN, OAUTH_SECRET, Phirehose::METHOD_FILTER);
$stream->setTrack($list);
$stream->consume();
Load it just like you load a normal third party library stored in /library/ folder, use this method :
$this->load->library('OauthPhirehose');
Hope this works.

How to make variable that can be used in many views?

I have a project, it has a structure like this:
http://img526.imageshack.us/img526/2333/92348689.png
I want to make a variable like the following
$templatePath = $this->baseUrl('/application/templates/')`
and it can be used in many views, in many modules. I think I can do it by declaring the variable in Bootstrap.php (application) but I don't know how to do that.
Usually, I just place myself such variables into application bootstrap file. Here's an example:
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap {
protected function _initViewVariables() {
$this->bootstrap('View');
$this->view->fooValue = 'foo';
$this->view->barValue = 'bar';
$config = Zend_Registry::get('config');
if( $config->recaptcha->enabled ) {
$this->view->captcha = true;
$this->view->recaptchaPublicKey = $config->recaptcha->publicKey;
}
else {
$this->view->captcha = false;
}
}
}
I hope it helps!
Base Url is available after routing has been completed (routeShutdown hook) so accessing it in Bootstrap will not work .
So create a controller plugin inside preDispatch() do
public function preDispatch($req) {
$view = new Zend_View();
$view->placeholder('burl')->set(Zend_Controller_Front::getInstance()->getBaseUrl());
}
To access it inside view do like index.phtml
echo $this->placeholder('burl');
You could use the Zend_Registry.
In your bootstrap or wherever in your site just State
Zend_Registry::set("TagLine", "Have a Nice Day");
To use in a view just
<?= Zend_Registry::get("TagLine"); ?>
for extra credit you could also make a view helper for this (there is one with ZF2)
class My_View_Helper_Registry extends Zend_View_Helper_Abstract
{
public function registry($key)
{
return Zend_Registry::get($key);
}
}
In your bootstrap you will add a method like:
protected function _initSiteRegistry(){
Zend_Registry::set("Site_Name", "My Cool Site";
Zend_Registry::set("Site_TagLine", "Have a nice day";
}
Also if you are using the view helper approach you will also want to register the helper path.. you can do this in _initView in the bootstrap.
protected function _initView(){
$view = new Zend_View();
$view->doctype("HTML5");
$view->setEncoding("UTF-8");
$view->addScriptPath(APPLICATION_PATH."/local/views");
// set this as the viewRenderer's view.
$viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('ViewRenderer');
$viewRenderer->setView($view);
$view->addHelperPath("My/View/Helper/", "My_View_Helper_");
return $view;
}

how to load a header contents to be available in all the pages

i have a controller where there are many methods, i have to load my header in all the pages.
Currently i am using $data["query1"] = $this->mainmenumodel->getmainmenulist(); in all the methods for loading my header data.
I have more then 30 methods in each classes, so for this it is a bit difficult to write this $data["query1"] = $this->mainmenumodel->getmainmenulist(); in every method.
Is there anything I can do in a class so that it will be available for entire method.
controller.php
--------------------------------
---------------------------------
class mainmenusetups extends MY_Controller {
var $data = array();
public function __construct() {
parent:: __construct();
$this->load->helper('url');
$this->load->model('mainmenumodel');
$this->load->library('pagination');
parent::MY_Controller();
if ((int) $mainmenu_id > 0)
{
$query = $this->mainmenumodel->get($mainmenu_id);
$this->data->mainmenumodel->getmainmenulist();//how to specify it only once to be use for enitere class
$this->load->view('admin/setups/mainmenu/index', $data);
}
else if (!($this->input->post('mainmenu_id')))
{
$data["query"] = $this->mainmenumodel->fetch_mainmenu_data($config["per_page"], $page);
$data["links"] = $this->pagination->create_links();
$this->data->mainmenumodel->getmainmenulist();//how to specify it only once to be use for enitere class
$this->load->view('admin/setups/mainmenu/index', $data);
}
//--------like this ,i have many methods and condition in every page----------- }
You're getting a little muddled, I think.
Inherit all your controllers from MY_Controller. On MY_Controller, set your header to a "global" variables like:
$this->data['header'] = $this->set_header();
function set_header()
{
//all my good logic, including:
return $this->load->view('my_header', '', true); // true will pass to a variable
}
Now, on all your inherited controllers, whenever you load up a view always use $this->data for your data; $this->data['header'] will be included & you can print it out at the top of your template/page

what are some lines meaning in magento.?

Supposed there is a function in a \AW\Blog\Model\post.php.there is a function in it.
public function PreNext($type){
$id = $this->_data['post_id'];
$blog = Mage::getResourceModel('blog/post_collection');
$blog->getSelect()->where('post_id>?',$id);
return $blog->getFirstItem();
}
why it write $this->_data['post_id']; could i write it with another.
what are the four lines meaning which in the function within magento.? many thanks.
the post.php
class AW_Blog_Model_Post extends Mage_Core_Model_Abstract{
const NOROUTE_PAGE_ID = 'no-route';
protected function _construct(){
$this->_init('blog/post');
}
public function load($id, $field=null){
return $post = parent::load($id, $field);
}
public function noRoutePage(){
$this->setData($this->load(self::NOROUTE_PAGE_ID, $this->getIdFieldName()));
return $this;
}
public function getShortContent(){
$content = $this->getData('short_content');
if(Mage::getStoreConfig(AW_Blog_Helper_Config::XML_BLOG_PARSE_CMS)){
$processor = Mage::getModel('core/email_template_filter');
$content = $processor->filter($content);
}
return $content;
}
public function getPostContent(){
$content = $this->getData('post_content');
if(Mage::getStoreConfig(AW_Blog_Helper_Config::XML_BLOG_PARSE_CMS)){
$processor = Mage::getModel('core/email_template_filter');
$content = $processor->filter($content);
}
return $content;
}
public function loadByIdentifier($v) {
return $this->load($v, 'identifier');
}
}
This is code of a custom extension, so only people having this extension can know, what this post.php file contains, and whether you can get the value using other ways than $this->_data['post_id'].
If the extension uses standard Magento Getters/Setters, maybe $this->getPostId() may work, too.
The rest loads a collection of records having a post_id greater than $this->_data['post_id'], but returns only the first record found.
Update
The class you posted extends
Mage_Core_Model_Abstract
which in turn extends
Varien_Object
in a standard Magento OOB.
The Varien_Object class defines the standard getters/setters I was talking about, so yes, you can also use $this->getPostId() to get the value.
To understand how these getters/setters work, I'd recommend to check the Varien_Object and read about PHPs magic methods, like __call(), __get() and __set().

Going from the Controller to the View

I am working on creating my own very simple MVC and I am brainstorming ways to go from the controller to the view. Which involves sending variables from a class to just a plain old PHP page.
I am sure that this has been covered before, but I wanted to see what kind of ideas people could come up with.
//this file would be /controller/my_controller.php
class My_Controller{
function someFunction(){
$var = 'Hello World';
//how do we get var to our view file in the document root?
//cool_view.php
}
}
Some kind of hashtable is a good way to do that. Return your variables as association array which will fill all the gaps in your view.
Store your variables as a property in your controller object, then extract them when rendering
class My_Controller {
protected $locals = array();
function index() {
$this->locals['var'] = 'Hello World';
}
protected function render() {
ob_start();
extract($this->locals);
include 'YOUR_VIEW_FILE.php';
return ob_get_clean();
}
}
You can define those magic __get and __set methods to make it prettier
$this->var = 'test';
I'm also developing my own simple MVC and the most simple way to do it is ...
class My_Controller
{
function someFunction() {
$view_vars['name'] = 'John';
$view = new View('template_filename.php', $view_vars);
}
}
View class
class View
{
public function __construct($template, $vars) {
include($template);
}
}
template_filename.php
Hello, <?php echo $vars['name'];?>
I highly recommend you to take a look at PHP Savant http://phpsavant.com/docs/
I'd checkout Zend_View and how it accomplished view rendering.
You can get the source of View and AbstractView on github - unfortunaly I don't find the current repository (in svn) that easy to browse.
Essentially the view variables are contained in a View object (which your controller would have access to), then the template (plain old php document) is rendered inside that object. That method allows the template access to $this.
It would be something like:
<?php
class View
{
public function render()
{
ob_start();
include($this->_viewTemplate); //the included file can now access $this
return ob_get_clean();
}
}
?>
So in your controller:
<?php
class Controller
{
public function someAction()
{
$this->view->something = 'somevalue';
}
}
?>
And your template:
<p><?php echo $this->something;?></p>
In my opinion this pattern allows you much flexibility with the view.
I created my own MVC for the free PHP course I'm conducting for a handful of people wanting to get better at PHP.
By far the best way to do this is to use the Command + Factory pattern.
E.g.
interface ControllerCommand
{
public function execute($action);
}
In each controller:
class UserController implements ControllerCommand
{
public function execute($action)
{
if ($action == 'login')
{
$data['view_file'] = 'views/home.tpl.php';
}
else if ($action == 'edit_profile')
{
$data['view_file'] = 'views/profile.tpl.php';
$data['registration_status'] = $this->editProfile();
}
return $data;
}
}
From your main front controller:
$data = ControllerCommandFactory::execute($action);
if (!is_null($data)) { extract($data); }
/* We know the view_file is safe, since we explicitly set it above. */
require $view_file;
The point is that every Controllercommand class has an execute function and that returns its view and any data for that view.
For the complete MVC, you can access the open source app by emailing me at theodore[at]phpexperts.pro.

Categories