Am getting my hands wet with this whole MVC thing and am really lost. I have a mysql table tblowner (ownerid,ownername).
Now what I want is to view the detail and edit it.
created the MVC directories and began with index.php
index.php?view=owner&action=view
require('controllers/controller.php');
$controller=new controller();
controllers/controller.php
class controller {
function controller(){
//Check action and view.
$view="home";
$allowedViews=array("home","owner");
if(isset($_GET['view'])){
$view=strtolower($_GET['view']);
if (!in_array($_GET['view'],$allowedViews)){
$view="home";
}
}
//requested action?
$action="view";
if(isset($_GET['action'])){
$action=strtolower($action);
}
//require model based on view now.
$controllerClass=$view.'controller';
require('controllers/'.$controllerClass.".php");
$controller=new $controllerClass($action);
}
}
models/ownermodel.php
class ownermodel
{
//contains two methods: edit and view related. Thats all.
//**********************************************************************
function ownermodeledit()
{
//edits owner data. It is always update since program cames prefilled with data.
if (isset($_POST['btnedit']))
{
//save changes.
}
else
{//show form now.
$this->showEditForm();
}
}
//**********************************************************************
function showEditForm($msg = '')
{
if ($msg)
{
echo '<p class="error">' . $msg . '</p>';
}
$ownerInfo = $this->ownermodelview();
if (is_array($ownerInfo))
{
?>
<form action="index.php?action=edit&view=owner" method="POST" id="frmeditowner" name="frmeditowner">
Name: <input type="text" id="oname" name="oname" value="<?php echo $ownerInfo['ownername']; ?>"/>
<?php
}//if(is_array($ownerInfo)) {
else
{
echo '<p class="error">There was an error retrieving owner information</p>';
}
}
//**********************************************************************
function ownermodelview()
{
//views model. return an array here
$mydb = new dbACW();
$params = array();
$return = "";
$result = $mydb->runSelectQuery("SELECT * FROM tbllicencee LIMIT 1", $params);
if (is_array($result) && count($result) > 0)
{
$return = array();
foreach ($result as $info)
{
$return['ownerid'] = $info['id'];
$return['ownername'] = $info['ownername'];
}
}
return $return;
}
}
That calls e.g. ownercontroller.php providing the necessary action (i.e. edit). And the model is where am lost at.
For viewing owner info, a method in the model would return an array containing information and a method in the viewer would display that array in anyway.
But for actions such as edit, what's the role of the view at all? Where would the form to edit the info be made?
And the view...currently it is inform of OOP (with class stuff). But if view is supposed to make the job of a web author easier to play around design? If it has a bunch of PHP code inside it, what differentiates it from a model?
Sorry for the long post...
In MVC structure, there is three main terms - Model, View & Controller, which sometimes confuses people.
In Model, we basically defines the classes with for the db interactions. Say, if I am trying to create a school management system, then I would be creating a class student_model, in which I defines the functions that will write to db or read from db, etc. Like, readStudentDetails(), insertNewStudent(), etc.
In View, we just display the contents to the user. So, basically we don't do much tasks in here rather than just echoing the outputs in HTML. For example, we have a View named home.php. And it will contain just the html and some echoing of data. That's all. No major processing or calculations and other stuff is done in Views. It's just for outputting the data to the user only.
Controller is basically an intermediary between Model and View. So, it's in Controller class that accepts HTTP requests, calls the model classes to do db interaction and access the views to display the outputs, etc.
If you are looking for a simple existing framework to learn this, try CodeIgniter: https://ellislab.com/codeigniter/user-guide/overview/mvc.html
It's pretty easy to follow the documentation and it's simple to use too. But there are other frameworks, like Zend Frameworks, etc. But for beginners, in my opinion, CodeIgniter is the best!
Hope this helps.
Related
Initial setting / premise
I'm trying to figure out what would be the best practice for handling a saving of parent and child model with single controller-action, but handling saving on model-level.
I have an "form"-object which has related model "json_object". This object is passed to controller with AJAX:
form: {
id: 12,
title: "something",
json_object_id: 223, // <-- exists within form -table
json_object: { id: 223, description: 'something else' }
}
Both are represented on database on their own tables and have their own class models. Relations also exists on model-level. Querying of form WITH json_object included as part of results already works.
Current solution
I'v been using lots of static model methods for saving in order to separate saving logic from controller to model. Due to this I'v been passing an object representation of request-input to models save. For an example:
// FormController.php
Form:::saveForm($request->input('form'));
// FormModel.php
public function jsonObject() {
return $this->belongsTo('App\JsonObject');
}
public static function saveForm(Object $in) {
if(isset($in->id) && $in->id > 0) {
$out = Form::find($in->id);
$out->fill((array) $in);
} else {
$out = new Form();
$out->fill((array) $in);
}
// ... any custom saving logics are handled here as well
if(isset($in->json_object)) {
// handle processing of json_object;
}
$out->save();
return $out;
}
With this structure I'm able to pass related model as anonymous object. As "$in" is unrelated to form model class I'm able to access it's anonymous content as well.
Problem / Question
I'v been trying to figure out how this could be archieved by using an instantiated model. On controller level I would most likely do:
public function store(Request $request)
{
if($request->input("form.id") > 0) {
$form = Form::find($request->input("form.id"));
} else {
$form = new Form();
}
$form->fill($request->input("form"));
$form->saveForm();
return response()->json($form);
}
What would be the preferable way to implement processing (saving) of included related model as part of model-level logic? Note: I don't want to introduce JsonObjects saving logic as part of controller logic!
I could pass $json_object as an attribute of saveForm-method, but it sounds poor practice. On the other hand if I represent it as $attribute and $fillable feature of "Form" then saving fails due to attribute not really existing as an column on form-table.
The main goal here is to try to handle most of saving logic on model level. I don't want to represent any model-level logic on controller level, so that's why I want to represent the handling of related model on models method. "SaveForm()"-method would first handle saving of form and then call JsonObject::save() / JsonObject::saveObject(), which would handle processing of JsonObject on its own capsulation (in order to preserve code reusability).
One possible solution
I could add $json_object to formModel.php as ...
public $json_object;
... and manually fill this property on controller.
...
$form->fill($request->input("form"));
$form->json_object = $request->input("form.json_object");
...
// Then use it on formModel:
public function saveForm() {
...
if(isset($this->json_object)) {
// Handle saving logics
dd($this->json_object);
}
NOTE: fill-method doesn't fill json_object to form! $fillable seems to work only against $attributes array, and json_object is not column within forms-table.
Still, is there a better way for handling relations?
I just moved from my "everything-in-functions" coding style to OOP in PHP. I know, there are a lot of sources in order to code properly, but my main problem is, after reading so many tutorials about coding a blog/cms/any web app in OOP it's quite not that understandable to me to code it the right way.
I was told the concept of OOP is basically close to the real world.
So properties are just properties of any object and methods are like what the object should do. But I can't really understand how to use these properties and methods in a web app. In the real world, it's easier than in a web application for me, for instance:
Let's say we want to create a human named "Paul" and he should drive a car.
class human
{
public $gender;
public $name;
function __construct($inGender=null, $inName=null) {
$this->gender = $inGender;
$this->name = $inName;
}
public function driveCar() {
//Let the car be driven.
//...
}
}
$paul = new human('male','Paul');
$paul->driveCar();
Alright, but when it comes to an object in a web application, let's say I want to code a blog system specifically let's focus the posts. Properties could be id, name, content, author of a post, BUT what does a post actually do? It can't really perform an action so I would code it like this:
class post
{
public $id;
public $title;
public $content;
public $tags;
//Overloading the Variables
function __construct($inId=null, $inTitle=null, $inContent=null, $inTags=null) {
if(!empty($inId) || $inId == 0) {
$this->id = $inId;
}
if(!empty($inTitle)) {
$this->title = $inTitle;
}
if(!empty($inContent)) {
$this->content = $inContent;
}
if(!empty($inTags)) {
$this->tags = explode(' ', $inTags);
}
}
}
//In order to pass multiple posts to an constructor I would use a foreach loop
$posts[] = new post(0,'Hello World', 'This is a test content','test blog oop');
$posts[] = new post(1,'Hella World!', 'This is made my myself','test test test');
//Usage in a template
<?php foreach($posts as $post): ?>
<h1><?= $post->title;?></h1>
<p><?= $post->content;?></p>
<?php endforeach; ?>
The problem here is the method does not do anything, what is not supposed to do I guess. And another problem would be, when I would store data into an array, I can't use a single array with data of posts as several parameters for the constructor. Even if this was a single post, how to accomplish the passing of data as an array properly in order to use the array as the parameters? Maybe I just coded it not the best way, but what would be a better way? I heard of setter and getter and magic methods. What would here best practise?
Alright, but another question. How would I program the create/delete posts functionality, new classes or new methods? I can't really imagine anything of this in the real world concept.
This all is not that clear for me since it's nowhere explained on any tutorial.
Help would be amazing.
regards
answering all your questions needs a book as understanding the oop concept completely needs much reading and practicing.
But to answer your post class I give you an easy to use example where you can create a class which will help you create, read, delete and update posts.
This class can be used in all your projects as it's a class and classes are simply there to make our life easier.
So here we go:
first we create the class:
class posts
{
//we just need a post title and a post content for the new post.
//So we create two properties for post_title and post_content
private $post_title; //the variables are private so we we restrict access the them from outside the class.
private $post_content;
private $connection;
//you really don't need here the _constructor function, but it's your choice.
//For example you can do all your database connection stuff in the constructor method to make it easy for users.
//So if someone creates a posts object it is obvious that he's going to make some interactions with the database so you open connections in your constructor.
//next we create the methods for our posts class
public function __constructor()
{
//here you created the connection to your database. You can retrieve
//the parameters to the mysqli_connect from a eg. config.php file to make your class more dynamic.
$this->connection = mysqli_connect('hostname', 'username', 'password', 'databasename');
}
public function create_post($title, $content)
{
$this->post_title=$title;
$this->post_content=$content;
$query="INSERT INTO posttable(id,title,content) VALUES('$this->post_title','$this->post_content')";
$result=$mysqli_query($this->connection,$query);
}
public function update_post($post_id, $post_title, $post_content)
{
}
public function delete_post($post_id)
{
}
public function view_posts($query, $fields)
{
$result=mysqli_query($this->connection, $query);
$finalData=array();
while ($row=mysqli_fetch_assoc($data)) {
foreach ($fields as $field) {
array_push($finalData, $row[$field]);
}
}
return $finalData;
}
}
//now we're going to use the class.
$post=new posts(); //a new posts object is created and the __construct method opened connection to db.
$post->create_post('some title', 'some content');//inserted new post into database.
$post->update_post($id, $content, $title);//you've just updated a post
$post->delete_post($id);//you've just deleted a post.
//getting posts
$query="SELECT * FROM posts";
$fields=array('id','title','content');
$all_posts=$post->view_posts($query, $fields);
//now you have $all_posts which is filled with an array of all posts from the posts table.
//now you can loop through it and show it on your page.
for ($i=0; $i<=count($all_posts); $i++) {
echo '<h1>'.$mydata[$i].'</h1>';
$i++;
echo '<h2>'.$mydata[$i].'</h2>';
$i++;
echo '<h3>'.$mydata[$i].'</h3>';
}
I didn't implement the update and delete method code but I think it's easy for you to write it by yourself.All my goal was to show you how you can use oop in your web applications. I personally have nearly 50 classes written by myself and do all the major jobs for nearly all possible web application tasks. It's up to you how you create your classes. Just for your knowledge, oop programming needs training and experience. You can do a task in multiple forms and with different solutions. You can find dozens of books which teach you oop design who's concept and goal is to teach you how to design a class to the best way.
I hope I was helpful
i need differents results from a model but i don't understand if it is correct make a single call and leave to model all the work or make more calls and collect the result to pass to the view when tables aren't joined or when i need fetch one row from a table and differents rows from others.
First example (more calls, collect and send to view):
CONTROLLER
// call functions of model
$modelName = new Application_Model_DbTable_ModelName();
$rs1 = $modelName->getTest($var);
$rs2 = $modelName->getTest2($var2);
// collect data
$pippo = $rs1->pippo;
if ($rs2->pluto == 'test') {
$pluto = 'ok';
} else {
$pluto = 'ko';
}
// send to view
$this->view->pippo = $pippo;
$this->view->pluto = $pluto;
MODEL
public function getTest($var) {
...
select from db...
return $result;
...
}
public function getTest2($var) {
...
select from db...
return $result;
...
}
Second example (one call, model collect all data, return to controller and send to view):
CONTROLLER
// call one function of model
$modelName = new Application_Model_DbTable_ModelName();
$rs = $modelName->getTest($var);
MODEL
public function getTest($var) {
...
select from db...
if ($result > 0) {
call other function
call other function
collect data
return $result;
...
}
Thanks
There's no one correct answer to this question, but in general, you should endeavor to keep your business logic in one place. Think of it as, "thin controller, thick model." I.e., keep the controllers as small and simple as possible and put all the business logic in the models.
There seems to be a few questions here:
But if i don't need to interact with db and i need only a simply
function is better put that function in model? For example:
CONTROLLER:
public function printAction() {
$data = $this->getRequest()->getPost();
$label = "blablabla";
$this->view->label = $label;
}
first, in the context of Zend Framework this particular example doesn't make much sense. The whole point of the controller is to populate the view template. However, I do get the idea. I would point you to Action Helpers and View helpers as a means to address your concerns. You can always add a utility class to your library for those pieces of code that don't seem to fit anywhere else.
Action Helpers typically are employed to encapsulate controller code that may be repetitive or reusable. They can be as simple or as complex as required, here is a simple example:
class Controller_Action_Helper_Login extends Zend_Controller_Action_Helper_Abstract
{
/**
* #return \Application_Form_Login
*/
public function direct()
{
$form = new Application_Form_Login();
$form->setAction('/index/login');
return $form;
}
}
//add the helper path to the stack in the application.ini
resources.frontController.actionhelperpaths.Controller_Action_Helper = APPLICATION_PATH "/../library/Controller/Action/Helper"
//the helper is called in the controller
$this->_helper->login();
a View helper does the same thing for the view templates:
class Zend_View_Helper_PadId extends Zend_View_Helper_Abstract
{
/**
* add leading zeros to value
* #param type $id
* #return string
*/
public function padId($id)
{
return str_pad($id, 5, 0, STR_PAD_LEFT);
}
}
//in this example the helper path is added to the stack from the boostrap.php
protected function _initView()
{
//Initialize view
$view = new Zend_View();
//add custom view helper path
$view->addHelperPath('/../library/View/Helper');
//truncated for brevity
$viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper(
'ViewRenderer');
$viewRenderer->setView($view);
//Return it, so that it can be stored by the bootstrap
return $view;
}
//and to use the helper in the view template
//any.phtml
<?php echo $this->padId($this->id) ?>
i need differents results from a model but i don't understand if it is
correct make a single call and leave to model all the work or make
more calls and collect the result to pass to the view when tables
aren't joined or when i need fetch one row from a table and differents
rows from others.
This question is more about structure then about correctness.
You can interact with your database table models in Action and View helpers for simple/repetitive queries if you need to, however most developers might frown on this approach as being difficult to maintain or just ugly.
Many people seem to favor Doctrine or Propel to help them manage their database needs.
At this point I like to roll my own and currently favor domain models and data mappers, not an end all be all pattern, but seems to be appropriate to your question.
This is not a simple suggestion to implement for the first time, however i found two articles helpful to get started:
http://phpmaster.com/building-a-domain-model/
http://phpmaster.com/integrating-the-data-mappers/
and if you really want to get into it try:
http://survivethedeepend.com/
I hope this answers at least a part of your questions.
In one of my controllers to fetch all the data for my general view page I use a foreach loop and then $object->column_name but now I have decided I would like to do a couple of things with this data:
Edit it -> It is an edit page for each $object by its $id
Use the $object->name field via the controller to enable me to use it in a $data['pageTitle']= Edit '.$object->name.';
What would be the best way to change the model below so that I can use it for many purposes / different ways of displaying the data for manipulation?
public function showAll()
{
$database = $this->db->get('form');
if($database->num_rows() > 0)
{
$row = $database->result();
}
return $row;
}
It is good practice to keep the database query part in your model rather than the controller.
In your controller you can do something like:
$recs = $this->sample_model->model_function();
foreach ($recs as $r)
{
$r->additional_info_appended_to_each_row = 'whatever';
}
This way you can append an additional variable to each database row for displaying / editing etc.
That code doesn't really show us enough of the relevant code to be able to answer that question. Assuming $database->result() returns an array of rows (a database query's result set) then the data it contains depends on how the query looks. All you show is is $this->db->get('form'), which can mean just about anything.
A generic answer to your question would be: Alter the SQL query to include the id and name fields. Then inject those into your view through your controller. (Or get them directly through the view. That's up to you.)
Not knowing a thing about your controllers or your views, here is an example that assumes your views extend the Smarty template engine.
public function GeneralController
{
public function defaultAction()
{
$model = new GeneralModel();
$objects = $model->getAll();
$view = new GeneralView();
$view->assign("objects", $objects);
$view->show();
}
}
The Smarty template would then use those rows when generating the HTML
{foreach $objects as $object}
<section class="object">
<header>
<h1>{$object->name}</h1>
</header>
<p>{$object->contents}</p>
<footer>
Edit
</footer>
</section>
{/foreach}
So basically I'm making a leap from procedural coding to OOP.
I'm trying to implement the principles of OOP but I have a nagging feeling I'm actually just writing procedural style with Objects.
So say I have a list of pipes/chairs/printers/whatever, they are all all listed as products in my single table database. I need to build a webapp that displays the whole list and items depending on their type, emphasis is on 'correct' use of OOP and its paradigm.
Is there anything wrong about just doing it like:
CLass Show
{
public function showALL(){
$prep = "SELECT * FROM myProducts";
$q = $this->db-> prepare($prep);
$q->execute();
while ($row = $q->fetch())
{
echo "bla bla bla some arranged display".$row['something']
}
}
and then simply
$sth = new show();
$sth->showAll();
I would also implement more specific display methods like:
showSpecificProduct($id)->($id would be passed trough $_GET when user say clicks on one of the links and we would have seperate product.php file that would basically just contain
include('show.class.php');
$sth = new show();
$sth->showSpecificProduct($id);
showSpecificProduct() would be doing both select query and outputing html for display.
So to cut it short, am I going about it allright or I'm just doing procedural coding with classes and objects. Also any ideas/hints etc. on resolving it if I'm doing it wrong?
As well as the model practices described by #Phil and #Drew, I would urge you to separate your business, data and view layers.
I've included a very simple version which will need to be expanded upon in your implementation, but the idea is to keep your Db selects separate from your output and almost "joining" the two together in the controller.
class ProductController
{
public $view;
public function __construct() {
$this->view = new View;
}
public function indexAction() {
$model = new DbProductRepository;
$products = $model->fetchAll();
$this->view->products = $products;
$this->view->render('index', 'product');
}
}
class View
{
protected $_variables = array();
public function __get($name) {
return isset($this->_variables['get']) ? $this->_variables['get'] : null;
}
public function __set($name, $value) {
$this->_variables[$name] = $value;
}
public function render($action, $controller) {
require_once '/path/to/views/' . $controller . '/' . $action . '.php';
}
}
// in /path/to/views/product/index.php
foreach ($this->products as $product) {
echo "Product ID {$product['id']} - {$product['name']} - {$product['cost']}<br />\n";
}
A better fit would be to implement a repository pattern. An example interface might be
interface ProductRepository
{
public function find($id);
public function fetchAll();
}
You would then create a concrete implementation of this interface
class DbProductRepository implements ProductRepsoitory
{
private $db;
public function __construct(PDO $db)
{
$this->db = $db;
}
public function find($id)
{
// prepare execute SQL statement
// Fetch result
// return result
}
public function fetchAll()
{
// etc
}
}
It's generally a bad idea to echo directly from a method or function. Have your methods return the appropriate objects / arrays / whatever and consume those results.
The scenario you are describing above seems like a good candidate for MVC.
In your case, I would create a class strictly for accessing the data (doing selects of product categories or specific products) and then have a different file (your view) take the output and display it.
It could look something like this:
class Product_Model {
public function find($prodId) { ... }
public function fetchAll($category = '') { ... }
public function search($string) { ... }
}
Then somewhere else you can do:
$products = new Product_Model();
$list = $products->fetchAll(37); // get all from category 37
// in true MVC, you would have a view that you would assign the list to
// $view->list = $list;
foreach($ilst as $product) {
echo "Product ID {$product['id']} - {$product['name']} - {$product['cost']}<br />\n";
}
The basic principle of MVC is that you have model classes that are simply objects representing data from some data source (e.g. database). You might have a mapper that maps data from the database to and from your data objects. The controller would then fetch the data from your model classes, and send the information to the view, where the actual presentation is handled. Having view logic (html/javascript) in controllers is not desirable, and interacting directly with your data from the controller is the same.
first, you will want to look into class autoloading. This way you do not have to include each class you use, you just use it and the autoloader will find the right file to include for you.
http://php.net/manual/en/language.oop5.autoload.php
each class should have a single responsibility. you wouldn't have a single class that connects to the database, and changes some user data. instead you would have a database class that you would pass into the user class, and the user class would use the database class to access the database. each function should also have a single responsibility. you should never have an urge to put an "and" in a function name.
You wouldn't want one object to be aware of the properties of another object. this would cause making changes in one class to force you to make changes in another and it eventually gets difficult to make changes. properties should be for internal use by the object.
before you start writing a class, you should first think about how you would want to be able to use it (see test driven development). How would you want the code to look while using it?
$user = new User($db_object);
$user->load($id);
$user->setName($new_name);
$user->save();
Now that you know how you want to be able to use it, it's much easier to code it the right way.
research agile principles when you get a chance.
One rule of thumb is that class names should usually be nouns, because OOP is about having software objects that correspond to real conceptual objects. Class member functions are usually the verbs, that is, the actions you can do with an object.
In your example, show is a strange class name. A more typical way to do it would be to have a class called something like ProductViewer with a member function called show() or list(). Also, you could use subclasses as a way to get specialized capabilities such as custom views for particular product types.