Joomla Component MVC variable passing between View and Controller - php

I am relatively new to Joomla and the way they implement an MVC arcitecture. It is slighty different to how I am used to it (Code Igniter, etc) and I am having a few issues simply passing data to the view.
I have created a function in the controller called 'getInitClubs' which sould be run automatically when the page runs, therefore I have made a call to this function from the 'view.html' file.
Here is my code:
Controller function:
public function getInitClubs() {
$model =& $this->getModel('directory');
$init_clubs = $model->clubResults($conds = array());
return $init_clubs;
}
Model Function:
public function clubResults($conds) {
$query = "SELECT * FROM vyj20_contact_details";
if(isset($conds['city'])) {
$query .= " WHERE state = '" . mysql_escape_string($conds['city']) . "'";
}
if(isset($conds['suburb'])) {
$query .= " AND suburb = '" . mysql_escape_string($conds['suburb']) . "'";
}
$this->_db->setQuery($query);
$results = $this->_db->loadObjectList();
return $results;
}
Now i know the model and controller code works, this is not the issue, the issue is actually pulling the results from the controller function 'getInitClubs' and showing them through the view.
How do I call the controller function from the view (like I would on Code Igniter MVC) in order to collect results for display? I have tried and tried but just can't seem to figure it out!
Thanks

The JView instances has getModel() method. You get the model instance you access a static registry, which is shared between all components. In the JController instance you should change the state of that model and in the JView instance you should pulling out the data.
Views in MVC design pattern are supposed to acquire information from model layer and render it using templates or, in some cases, just send a simple HTTP header. In this aspect Joomla has a surprisingly good take on MVC pattern.
P.S. since PHP 5.0 was released (some time around 2005th), you do not need to use references when assigning objects. It is actually harmful, because it messes with refcount.

You controller function should be like.
$model =& $this->getModel('directory');
$init_clubs = $model->clubResults($conds = array());
$view = $this->getView('view_name', 'html'); // get the view
$view->assignRef('data_list', $init_clubs); // set the data to the view
$view->display(); // show the view
Read more
Developing a Model-View-Controller Component
Model-View-Controller
Developing a Model-View-Controller Component/
Model View Controller

Related

Right place to put query in OOP application

I want to build a simple blog application with PHP using OOP concept. So basically I have a Blog class and a Database Class. In Blog class I have a method called "createANewBlog()" which takes a blog text, and a database connection. for example:
class Blog{
public $id;
public $text;
public function createANewBlog($inText, $db)
{
$this->text = $inText;
$this->id = $db->create($inText);
return true;
}
}
so basically this function call a create() function in database class to get the last inserted Id.
class DB{
function create($intext){
$sql = "INSERT INTO....... ";
then i will send the last inserted id;
}
}
In the index controller I will simply create a blog object and call that method to create a new object.
Now my question is "Is it the right way to code in OOP" or I sould call the Query inside the blog class createANewBlog() function like:
createANewBlog($inText, $db){
$this->text = $inText;
$this->id = $db->execute("INSERT INTO .....");
return true;
}
please help me as I have no idea where is the right place to put the query(Inside the blog class or inside the databse class).
Your structure is some what right but the best practice is to isolate each thing according to their work.
So there would be following things.
Model (Blog class)
Database Connection class
Blog DAO Class
Controller
View
DAO (data access object) is an object that provides an abstract
interface to database.
So always use DAO to make communication between your model and database. It may contain insert, read, delete, find, filter methods/functions.
Uses of the above things are as follow,
Model should contain fields/properties of entity with Getter and setter methods.
Database connection class should contain only methods/logic to connect to database.
DAO class should contain all the logic of database operations.
Controller should have pipeline between views/models/DAOs.
View should contain only code to render the data without writing business logic in it.
This way you will keep it simple,robust and maintainable.
The idea of OOP is to create great application structure. In great application you need to use modular technique. i'll not giving you some big chunk of information which you need to follow . I'll rather giving you a tactics that i followed while i was learning OOP for the first time .
Let me give you an example with code!:
You're working with a database connection , so create a class that will store all the database connection and other connection stuff.
In here i created class called connection_admin
Class connection_admin {
protected $_link;
//If You Delete This Everybody of the Team Will send you a serial killer to kill you ......... :v :v
function __construct($host,$user,$pass,$db){
$this->_link = mysqli_connect($host,$user,$pass);
mysqli_select_db($db,$this->_link);
}
public function query($sql){
$result = mysqli_query($sql);
$this->confirm_query($sql);
return $result;
}
public function confirm_query($sql){
if (!$sql) {
# code...
die('Query Failed'. mysql_error());
}
}
public function count_matched_id($queried_output){
return mysqli_result($queried_output, 0);
}
}
Then i created a global object like "init.php" , which i'll include everywhere in my project.
<?php
include 'function/admin_connection.php';
$Connection = new connection_admin('localhost','root','','my_cart');
And now it's time to require them all in all .php files..
Then in the view files you just need to call $Connection->query() to query database
THADAAAAA!!
Note: it's not a very good use of php's OOP feature , but it'll teach
you how to use OOP . after that try to follow MVC structure.

