Zend Framework: How to write a correct model that use another table? - zend-framework

I have models in project that use more than one table to select.
How can I write code like this more correct?
public function __construct()
{
$this->_name = DB_PREFIX . 'teachers';
parent::__construct();
}
public function init()
{
$this->db = Zend_Db_Table::getDefaultAdapter();
}
public function getTeachers($course_id)
{
$students_query = $this ->db->select()
->from($this->_name, '')
->from(<ANOTHER_TABLE_NAME>, array('uid', 'ulogin'))
->where("<ANOTHER_TABLE_NAME>.uid = {$this->_name}.teacher_id")
->where("{$this->_name}.course_id = ?", $course_id)
->order("<ANOTHER_TABLE_NAME>.ulogin");
$result = $this->db->fetchAll($students_query) ? $this->db->fetchAll($students_query) : NULL;
return $result;
}

$students_query = $this->db->select()
->from($this->_name, '')
->setIntegrityCheck(false)
->join('<ANOTHER_TABLE_NAME>', "<ANOTHER_TABLE_NAME>.uid = {$this->_name}.teacher_id", array('uid', 'ulogin'))
->where("{$this->_name}.course_id = ?", $course_id)
->order("<ANOTHER_TABLE_NAME>.ulogin");

Related

Issue with add global variable codeigniter 3

