I an using zend db table models for backend crud operations. However I think the model like this is meaningless for my front end data display like news by category , news and blog widgets and etc from various table or joining various table.
class Bugs extends Zend_Db_Table_Abstract {
protected $_name = 'bugs'; }
Model this way is perfect for my backend admin panel crud operation, How would i create model for front end operation, any example would be highly appreceated. Thanks
You can join on other tables even with a Zend_Db_Table-derived model. Just be sure to turn off integrity check.
Code (not tested) could look something like this:
class My_Model_News extends Zend_Db_Table
{
// Hate the 'tbl_' prefix. Just being explicit that this is a
// table name.
protected $_name = 'tbl_news';
public function fetchNewsByAuthor($authorId)
{
$select = $this->select();
$select->setIntegrityCheck(false)
->from(array('n' => 'tbl_news'), array('*'))
->join(array('a' => 'tbl_author'), array('n.author_id = a.id'), array('author_name' => 'a.name'))
->order('n.date_posted DESC');
return $this->fetchAll($select);
}
}
Then in your controller:
$authorId = $this->_getParam('authorId');
$newsModel = new My_Model_News();
$this->view->articles = $newsModel->fetchNewsByAuthor($authorId);
Truth be told, that's one of the things that leaves me flat about most TableGateway approaches, like Zend_Db_Table. I find that TableGateway is great for single-table queries, but I find that most of my real-life situations require multi-tables. As a result, I end up creating models that are not tied to a single table, but rather accept a Zend_Db_Adapter instance and then query/join whatever tables they need. Or, I push out to more complex ORM's, like Doctrine.
I think what you are asking about in ZF would be a View Helper, A view helper takes data from your models and allows you to dump it to the view without having to process it in the controller. Here is a simple example:
<?php
class Zend_View_Helper_Track extends Zend_View_Helper_Abstract
{
/**
*
* #param type $trackId
* #return type object
*/
public function Track($trackId) {
//this model just aggregates data from several DbTable models
$track = new Application_Model_TrackInfo();
$data = $track->getByTrackId($trackId);
return $data;
}
}
view helpers are characterized by returning some data (object, string, array, boolean) and can be used to supply data to views and partials.
The following is an example of a partial that uses several view helpers to present data in view.
<fieldset><legend>Dates and Qualifications</legend>
<table>
<tr>
<td>Birth Date: </td><td><?php echo $this->escape($this->FormatDate($this->bdate)) ?></td>
</tr>
<tr>
<td>Seniority Date: </td><td><?php echo $this->escape($this->FormatDate($this->sendate)) ?></td>
</tr>
</table>
<table>
<tr>
<td>I'm a Lead:</td><td><?php echo $this->escape(ucfirst($this->ToBool($this->lead))) ?></td>
</tr>
<tr>
<td>Lead Date:</td><td><?php echo $this->escape($this->FormatDate($this->ldate)) ?></td>
</tr>
<tr>
<td>I'm an Inspector:</td><td><?php echo $this->escape(ucfirst($this->toBool($this->inspector))) ?></td>
</tr>
<tr>
<td>Admin Login:</td><td><?php echo $this->escape(ucfirst($this->toBool($this->admin))) ?></td>
</tr>
</table>
</fieldset>
and finally I call this partial in a view with:
<?php echo $this->partial('_dates.phtml', $this->memberData) ?>
as far as DbTable models being useless for the frontend, you might be surprised. Once you have established the relationships between your tables properly in your DbTable classes the functionality of what they can do goes way up. However if you are like most people you will likely have at least one layer of domain models (mappers, service, repository) between your DbTable classes and your application.
This is a model with relationships, it's sole purpose is to supply the data to build navigation.
<?php
class Application_Model_DbTable_Menu extends Zend_Db_Table_Abstract {
protected $_name = 'menus';
protected $_dependentTables = array('Application_Model_DbTable_MenuItem');
protected $_referenceMap = array(
'Menu' => array(
'columns' => array('parent_id'),
'refTableClass' => 'Application_Model_DbTable_Menu',
'refColumns' => array('id'),
'onDelete' => self::CASCADE,
'onUpdate' => self::RESTRICT
)
);
public function createMenu($name) {
$row = $this->createRow();
$row->name = $name;
return $row->save();
}
public function getMenus() {
$select = $this->select();
$select->order('name');
$menus = $this->fetchAll($select);
if ($menus->count() > 0) {
return $menus;
} else {
return NULL;
}
}
public function updateMenu($id, $name) {
$currentMenu = $this->find($id)->current();
if ($currentMenu) {
//clear the cache entry for this menu
$cache = Zend_Registry::get('cache');
$id = 'menu_' . $id;
$cache->remove($id);
$currentMenu->name = $name;
return $currentMenu->save();
} else {
return FALSE;
}
}
public function deleteMenu($menuId) {
$row = $this->find($menuId)->current();
if ($row) {
return $row->delete();
} else {
throw new Zend_Exception("Error loading menu...");
}
}
}
Zend_Db_Table_Abstract supplies the interface for several data access patterns and you just have to supply the business logic and whatever level of abstraction you want.
Related
This is again an understanding issue, any explanation is appreciated:
I before had the issue to show a foreignkey table in my view, that now works, it looks like follows:
That's quite what I wanted, but:
I only get the first row, but there are of course several in the second collection (it is the row with filename).
It is because of my method in my model, which looks like follows:
public function getImportU($unitid)
{
$unitid = (int) $unitid;
$rowset = $this->tableGateway->select(['UnitID' => $unitid]);
$row = $rowset->current();
if (! $row) {
return null;
}
else{
return $row;
}
}
Of course I have a row object and it returns the current row. So I thought, ok I will try with a rowset, after that it looked like this:
public function getImportU($unitid)
{
$unitid = (int) $unitid;
$rowset = $this->tableGateway->select(['UnitID' => $unitid]);
//$row = $rowset->current();
if (! $rowset) {
return null;
}
else{
return $rowset;
}
}
I got some errors which said:
Notice: Undefined property: Zend\Db\ResultSet\ResultSet::$Importdate in
Blockquote
So how to get a recordcollection, all records there are in the table with the same unitid? And how to call them in the view. It is probably not a big deal, but I couldn't find anything usable in the documentation.
EDIT1: Adding related code.
Here I pass the ViewModel within my Controller indexAction:
return new ViewModel([
'projects' => $this->projectTable->fetchAll(),
'dcls' => $this->table,
//'id' =>$this->authService,
]);
And here a snippet of my index.phtml:
foreach ($projects as $project) :
//var_dump(get_object_vars($project));
?>
<tr>
<td><?= $project['Projectname']?></td>
<td><?= $project['ProjectShortcut']?></td>
<td><?= $project['ProjectCiNumber']?></td>
<td><?= $project['Unitname']?></td>
<td><?= $project['UnitShortcut']?></td>
<td><?= $project['UnitCiNumber']?></td>
<td><?= $project['UnitID']?></td>
</tr>
<?php
$dclsx=$dcls->getImportU($project['UnitID']);
// var_dump($dclss);
if ( empty ($dclsx)==false){ ?>
<tr>
<th></th>
<th>filename</th>
<th>importdate</th>
<th>importuser</th>
<th>importok</th>
</tr>
<?php
$dclss=array($dclsx);
// var_dump($dclss);
foreach ( $dclss as $dcl) :
?>
<tr>
<td> </td>
<td><?= $dcl->filename?></td>
<td><?= $dcl->Importdate?></td>
<td><?= $dcl->Importuser?></td>
</tr>
?php
endforeach;
}
endforeach; ?>
I believe you are pretty close to the solution.
"getImportU" returning a rowset is the correct solution as I see it:
public function getImportU($unitid)
{
$unitid = (int) $unitid;
$rowset = $this->tableGateway->select(['UnitID' => $unitid]);
if (! $rowset) {
return null;
}
else{
return $rowset;
}
}
Your view should be changed from:
<?php
$dclss=array($dclsx);
// var_dump($dclss);
foreach ( $dclss as $dcl) :
to:
<?php
foreach ( $dclsx as $dcl) :
$dclsx is a resultset and can be iterated, it does not make sense to put it in an array.
Your error also suggests that "Importdate" cannot be found in the blockquote table.
Please check if the column exists at the table(also check the name is case sensitive, is it "Importdate", "importdate" or "importDate"?)
I've got on my page several News, to every News we can add comment via form.
So actually I've got 3 News on my index.ctp, and under every News is a Form to comment this particular News. Problem is, when i add comment, data is taken from the last Form on the page.
I don;t really know how to diverse them.
i've red multirecord forms and Multiple Forms per page ( last one is connected to different actions), and i don't figure it out how to manage it.
Second problem is, i can't send $id variable through the form to controller ( $id has true value, i displayed it on index.ctp just to see )
This is my Form
<?php $id = $info['Info']['id']; echo $this->Form->create('Com', array('action'=>'add',$id)); ?>
<?php echo $this->Form->input(__('Com.mail',true),array('class'=>'form-control','field'=>'mail')); ?>
<?php echo $this->Form->input(__('Com.body',true),array('class'=>'form-control')); ?>
<?php echo $this->Form->submit(__('Dodaj komentarz',true),array('class'=>'btn btn-info')); ?>
<?php $this->Form->end(); ?>
and there is my controller ComsController.php
class ComsController extends AppController
{
public $helpers = array('Html','Form','Session');
public $components = array('Session');
public function index()
{
$this->set('com', $this->Com->find('all'));
}
public function add($idd = NULL)
{
if($this->request->is('post'))
{
$this->Com->create();
$this->request->data['Com']['ip'] = $this->request->clientIp();
$this->request->data['Com']['info_id'] = $idd;
if($this->Com->save($this->request->data))
{
$this->Session->setFlash(__('Comment added with success',true),array('class'=>'alert alert-info'));
return $this->redirect(array('controller'=>'Infos','action'=>'index'));
}
$this->Session->setFlash(__('Unable to addd comment',true),array('class'=>'alert alert-info'));
return false;
}
return true;
}
}
you are not closing your forms
<?php echo $this->Form->end(); ?>
instead of
<?php $this->Form->end(); ?>
for the id problem you should write
echo $this->Form->create(
'Com',
array('action'=>'add/'.$id
)
);
or
echo $this->Form->create(
'Com',
array(
'url' => array('action'=>'add', $id)
)
);
I recently was introduced into the Yii Framework and am presently developing a web application system for my company. However I noticed that when creating the model in order to give the connection to the respective table, it only allows to choose one relation at a time. However I need to connect two separate tables from the same database with a single form.
Any ideas on how this could be accomplished?
Inside the models you can see the below function,
/**
* #return array relational rules.
*/
public function relations()
{
return array(
);
}
in this you can add relations. like
'user' => array(self::BELONGS_TO, 'User', 'user_id'),
'comments' => array(self::HAS_MANY, 'Comments', 'blog_post_id'),
etc.,
If your database engine is in Innodb and tables have foreign key relations , then the relations will be automatically generated while creating the models.
For more info read this
you can use any number of relations.
=============================================
And after second reading, I think you were asking about getting objects of two models into one form? for that you can generate objects of each model in controller and pass those objects to view via render or renderPartial function
e.g.,
$this->render('admin',array(
'model'=>$model,
'model2'=>$model2,
));
and inside the view use model and model2 for respective fields
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'sample-form',
'enableAjaxValidation'=>false,
)); ?>
.....
<?php echo $form->labelEx($model,'column'); ?>
<?php echo $form->textField($model,'column'); ?>
<?php echo $form->error($model,'column'); ?>
<?php echo $form->labelEx($model2,'column'); ?>
<?php echo $form->textField($model2,'column'); ?>
<?php echo $form->error($model2,'column'); ?>
....
inside the controller function use something like below(say for saving data)
$model->attributes=$_POST['ModelOnesName'];
$valid = $model->validate();
$model2->attributes = $_POST['ModelTwosName'];
$valid = $model2->validate() && $valid; //if need validation checks
if($valid)
{
$model->save();
$model2->save();
}
I am new to zend frame work . I am trying to learn zf create db-table tblename,zf create model tblname,zf create model tblnameMapper.
add user.php (form)
<?php
class Application_Form_Adduser extends Zend_Form
{
public function init()
{
$this->setMethod('post');
$username = $this->createElement('text','username');
$username->setLabel('Username:')
->setAttrib('size',10);
$password=$this->createElement('text','password');
$password->setLabel('Password')
->setAttrib('size',10);
$reg=$this->createElement('submit','submit');
$reg->setLabel('save');
$this->addElements(array(
$username,
$password,
$reg
));
return $this;
}
add user view:
<?php
echo 'Add user';
echo "<br />" .$this->a;
echo $this->form;
?>
admin controller:
<?php
class AdminController extends Zend_Controller_Action
{
public function adduserAction(){
$form = new Application_Form_Auth();
$this->view->form = $form;
$this->view->assign('a','Entere new user:');
if($this->getRequest()->isPost()){
$formData = $this->_request->getPost();
$uname=$formData['username'];
$pass=$formData['password'];
$msg=$uname." added to database successfully";
$this->view->assign('a',$msg);
$db= Zend_Db_Table_Abstract::getDefaultAdapter();
$query="INSERT INTO `user` ( `id` , `uname` , `password` )
VALUES ('', '{$uname}', '{$pass}');";
$db->query($query);
}}
i want to implement db-table with the above code .i am new to zend frame work i spend some time on reading programmers guide but in vain .It is very hard to get things from manual.So please some one explain step by step procedure for implementing the same .Thanks in advanced.
Ok here is a quick example:
Create DbTable Model (Basically an adapter for each table in your database):
at the command line: zf create db-table User user add -m moduleName if you want this in a module. This command will create a file name User.php at /application/models/DbTable that looks like:
class Application_Model_DbTable_User extends Zend_Db_Table_Abstract {
protected $_name = 'user'; //this is the database tablename (Optional, automatically created by Zend_Tool)
protected $_primary = 'id'; //this is the primary key of the table (Optional, but a good idea)
}
now to create a method in your DbTable model that executes the query from your controller, add a method similar to:
public function insertUser(array $data) {
$Idata = array(
'name' => $data['name'] ,
'password' => $data['passowrd']
);
$this->insert($Idata); //returns the primary key of the new row.
}
To use in your controller:
public function adduserAction(){
$form = new Application_Form_Auth(); //prepare form
try{
if($this->getRequest()->isPost()){//if is post
if ($form->isValid($this->getRequest()_>getPost()){ //if form is valid
$data = $form->getValues(); //get filtered and validated form values
$db= new Application_Model_DbTable_User(); //instantiate model
$db->insertUser($data); //save data, fix the data in the model not the controller
//do more stuff if required
}
}
$this->view->form = $form; //if not post view form
$this->view->assign('a','Entere new user:');
} catch(Zend_Exception $e) { //catach and handle exception
$this->_helper->flashMessenger->addMessage($e->getMessage());//send exception to flash messenger
$this->_redirect($this->getRequest()->getRequestUri()); //redirect to same page
}
}
This is about as simple as it gets. I have barely scratched the surface of what can be accomplished in simple applications with Zend_Db and a DbTable model. However you will likely find as I have, that at some point you will need more. That would be the time to explore the domain model and mappers.
For a really good basic tutrial that includes all of this and more please check out Rob Allen's ZF 1.x tutorial
I hope this helps.
I think I have just been working too long and am tired. I have an application using the Zend Framework where I display a list of clubs from a database. I then want the user to be able to click the club and get the id of the club posted to another page to display more info.
Here's the clubs controller:
class ClubsController extends Zend_Controller_Action
{
public function init()
{
}
public function indexAction()
{
$this->view->assign('title', 'Clubs');
$this->view->headTitle($this->view->title, 'PREPEND');
$clubs = new Application_Model_DbTable_Clubs();
$this->view->clubs = $clubs->fetchAll();
}
}
the model:
class Application_Model_DbTable_Clubs extends Zend_Db_Table_Abstract
{
protected $_name = 'clubs';
public function getClub($id) {
$id = (int) $id;
$row = $this->fetchRow('id = ' . $id);
if (!$row) {
throw new Exception("Count not find row $id");
}
return $row->toArray();
}
}
the view:
<table>
<?php foreach($this->clubs as $clubs) : ?>
<tr>
<td><a href=''><?php echo $this->escape($clubs->club_name);?></a></td>
<td><?php echo $this->escape($clubs->rating);?></td>
</tr>
<?php endforeach; ?>
</table>
I think I am just getting confused on how its done with the zend framework..
in your view do this
<?php foreach ($this->clubs as $clubs) : ?>
...
<a href="<?php echo $this->url(array(
'controller' => 'club-description',
'action' => 'index',
'club_id' => $clubs->id
));?>">
...
That way you'll have the club_id param available in index action of your ClubDescription controller. You get it like this $this->getRequest()->getParam('club_id')
An Example:
class ClubsController extends Zend_Controller_Action
{
public function init()
{
}
public function indexAction()
{
$this->view->assign('title', 'Clubs');
$this->view->headTitle($this->view->title, 'PREPEND');
$clubs = new Application_Model_DbTable_Clubs();
$this->view->clubs = $clubs->fetchAll();
}
public function displayAction()
{
//get id param from index.phtml (view)
$id = $this->getRequest()->getParam('id');
//get model and query by $id
$clubs = new Application_Model_DbTable_Clubs();
$club = $clubs->getClub($id);
//assign data from model to view [EDIT](display.phtml)
$this->view->club = $club;
//[EDIT]for debugging and to check what is being returned, will output formatted text to display.phtml
Zend_debug::dump($club, 'Club Data');
}
}
[EDIT]display.phtml
<!-- This is where the variable passed in your action shows up, $this->view->club = $club in your action equates directly to $this->club in your display.phtml -->
<?php echo $this->club->dataColumn ?>
the view index.phtml
<table>
<?php foreach($this->clubs as $clubs) : ?>
<tr>
<!-- need to pass a full url /controller/action/param/, escape() removed for clarity -->
<!-- this method of passing a url is easy to understand -->
<td><a href='/index/display/id/<?php echo $clubs->id; ?>'><?php echo $clubs->club_name;?></a></td>
<td><?php echo $clubs->rating;?></td>
</tr>
<?php endforeach; ?>
an example view using the url() helper
<table>
<?php foreach($this->clubs as $clubs) : ?>
<tr>
<!-- need to pass a full url /controller/action/param/, escape() removed for clarity -->
<!-- The url helper is more correct and less likely to break as the application changes -->
<td><a href='<?php echo $this->url(array(
'controller' => 'index',
'action' => 'display',
'id' => $clubs->id
)); ?>'><?php echo $clubs->club_name;?></a></td>
<td><?php echo $clubs->rating;?></td>
</tr>
<?php endforeach; ?>
</table>
[EDIT]
With the way your current getClub() method in your model is built you may need to access the data using $club['data']. This can be corrected by removing the ->toArray() from the returned value.
If you haven't aleady done so you can activate error messages on screen by adding the following line to your .htaccess file SetEnv APPLICATION_ENV development.
Using the info you have supplied, make sure display.phtml lives at application\views\scripts\club-description\display.phtml(I'm pretty sure this is correct, ZF handles some camel case names in a funny way)
You can put the club ID into the URL that you link to as the href in the view - such as /controllername/club/12 and then fetch that information in the controller with:
$clubId = (int) $this->_getParam('club', false);
The 'false' would be a default value, if there was no parameter given. The (int) is a good practice to make sure you get a number back (or 0, if it was some other non-numeric string).