Email Templating in yii with MVC itself

I am designing an Email controller with actions like actionRegisterEmail and actionForgotPasswordEmail.
This would help me to view the emails in browser also while assigning dummy data if data is not set.
class EmailController extends Controller
{
public $layout='email';
public function actionForgotEmail(ResetPasswordEmail $forgotModel=null){
if($forgotModel == null){
$forgotModel = new ResetPasswordEmail;
$forgotModel->name = "John Doe" ;
$forgotModel->link = "a url" ;
}
return $this->render('reset_password',$forgotModel);
}
}
When I'll be sending this emails I will be instantiating the controllers and fetching their returned html which they return with $this->render.
The idea is good according to me but yii doesn't allow me to call action methods on instantiated controllers like
$emailController = Yii::app()->createController('email');
$vary = $emailController->actionForgotEmail($reset);
todb_and_mail($vary);
.
This way I can mail the rendered html and also test with dummy. But I have come across many posts which says do not instantiate controller use components.But I want to have a seperate view and pass data to it.Do we have any more simpler alternative ?
Just to help anyone with the same doubt.I instantiated a dummy controller and set its layout and called the render method then.
class MailHelper extends CComponent {
public static function getEmail($view_template,$data){
$controller = new CController('Email');
$controller->layout = "email" ;
return $controller->render($view_template, $data, true);
}
}
This way I can get the functionality of passing variables and data to view.We are using static html for visibility of the view files directly from the browser, this was actually simple I made it complicated to get the other things involved thanks davey for guiding me right.

pass a variable from controller, through a model to a view file

I'm trying to understand how passing variables work exactly.
I've set a controller:
class indexController
{
public function calling()
{
$route = new Route():
$route->title = 'Register user';
$route->getview('users','register');
}
}
And a model:
class Route
{
public function getview($module,$filename)
{
require_once('templates/'.$module.'/'.$filename.'.phtml');
}
}
And a view file which has something like this:
<div class="title"><?php echo $this->title; ?></div>
How to set title for the view? Should I 'public' this var in controller, and get it while constructing model to use in my view file?
There are problems with your design but forgetting those this is a way you could do it.
public function var( $var, $val ) {
$this->vars[$var] = $val; // should disallow _view as a $var
}
public function getview($module,$filename)
{
$_view = 'templates/'.$module.'/'.$filename.'.phtml';
extract( $this->vars ); //creates variables for
require_once( $_view );
}
Use it like this
$route = new Route():
$route->var( 'title', 'Register user' );
$route->getview('users','register');
What gave you an impression that you are implementing MVC? Because from where stand, it looks like you have mixed up the responsibilities for each part of the pattern.
Here are the basics ..
MVC is an architectural design pattern, that is an expression of SoC principle. It separates the model layery (that is responsible for implementing domain business logic) from presentation layer. And within presentation layer it separates the parts that handle user input (controller) from logic that generates the user interface (view).
When applying this pattern to Web, the flow of information goes something like this:
controller receives request from users
controller alters the state of model layer and (maybe) the current view
view request necessary information from model layer
view produces a response to the user
What you have there is NOT a view, but simply a template. And what you have there is NOT model, but simply a class.
And now you questions:
How to set title for the view?
Your view should request the information, that it needs, from model layer:
namespace Views;
class Doclument
{
// ... some code
public function foobar()
{
$library = $this->serviceFactory->acquire('Library');
$title = $library->getCurrentDocument('title');
$content = $library->getCurrentDocument('content');
$this->template['main']->assign([
'title' => $title,
'body' => $content,
]);
}
// ... some more code
public function render()
{
/*
if any templates have been initialized,
here you would put code for combining them and
return html (or some other format)
*/
}
}
Off course, you would need to know, which document the user wanted to see .. that should be done in a controller:
namespace Controllers;
class Document
{
// ... again, some code, that's not important here
public function getFoobar( $request )
{
$library = $this->serviceFactory->acquire('Library');
$library->useLanguage( $request->getParameter('lang') );
$library->locateDocument( $request->getParameter('id') );
}
}
The $serviceFactory would be shared between both controllers and views, since it's how you interact with the model layer. This also gives you a way to initialize each service only once, without creating a dependence on global state.
Should I 'public' this var in controller, and get it while constructing model to use in my view file?
No.
Model layer (yes, it should be layer and not a class) should not be aware of anything from implementation of presentation layer. An actually, view should not be aware of controller's either.
Actually, having public variables in OOP is considered to be a bad practice (unless you are creating data structures .. think: stuff like binary trees). It causes your code to leak encapsulation.
P.S.
I'm trying to understand how passing variables work exactly.
That's basics of OOP. You should not be playing around with high-level constructs like MVC pattern, if you do not have a good grasp on OOP concepts, practices and methodology.
Look up thing called "dependency injection".