I've admin dashboard with header available in all pages.
in Admin Controller I add function:
`class Admin_controller extends Admin_Core_Controller
{
public function __construct()
{
parent::__construct();
}
public function index()
{
$data['notification_count'] = $this->order_admin_model->get_all_notifications_count();
$data['notification'] = $this->order_admin_model->get_all_notifications();
$this->load->view('admin/includes/_header', $data);
$this->load->view('admin/index');
$this->load->view('admin/includes/_footer');
}
}`
The problem is this working only for "home page (index)" dashboard. When I open anyother page then I get issue undefinied variable.
How can I call this variables in global?
`
$data['notification_count'] = $this->order_admin_model->get_all_notifications_count();
$data['notification'] = $this->order_admin_model->get_all_notifications();`
update:
I've one file Core_Controller.php and this file contains:
class Admin_Core_Controller extends Core_Controller
{
public function __construct()
{
parent::__construct();
if (!is_admin()) {
redirect(admin_url() . 'login');
exit();
}
//set control panel lang
$this->control_panel_lang = $this->selected_lang;
if (!empty($this->session->userdata('mds_control_panel_lang'))) {
$this->control_panel_lang = $this->session->userdata('mds_control_panel_lang');
//language translations
$this->language_translations = $this->get_translation_array($this->control_panel_lang->id);
}
//check long cron
if (check_cron_time_long() == true) {
//delete old sessions
$this->settings_model->delete_old_sessions();
//add last update
$this->db->where('id', 1)->update('general_settings', ['last_cron_update_long' => date('Y-m-d H:i:s')]);
}
}
protected function render($view, $data = NULL)
{
$data['notification_count'] = $this->order_admin_model->get_all_notifications_count();
$data['notification'] = $this->order_admin_model->get_all_notifications();
$this->load->view('admin/includes/_header', $data);
$this->load->view($view, $data);
$this->load->view('admin/includes/_footer');
}
public function paginate($url, $total_rows)
{
//initialize pagination
$page = $this->security->xss_clean($this->input->get('page'));
$per_page = $this->input->get('show', true);
$page = clean_number($page);
if (empty($page) || $page <= 0) {
$page = 0;
}
if ($page != 0) {
$page = $page - 1;
}
if (empty($per_page)) {
$per_page = 15;
}
$config['num_links'] = 4;
$config['base_url'] = $url;
$config['total_rows'] = $total_rows;
$config['per_page'] = $per_page;
$config['reuse_query_string'] = true;
$this->pagination->initialize($config);
return array('per_page' => $per_page, 'offset' => $page * $per_page);
}
}
You see I add your code here and now in Admin_Controller I add:
class Admin_controller extends Admin_Core_Controller
{
public function __construct()
{
parent::__construct();
}
public function index()
{
$data['title'] = trans("admin_panel");
$data['order_count'] = $this->order_admin_model->get_all_orders_count();
$data['product_count'] = $this->product_admin_model->get_products_count();
$data['pending_product_count'] = $this->product_admin_model->get_pending_products_count();
$data['blog_posts_count'] = $this->blog_model->get_all_posts_count();
$data['members_count'] = $this->auth_model->get_users_count_by_role('member');
$data['latest_orders'] = $this->order_admin_model->get_orders_limited(15);
$data['latest_pending_products'] = $this->product_admin_model->get_latest_pending_products(15);
$data['latest_products'] = $this->product_admin_model->get_latest_products(15);
$data['latest_reviews'] = $this->review_model->get_latest_reviews(15);
$data['latest_comments'] = $this->comment_model->get_latest_comments(15);
$data['latest_members'] = $this->auth_model->get_latest_members(6);
$data['latest_transactions'] = $this->transaction_model->get_transactions_limited(15);
$data['latest_promoted_transactions'] = $this->transaction_model->get_promoted_transactions_limited(15);
$this->load->view('admin/includes/_header', $data);
$this->render('admin/index');
$this->load->view('admin/includes/_footer');
}
and after this dashboard now working and everytime is refreshed every sec.
I would suggest creating a base controller with a render function, then have your controllers extend from this base controller and use this function to render their pages. The render function can then contain the variables that need to be available on all pages.
Since you already have an Admin_Core_Controller class, you might be able to add the render function there instead (not sure of your project structure). Something like this:
class Admin_Core_Controller // ...
{
// ...
protected function render($view, $data = NULL)
{
$data['notification_count'] = $this->order_admin_model->get_all_notifications_count();
$data['notification'] = $this->order_admin_model->get_all_notifications();
$this->load->view('admin/includes/_header', $data);
$this->load->view($view, $data);
$this->load->view('admin/includes/_footer');
}
}
Then use it to render your page in Admin_Controller:
class Admin_controller extends Admin_Core_Controller
{
public function __construct()
{
parent::__construct();
}
public function index()
{
$this->render('admin/index');
}
}
Edit Your Admin_Controller class should look like this - I've removed the header and footer includes (those are already rendered by the render function) and passed the $data array to render:
class Admin_controller extends Admin_Core_Controller
{
public function __construct()
{
parent::__construct();
}
public function index()
{
$data['title'] = trans("admin_panel");
$data['order_count'] = $this->order_admin_model->get_all_orders_count();
$data['product_count'] = $this->product_admin_model->get_products_count();
$data['pending_product_count'] = $this->product_admin_model->get_pending_products_count();
$data['blog_posts_count'] = $this->blog_model->get_all_posts_count();
$data['members_count'] = $this->auth_model->get_users_count_by_role('member');
$data['latest_orders'] = $this->order_admin_model->get_orders_limited(15);
$data['latest_pending_products'] = $this->product_admin_model->get_latest_pending_products(15);
$data['latest_products'] = $this->product_admin_model->get_latest_products(15);
$data['latest_reviews'] = $this->review_model->get_latest_reviews(15);
$data['latest_comments'] = $this->comment_model->get_latest_comments(15);
$data['latest_members'] = $this->auth_model->get_latest_members(6);
$data['latest_transactions'] = $this->transaction_model->get_transactions_limited(15);
$data['latest_promoted_transactions'] = $this->transaction_model->get_promoted_transactions_limited(15);
$this->render('admin/index', $data);
}
}

Zend_Paginator for Categories

I have used Zend_Paginator in my Index action , this show all my catalog :
public function indexAction()
{
Zend_View_Helper_PaginationControl::setDefaultViewPartial('/pagination.phtml');
$pages = new Application_Model_DbTable_Catalog();
$num = 10;
$page = $this->_getParam('page');
$select = $pages->select();
$result = $this->view->table = $pages->fetchAll($select)->toArray();
$paginator = new Zend_Paginator(new Zend_Paginator_Adapter_Array($result));
$paginator->setItemCountPerPage($num);
$paginator->setCurrentPageNumber($page);
$paginator->setView($this->view);
$this->view->paginator = $paginator;
}
It works perfectly, now I have CategoryAction, it's sort my catalog by category
public function categoryAction()
{
$id = intval($this->_getParam('id', 0));
if ($id > 0) {
$catalog = new Application_Model_DbTable_Catalog();
$this->view->catalog = $catalog->getByCategoryId($id);
и
$category = new Application_Model_DbTable_Categories();
$this->view->category = $category->getById($id);
}
So I can't understand how to add Pagination to this action,
Help me, Pleaaasssseeeeeee:-(,
P.S. sorry for my bad English
Ok there is a better/easier way to do this.
Pagination starts with your database query. You are using DbTable models so it's very easy in ZF1 to setup the adapter.
<?php
class Application_Model_DbTable_Catalog extends Zend_Db_Table_Abstract
{
protected $_name = 'catalog'
/*
* This method returns a paginator adapter with a fetchAll($where = null, $order = null, $count = null, $offset = null)
* paginator adapter will supply the values for $offset and $limit
*/
public function getPagedCatalog()
{
$select = $this->select(); //put anything you need into $select
$adapter = new Zend_Paginator_Adapter_DbTableSelect($select);//the paginator adapter in place of the fetchAll().
return $adapter;
{
}
<?php
class Application_Model_DbTable_Categories extends Zend_Db_Table_Abstract
{
protected $_name = 'categories'
/*
* This method returns a paginator adapter with a fetchAll($where = $id, $order = null, $count = null, $offset = null)
* paginator adapter will supply the values for $offset and $limit
*/
public function getPagedCatagories($id)
{
$select = $this->select(); //put anything you need into $select
$select->where('catagory_id = ?', $id);//you may need to build a join for this to work how you want it to, depends on your table structure.
$adapter = new Zend_Paginator_Adapter_DbTableSelect($select);//the paginator adapter in place of the fetchAll().
return $adapter;
{
}
now your models will return paginator adapters with the contents of these tables available. Zend_Paginator will automatically supply the $limit and $offset parameters to the query so that each page will perform a query. The whole table will not be stored in memory with this adapter.
Now your indexAction() may look like:
public function indexAction()
{
Zend_View_Helper_PaginationControl::setDefaultViewPartial('/pagination.phtml');
$pages = new Application_Model_DbTable_Catalog();
$adapter = $pages->getPagedCatalog(); //get adapter from model
$page = $this->_getParam('page', 1);//a default of page 1 prevents possible unusual behavior when no page number is set.
$paginator = new Zend_Paginator($adapter);
$paginator->setItemCountPerPage('10');
$paginator->setCurrentPageNumber($page);
//$paginator->setView($this->view); This line is likely not needed
$this->view->paginator = $paginator;
}
and your categoryAction() might work like:
public function categoryAction()
{
$page = $this->_getParam('page', 1);
$id = intval($this->_getParam('id', 0));
if ($id > 0) {
$category = new Application_Model_DbTable_Categories();
$adapter = $category->getPagedCatagories($id);
//same as above
$paginator = new Zend_Paginator($adapter);
$paginator->setItemCountPerPage('10');
$paginator->setCurrentPageNumber($page);
//$paginator->setView($this->view); This line is likely not needed, unless you have multiple view objects.
$this->view->paginator = $paginator;
} else {
//do some other stuff...
}
}
if you get crazy and want to use your own mapper classes to base a paginator adapter on you can extend the adapter class by overriding getItems(), something like:
<?php
class Music_Model_Paginator_Track extends Zend_Paginator_Adapter_DbTableSelect
{
//override getItems()
public function getItems($offset, $itemCountPerPage)
{
$rows = parent::getItems($offset, $itemCountPerPage);
$albums = array();
foreach ($rows as $row) {
$album = new Music_Model_Mapper_Track();//use this class to turn each $row into an object
$albums[] = $album->createEntity($row); //build the new entity objects
}
//returns an array of entity objects to the paginator
return $albums;
}
}
Hope this helps.

yii lucene index doesn't exists

I want to do the SearchBox on my webapp. I followed tutorial: SeachBox Tutorial excatly, did everything author mentioned, and I'm getting an error:
Index doesn't exists in the specified directory.
My SearchController:
<?php
class SearchController extends Controller
{
private $_indexFiles = 'runtime.search';
public function init(){
Yii::import('application.vendors.*');
require_once('Zend/Search/Lucene.php');
parent::init();
}
/**
* Search index creation
*/
public function actionCreate()
{
$index = Zend_Search_Lucene::create($_indexFiles);
$index = new Zend_Search_Lucene(Yii::getPathOfAlias('application.' . $this->_indexFiles), true);
$posts = News::model()->findAll();
foreach($news as $news){
$doc = new Zend_Search_Lucene_Document();
$doc->addField(Zend_Search_Lucene_Field::Text('title',
CHtml::encode($news->name), 'utf-8')
);
$doc->addField(Zend_Search_Lucene_Field::Text('link',
CHtml::encode($news->url)
, 'utf-8')
);
$doc->addField(Zend_Search_Lucene_Field::Text('content',
CHtml::encode($news->description)
, 'utf-8')
);
$index->addDocument($doc);
}
$index->commit();
echo 'Lucene index created';
}
public function actionSearch()
{
$this->layout='column2';
if (($term = Yii::app()->getRequest()->getParam('q', null)) !== null) {
$index = new Zend_Search_Lucene(Yii::getPathOfAlias('application.' . $this->_indexFiles));
$results = $index->find($term);
$query = Zend_Search_Lucene_Search_QueryParser::parse($term);
$this->render('search', compact('results', 'term', 'query'));
}
}
}
Any ideas to solve this problem? Thanks for any help.
EDIT: OK, the solution was quite obvious. Index wasn't writed because it wasn't really declared...
this private $_indexFiles = 'runtime.search'; before init should just be in actionCreate function - then it works
Thanks for your help!
You have a typo:
$posts = News::model()->findAll();
foreach($news as $news){
Should be:
$posts = News::model()->findAll();
foreach($posts as $news){

How to use locale in select query in Zend model

On my administrator cms I can add newsitems and add a language code in column 'language' to the newsitem 'en' or 'nl'. In the bootstrapfile the language is set through:
public function _initLanguage()
{
$objSessionLanguage= new Zend_Session_Namespace('Zend_Lang');
$objLocale = new Zend_Locale();
$locale = new Zend_Locale();
$language = $locale->getLanguage();
$region = $locale->getRegion();
Zend_Loader::loadClass('Zend_Controller_Request_Http');
$request = new Zend_Controller_Request_Http();
if($language=='nl' or $language=='en')
{
if($language=='nl')
{
$localFile = 'dutch.php';
$Locale = 'nl';
}else
{ {
$localFile = 'english.php';
$Locale = 'en';
}
$objSessionLanguage->localFile=$localFile;
$objSessionLanguage->Locale=$Locale;
}else
{
if(!isset($objSessionLanguage->localFile))
{
$localFile = 'english.php';
$Locale = 'en';
}else
{
$localFile = $objSessionLanguage->localFile;
$Locale =$objSessionLanguage->Locale;
}
}
$objTranslate = new Zend_Translate('array', APPLICATION_PATH .'/../language/english.php', 'en');
$objTranslate->addTranslation(APPLICATION_PATH .'/../language/'.$localFile, $Locale);
$objTranslate->setLocale($Locale);
Zend_Registry::set("Zend_Translate", $objTranslate);
}
To display newsitems in a NewsList I want to select the newsitems in the newsmodel depending on language.
<?php
class Admin_Model_News extends Zend_Db_Table_Abstract
{
protected $_modelName = 'news';
protected $_modelLabel = 'News';
protected $_name = 'news';
protected $_objGeneralSettingVar;
public function init()
{
parent::init();
$this->_objGeneralSettingVar = Zend_Registry::get( "objGeneralSettingVar");
}
public function fetchNewsList()
{
$objSelect = $this->select()->limit(5);
$objSelect->where ("language = '$language'");
$objSelect->order("news_date DESC");
return $this->fetchAll($objSelect)->toArray();
}
}
But with the above
$objSelect->where ("language = '$language'");
no newsitems is displayed. I am sure I am missing something but can not seem to find it. How can I use the language setting in selecting newsitems on language?
In Admin_Model_News you are using
$objSelect->where ("language = '$language'");
for your where clause, but $language has not been set anywhere, so you are querying Where language = null.
The function fetchNewsList should look like this:-
public function fetchNewsList($language)
{
$objSelect = $this->select()->limit(5);
$objSelect->where ("language = '$language'");
$objSelect->order("news_date DESC");
return $this->fetchAll($objSelect)->toArray();
}
You don't show how you are using Admin_Model_News, but it should be something like this:-
$news = new Admin_Model_News();
$newList = $news->fetchNewsList(howeverYouGetlanguage());

Zend Framework - Passing a variable request in controller

In one of these php frameworks I've noticed a posibility to request the object Request in action as $this->request->paramName
class MyRequest extends Zend_Controller_Request_Http{
public $params = array();
public function __construct() {
$this->params = $this->getParams();
parent::__construct();
}
public function __get($name) {
if (isset($this->_params[$name])) {
return $this->_params[$name];
}
}
public function __isset($name) {
return isset($this->_params[$name]);
}
}
in MyController I've added variable request
public $request = null;
How can I change that standart Request to my one?
public function __construct(
Zend_Controller_Request_Abstract $request,
Zend_Controller_Response_Abstract $response,
array $invokeArgs = array()) {
$request = new MyRequest();
parent::__construct($request, $response, $invokeArgs);
$this->request = $this->getRequest();
}
This function has given no results.
Option 1 is make method _initRequest() in bootstrap:
protected function _initRequest() {
$this->bootstrap ( 'FrontController' );
$front = $this->getResource ( 'FrontController' );
$request = $front->getRequest ();
if (null === $front->getRequest ()) {
$request = new MyRequest();
$front->setRequest ( $request );
}
return $request;
}
A bit dirty and untested solution. Would love to hear if it works.
//Bootstrap:
public function _initRequest()
{
$this->bootstrap('frontController');
$front = $this->getResource('frontController');
$front->setRequest(new MyRequest());
}
Try this it might help you:
in controller file
public function exampleAction(){
$result = $this->_request;
$model = new Employer_Model_JobInfo();
$results = $model->sample($result);
}
// the above line stores the values sent from the client side in $result.then sends that values to Model file with parameter $result ..
in model file
class Employer_Model_JobInfo extends Gears_Db_Table_Abstract{
public function sample($param){
$paramVal = $param->getParam('name');
$paramVal1 = $param->getParam('email');
}
}
The name and email are what name used to sent the data from client to server.