Initializing View, Template and Controller and Model is optional

I was too sleepy when I asked the question, so sorry for that, anyway to make things clear I prepared the question for 2 hours.
I'm trying to organize my code and decided to organize it mvc'ish(mvc-like), I don't know if I can follow all the principles, but I wanted to be at least close to that.
My application has a front-controller (dunno if my definition is right), so that all the http-request of my application will be passing through a single point, in my case the index.php in the root directory of my application.
Having said that I have set it up like that, you can imagine that I used .htaccess to direct all request to index.php.
I exploded the url and created an array out of it, $url[] like so. So whenever I access my app like this http://localhost/app/pagename it'll be accessing a controller (pagename_controller)
I did it like this :
$file = $controller_path . $page . '_controller.php';
if (file_exists($file)) {
require $file;
$class_name = ucfirst($page) . '_controller';
$target = new $class_name();
}
also I wrap it up in a Container, the 'decorator pattern', for future use, validations maybe.
like this :
$controller = new Wrap($target);
$controller->index();
I don't know if the use of $controller variable name is appropriate so please forgive me when it is all wrong.
I kinda think that I can setup my application like this :
user sends a request, how? by using the application means that he/she sends out a http-request, that will load the initial state of the application
As you can see in the diagram of my desired application structure, I was able to do only the first part which is to direct the request to a single entry (index.php)
Now the problems are the initialization of other parts of the application.
As of this moment, I have 3 files that I want to setup, but I am confused on how.
index_controller, index_view, Template
class Index_controller {
private $model;
private $view;
public function __construct(){
// optional model -> $this->model = 'index'
$this->view = 'index' //
}
public function index(){
$this->load->view($this->view)
}
}
class Index_view {
private $model;
private $template;
public function __construct(Model $model = null){
$this->template = new Template('default');
}
public function view() {
$this->template->assign('css', 'default_css'); // don't know if this is efficient
// or $this->template->assign('header', 'default_header');
// or $this->template->assign('sidebar', 'default_sidebar');
// or $this->template->assign('footer', 'default_footer');
// or any other things I want to use in the template
}
}
class Template {
public $data = array();
private $tmpl;
public function __construct($template) {
$this->tmpl = $template . '_tmpl.php';
}
public function assign($name, $value){
$this->data[$name] = $value;
}
// public function output
// function that will explode the data array and render it out as a webpage
// I'll create templates and
}
With that at hand, I want to know now how do I link those things together. At the moment I have a system folder that can contain classes, and I setup a autoloader for that folder.
I am thinking of creating a Controller class and View class that acts as the ActionFactory and ViewFactory as illustrated in the diagram, although I know that these are not their responsibilities.
I am thinking of this :
class Controller {
protected $load;
public function __construct() {
$this->load = new View();
}
}
class View {
public function __construct() {
// some things i don't know
}
public function view() {
// some things i don't know
}
}
What are your suggestions and comments in my setup. How can I initiate the triad?
Well, let's not get stuck on your implementation details too much. You can go read about securing your framework at some other time. Let's deal with your question...
I actually created a framework that works along the lines you are trying to implement. I think what you are missing is a RoutingHandler class. Routing is the physical manipulation of the URL, which tells your application which Controller to load, and which Action to run.
In my world I also have Modules, so the basic routing scheme is
Module -> Controller -> Action
These three items map to my URI scheme in that fashion. Variables can be appended also like so...
http://www.domain.com/module/controller/action/var1/val1/var2/val2
So, what happens after the URI is parsed, and control is passed over to the appropriate controller and action? Let's make some code up to demonstrate a simple example...
<?php
class indexController extends Controller {
protected function Initialize() {
$this->objHomeModel = new HomeModel;
$this->objHeader = new Header();
$this->objFooter = new Footer();
$this->objHeader
->SetPageId('home');
}
public function indexAction() {
$this->objHeader->SetPageTitle('This is my page title.');
}
}
?>
In the Initialize method, I'm setting some controller-wide stuff, and grabbing an instance of my Model to use later. The real meat is in the indexAction method. This is where you would set up stuff to use in your View. For example...
public function randomAction() {
$this->_CONTROL->Append($intSomeVar, 42);
}
_CONTROL is an array of values that I manipulate and pass onto the View. The Controller class knows how to find the right template for the View because it is named after the Action (and in a sibling directory).
The Controller parent class takes the name of the action method and parses it like so...
indexAction -> index.tpl.php
You can also do some other fun stuff here, for example...
Application::SetNoRender();
...would tell the Controller not to render inside a template, but just complete the method. This is useful for those situations where you don't actually want to output anything.
Lastly, all of the controllers, models, and views live inside their own directory like so...
my_module
controllers
indexController.class.php
someotherController.class.php
:
:
models
HomeModel.class.php
:
:
templates
index.tpl.php
someother.tpl.php
:
:
I could go on, but I'm writing this from memory, and there are some wrinkles here and there, but hopefully this gives you food for thought.

PHP views relate controllers

I would like to implement controllers that connect to any specific views like MVC does. I'm not using any framework that provided in PHP.
So, I need some guide and advice on doing it.
I have some controllers and views. For my views,i would like to just output my data only.
My concern now is how my function (like create() ) in controllers, can get all the $_POST['params'] that users input data in my views/create.php, and create a new Model in the create() controllers's function.
So,right now, i'm thinking to do in this way, I will create MyViews class in my controllers folder. The purpose is loading the specific views and get all the $_POST params into an object. Then, every controllers like Users_controllers, will create MyViews. In the function of Users_controllers, like create(), destroy(), I might use the function in MyViews to load specific views to load the object.
I found a source that load views
<?php
class MyView {
protected $template_dir = 'templates/';
protected $vars = array();
public function __construct($template_dir = null) {
if ($template_dir !== null) {
// Check here whether this directory really exists
$this->template_dir = $template_dir;
}
}
public function render($template_file) {
if (file_exists($this->template_dir.$template_file)) {
include $this->template_dir.$template_file;
} else {
throw new Exception('no template file ' . $template_file . ' present in directory ' . $this->template_dir);
}
}
public function __set($name, $value) {
$this->vars[$name] = $value;
}
public function __get($name) {
return $this->vars[$name];
}
} ?>
hmm,I have no idea How I can detect the _POST params
if(isset($_POST['Post']))
{
$model->attributes=$_POST['Post'];
if($model->save())
$this->redirect(array('view','id'=>$model->id));
}
this is the Yii framework I observed. How could I detect params whether is $_POST or $_GET after load a specific views.
Any guidance and advice to archive my tasks?
Unrelared to question You have one major problem: your ability to express what mean is extremely limited. The question, which you asked, was actually unrelated to your problem.
From what I gather, you need to detect of user made a POST or GET request. Do detect it directly you can check $_SERVER['REQUEST_METHOD'], but checking it withing controller might be quite bothersome. You will end up with a lot of controller's methods which behave differently based on request method.
Since you are not using any of popular frameworks, is would recommend for you to instead delegate this decision to the routing mechanism.
A pretty good way to handle this, in my opinion, is to prefix the controller's method names with the request method: postLogin(), getArticles() etc. You can find few additional example here. If there is a POST request, it will have something in $_POST array.
What are calling "views" are actually templates. If you read this article, you will notice, that the code there is actually an improved version of your MyView. Views are not templates. Views are instances which contain presentation logic and manipulate multiple templates.
P.S. If you are exploring MVC and MVC-inspired patterns in relation to PHP, you might find this post useful.

Categories