Hello why I have this execption:
This is controller:
public function addnew(Request $request)
{
$data = \Input::except(array('_token')) ;
$rule=array(
'restaurant_type' => 'required',
'restaurant_name' => 'required',
'restaurant_address' => 'required',
'restaurant_logo' => 'mimes:jpg,jpeg,gif,png'
);
$validator = \Validator::make($data,$rule);
if ($validator->fails())
{
return redirect()->back()->withErrors($validator->messages());
}
$inputs = $request->all();
if(!empty($inputs['id'])){
$restaurant_obj = Restaurants::findOrFail($inputs['id']);
}else{
$restaurant_obj = new Restaurants;
}
//Slug
if($inputs['restaurant_slug']=="")
{
$restaurant_slug = str_slug($inputs['restaurant_name'], "-");
}
else
{
$restaurant_slug =str_slug($inputs['restaurant_slug'], "-");
}
//Logo image
$restaurant_logo = $request->file('restaurant_logo');
if($restaurant_logo){
\File::delete(public_path() .'/upload/restaurants/'.$restaurant_obj->restaurant_logo.'-b.jpg');
\File::delete(public_path() .'/upload/restaurants/'.$restaurant_obj->restaurant_logo.'-s.jpg');
$tmpFilePath = 'upload/restaurants/';
$hardPath = substr($restaurant_slug,0,100).'_'.time();
$img = Image::make($restaurant_logo);
$img->fit(120, 120)->save($tmpFilePath.$hardPath.'-b.jpg');
$img->fit(98, 98)->save($tmpFilePath.$hardPath. '-s.jpg');
$restaurant_obj->restaurant_logo = $hardPath;
}
$user_id=Auth::User()->id;
$restaurant_obj->user_id = $user_id;
$restaurant_obj->restaurant_type = $inputs['restaurant_type'];
$restaurant_obj->restaurant_name = $inputs['restaurant_name'];
$restaurant_obj->restaurant_slug = $restaurant_slug;
$address = $restaurant_obj->restaurant_address = $inputs['restaurant_address'];
$restaurant_obj->restaurant_description = $inputs['restaurant_description'];
//ne radi??
$getGeoCode = Geocode::make()->address($address);
if($getGeoCode){
$latitude = $getGeoCode->latitude();
$longitude = $getGeoCode->longitude();
$restaurant_obj->latitude = $inputs['latitude'];
$restaurant_obj->longitude = $inputs['longitude'];
}
$restaurant_obj->open_monday = $inputs['open_monday'];
$restaurant_obj->open_tuesday = $inputs['open_tuesday'];
$restaurant_obj->open_wednesday = $inputs['open_wednesday'];
$restaurant_obj->open_thursday = $inputs['open_thursday'];
$restaurant_obj->open_friday = $inputs['open_friday'];
$restaurant_obj->open_saturday = $inputs['open_saturday'];
$restaurant_obj->open_sunday = $inputs['open_sunday'];
$restaurant_obj->save();
if(!empty($inputs['id'])){
\Session::flash('flash_message', 'Changes Saved');
return \Redirect::back();
}else{
\Session::flash('flash_message', 'Added');
return \Redirect::back();
}
}
This is model:
class Restaurants extends Model
{
protected $table = 'restaurants';
protected $fillable = ['type', 'restaurant_name','restaurant_slug','restaurant_description','restaurant_address','delivery_charge','restaurant_logo', 'latitude', 'longitude'];
public $timestamps = false;
public function restaurants()
{
return $this->hasMany('App\Restaurants', 'id');
}
public static function getRestaurantsInfo($id)
{
return Restaurants::find($id);
}
public static function getUserRestaurant($id)
{
return Restaurants::where('user_id',$id)->count();
}
public static function getMenuCategories($id)
{
return Categories::where('restaurant_id',$id)->count();
}
public static function getMenuItems($id)
{
return Menu::where('restaurant_id',$id)->count();
}
public static function getOrders($id)
{
return Order::where('restaurant_id',$id)->count();
}
public static function getTotalRestaurants()
{
return Restaurants::count();
}
public function scopeSearchByKeyword($query, $keyword)
{
if ($keyword!='') {
$query->where(function ($query) use ($keyword) {
$query->where("restaurant_address", "LIKE","%$keyword%")
->orWhere("restaurant_name", "LIKE", "%$keyword%");
});
}
return $query;
}
public static function getRestaurantOwnerInfo()
{
$rest=Restaurants::find($id);
return User::find($rest->user_id);
}
}
I try everything that can remember composer dump-autoload, php artisan migrate:rollback, and again make migration etc. I have fields in my db latitude and longitude. Thanks.
It seems you're wanting to do the following by the code you posted:
if($getGeoCode){
$restaurant_obj->latitude = $getGeoCode->latitude();
$restaurant_obj->longitude = $getGeoCode->longitude();
}
$inputs['latitude'] doesnt existe . add latidue into your rule validation to make sur or do dd(Input:all()) to make sure $inputs['latitude'] exist
Related
I am getting error in my model file
An uncaught Exception was encountered
Type: Error
Message: Call to a member function row() on bool
Filename: application/models/Ledger_model.php
Line Number: 47
Backtrace:
File: application/controllers/Purchase.php
Line: 56
Function: get_branch_from_ledger_id
File: index.php
Line: 315
Function: require_once
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Ledger_model extends CI_Model
{
function __construct() {
parent::__construct();
}
public function index(){
}
/*
return all discount details to display list
*/
public function get_records(){
return $this->db->select('l.*,a.group_title')
->from('ledger l')
->join('account_group a','a.id = l.accountgroup_id')
->get()
->result();
}
public function get_records_by_accountgroup_category($category)
{
return $this->db->select('l.*,a.group_title')
->from('ledger l')
->join('account_group a','a.id = l.accountgroup_id')
->where_in('category',$category)
->get()
->result();
}
function get_single_record($id)
{
return $this->db->get_where("ledger",array('id'=>$id))->row();
}
function get_branch_from_ledger_id($id)
{
return $this->db->select('l.*,a.branch_id')
->from('ledger l')
->join('account_group a','a.id = l.accountgroup_id')
->where('l.id',$id)
->get()
->row()
->branch_id;
}
// public function get_records_by_branch($branch_id)
// {
// return $this->db->select('l.*,b.branch_name as branch_name,ag.category as category')
// ->from('ledger l')
// ->join('account_group ag','l.accountgroup_id = ag.id')
// ->join('account_group_branch agb','agb.account_group_id = l.accountgroup_id')
// ->join('branch b','b.branch_id = agb.branch_id')
// ->where('b.branch_id',$branch_id)
// ->get()
// ->result();
// }
function add_record($data)
{
if($this->db->insert('ledger',$data))
{
return $this->db->insert_id();
}else
{
return FALSE;
}
}
function edit_record($data,$id)
{
$this->db->where('id',$id);
if($this->db->update('ledger',$data)){
// echo $this->db->last_query();
// exit;
return true;
}else{
return false;
}
}
function delete_record($id)
{
// $ledger = $this->db->get_where('ledger',array('accountgroup_id'=>$id))->result();
// $no_ledger = sizeof($ledger);
// echo $no_users;
// exit;
// if($no_ledger > 0)
// {
// return $no_ledger;
// }
// else
// {
$this->db->where('id', $id);
if($this->db->delete('ledger'))
{
return true;
}
else
{
return false;
}
// }
}
public function getBranch()
{
$this->db->select('branch_id,branch_name');
$branch = $this->db->get('branch');
return $array = $branch->result_array();
}
public function getAccountGroup()
{
$this->db->select('id,group_title');
$acc_group = $this->db->get('account_group');
return $array = $acc_group->result_array();
}
public function addModel($data){
$sql = "insert into discount (discount_name,discount_value,user_id) values(?,?,?)";
if($this->db->query($sql,$data)){
return TRUE;
}
else{
return FALSE;
}
}
public function getRecord($id){
$sql = "select * from discount where discount_id = ?";
if($query = $this->db->query($sql,array($id))){
return $query->result();
}
else{
return FALSE;
}
}
public function editModel($data,$id){
$sql = "update discount set discount_name = ?,discount_value = ? where discount_id = ?";
if($this->db->query($sql,array($data['discount_name'],$data['discount_value'],$id))){
return TRUE;
}
else{
return FALSE;
}
}
public function deleteModel($id){
$sql = "delete from discount where discount_id = ?";
if($this->db->query($sql,array($id))){
return TRUE;
}
else{
return FALSE;
}
}
public function addLedger($data)
{
$this->db->insert('ledger', $data);
return $this->db->insert_id();
}
public function getledgerWithJoin($id)
{
$this->db->select('L.*,B.branch_name,A.group_title');
$this->db->from('ledger AS L');// I use aliasing make joins easier
$this->db->join('branch AS B', 'B.id = L.branch_id', 'INNER');
$this->db->join('account_group AS A', 'A.id = L.accountgroup_id', 'INNER');
$this->db->where('L.id',$id);
$q = $this->db->get();
if( $q->num_rows() > 0 )
{
return $q->row();
}
return FALSE;
}
public function getledgerById($id)
{
$q = $this->db->get_where('ledger', array('id' => $id), 1);
if( $q->num_rows() > 0 )
{
return $q->row();
}
return FALSE;
}
public function updateLedger($ledgerDetail,$id)
{
$ledgerData = array(
'branch_id' => $ledgerDetail['branch_id'],
'type' => $ledgerDetail['type'],
'title' => $ledgerDetail['title'],
'accountgroup_id' => $ledgerDetail['accountgroup_id'],
'opening_balance' => $ledgerDetail['opening_balance'],
'closing_balance' => $ledgerDetail['closing_balance'],
);
$this->db->where('id', $id);
if($this->db->update('ledger', $ledgerData)) {
return true;
}
return false;
}
public function getBillerLedgerDetail($ledger_id){
$user = $this->db->get_where('biller', array('ledger_id' => $ledger_id))->row();
if(is_null($user)){
return false;
}else{
return $user->biller_id;
}
}
public function getCustomerLedgerDetails($ledger_id){
$user = $this->db->get_where('customer', array('ledger_id' => $ledger_id))->row();
if(is_null($user)){
return false;
}else{
return $user->customer_id;
}
}
public function getBankLedgerDetails($ledger_id){
$user = $this->db->get_where('bank_account', array('ledger_id' => $ledger_id))->row();
if(is_null($user)){
return false;
}else{
return true;
}
}
public function getSuppliersLedgerDetails($ledger_id){
$user = $this->db->get_where('suppliers', array('ledger_id' => $ledger_id))->row();
if(is_null($user)){
return false;
}else{
return true;
}
}
public function getPurchaserLedgerDetails($ledger_id){
$user = $this->db->get_where('users', array('ledger_id' => $ledger_id))->row();
if(is_null($user)){
return false;
}else{
return $user->id;
}
}
public function deleteLedger($id)
{
if($this->db->delete('ledger', array('id' => $id))) {
return true;
}
return FALSE;
}
}
?>
It sounds like there were no results, so there was nothing to get. Try this to check for results before you attempt to grab it.
function get_branch_from_ledger_id($id)
{
$rows = $this->db->select('l.*,a.branch_id')
->from('ledger l')
->join('account_group a','a.id = l.accountgroup_id')
->where('l.id',$id)
->get();
return $rows ? $rows->row()->branch_id : false;
}
I've made a website in symfony. This website contains some forms with a checkbox choice and other fields.
The datas from the checkbox are serialized on flush.
It's all good.
Now i have to export this datas and i use the data exporter library from Sonata project. But the datas are still serialized and i have some things like that in my csv file:
a:2:{i:0;s:6:"Volets";i:1;s:22:"Panneau de remplissage";}
How can I unserialize my datas in order to have a clean csv file?
Here's my code
My controller
/**
* #Security("has_role('ROLE_WEBFORM')")
*/
public function exportAction(Request $request)
{
$filters = array();
$this->handleFilterForm($request, $filters);
if (!$filters['webform']) {
throw $this->createNotFoundException();
}
$webForm = $this->getRepository('CoreBundle:WebForm')->find($filters['webform']);
$source = new WebFormEntryIterator($webForm, $this->getEntityManager(), $this->get('ines_core.embedded_form.field_type_registry'), $filters);
return WebFormEntryExporter::createResponse('export.csv', $source);
}
and my class WebFormEntryExporter
class WebFormEntryExporter
{
public static function createResponse($filename, SourceIteratorInterface $source)
{
$writer = new CsvWriter('php://output', ';', '"', "", true, true);
$contentType = 'text/csv';
$callback = function() use ($source, $writer) {
$handler = \Exporter\Handler::create($source, $writer);
$handler->export();
};
return new StreamedResponse($callback, 200, [
'Content-Type' => $contentType,
'Content-Disposition' => sprintf('attachment; filename=%s', $filename)
]);
}
}
And my WebFormEntryIterator
class WebFormEntryIterator implements SourceIteratorInterface
{
protected $em;
protected $registry;
protected $repository;
protected $query;
protected $webForm;
protected $iterator;
public function __construct(WebForm $webForm, EntityManager $em, FieldTypeRegistry $registry, array $filters)
{
$this->webForm = $webForm;
$this->em = $em;
$this->registry = $registry;
$this->initQuery($filters);
}
/**
* {#inheritdoc}
*/
public function current()
{
$current = $this->iterator->current();
$entity = $current[0];
$data = [];
$data['ID'] = $entity->getId();
$data['Formulaire'] = $this->webForm->getName();
$data['Date de création'] = date_format($entity->getCreatedAt(), 'd/m/Y H:i:s');
foreach ($this->webForm->getEmbeddedFieldConfigs() as $fieldConfig) {
$header = $fieldConfig->getLabel();
$meta = $entity->getContentMeta($fieldConfig->getName());
$extension = $this->registry->get($meta->getFormat());
if (method_exists($extension, 'setEntityManager')) {
$extension->setEntityManager($this->em);
}
$value = $extension->formatMeta($meta);
$data[$header] = $value;
unset($extension);
}
$this->query->getEntityManager()->getUnitOfWork()->detach($current[0]);
unset($entity);
unset($webForm);
return $data;
}
/**
* {#inheritdoc}
*/
public function next()
{
$this->iterator->next();
}
/**
* {#inheritdoc}
*/
public function key()
{
return $this->iterator->key();
}
/**
* {#inheritdoc}
*/
public function valid()
{
return $this->iterator->valid();
}
/**
* {#inheritdoc}
*/
public function rewind()
{
if ($this->iterator) {
throw new InvalidMethodCallException('Cannot rewind a Doctrine\ORM\Query');
}
$this->iterator = $this->query->iterate();
$this->iterator->rewind();
}
protected function initQuery(array $filters)
{
$repository = $this->em->getRepository('InesCoreBundle:Content');
$qb = $repository->getWebFormEntryQueryBuilder();
$repository->applyWfeFilters($qb, $filters);
$this->query = $qb->getQuery();
}
}
Sorry for my broken English.
Thanks a lot
thanks chalasr.
I have to make the tratment in this file, in the current() function.
This is what I've done:
public function current()
{
$current = $this->iterator->current();
$entity = $current[0];
$data = [];
$data['ID'] = $entity->getId();
$data['Formulaire'] = $this->webForm->getName();
$data['Date de création'] = date_format($entity->getCreatedAt(), 'd/m/Y H:i:s');
foreach ($this->webForm->getEmbeddedFieldConfigs() as $fieldConfig) {
$header = $fieldConfig->getLabel();
$meta = $entity->getContentMeta($fieldConfig->getName());
$extension = $this->registry->get($meta->getFormat());
if (method_exists($extension, 'setEntityManager')) {
$extension->setEntityManager($this->em);
}
$value = $extension->formatMeta($meta);
if($this->is_serialized($value)) {
$value = unserialize($value);
$data[$header] = implode(' | ', $value);
} else {
$data[$header] = $value;
}
unset($extension);
}
$this->query->getEntityManager()->getUnitOfWork()->detach($current[0]);
unset($entity);
unset($webForm);
return $data;
}
public function is_serialized($data)
{
if (trim($data) == "") { return false; }
if (preg_match("/^(i|s|a|o|d){1}:{1}(.*)/si",$data)) { return true; }
return false;
}
I created a standart class Loadercontent(controller) in Codeigniter.
Also in the same file a add abstract Search class and child class SearchDoctor:
When I try to get CI instance &get_instance(); at abstract constructor, I get NULL:
$this->_ci =&get_instance();
var_dump($this->_ci); // NULL
So after I can not use:
$this->_ci->load->view($this->view, $this->item);
because $this->_ci is empty. What is wrong in my code ot abstract class in CI? Also maybe you can ask something about code? Is it wrong?
The full code:
<?php
abstract class Search
{
protected $fields = array('country' => 'country', 'city' => 'city');
protected $table;
protected $limit = 20;
protected $offset = 0;
protected $items;
protected $rand = false;
protected $data;
protected $view;
protected $_ci;
public function __construct($input)
{
$this->_ci =&get_instance();
$this->data = $input;
$this->getPostGet();
}
public function getPostGet(){
if(empty($this->data)){
foreach($this->data as $key => $val){
$this->_check($val, $key);
}
}
}
public function _check($val, $key){
if(in_array($val, $this->fields)){
$this->items[] = $this->getField($val, $key);
}
}
public function getField($value, $key){
return $key. ' = '.$value;
}
public function doQuery(){
if(!empty($this->items)){
$limit = $this->formatLimit();
$this->items = $this->other_model->getItemsTable($this->query, $this->table, $limit);
}
}
public function formatLimit(){
$this->offset = (isset($this->data['limit'])) ? $this->data['limit'] : $this->offset;
$this->limit = (isset($this->data['limit'])) ? $this->offset + $this->limit : $this->limit;
return array('offset' => $this->limit, 'limit' => $this->limit);
}
public function addFields($array){
$this->fields = array_merge($this->fields, $array);
}
public function getView(){
$this->_ci->load->view($this->view, $this->item);
}
public function response(){
echo json_encode($this->view); die();
}
}
class SearchDoctor extends Search
{
protected $fields = array('name' => 'DetailToUsersName');
public function __construct($type)
{
$this->table = 'users';
$this->view = 'users/doctors_list';
$this->limit = 10;
$this->rand = true;
$this->addFields($this->fields);
parent::__construct($type);
}
}
/* Init class */
class Loadercontent {
public function index(){
if(isset($_GET) || isset($_POST)){
$class = 'Search';
if(isset($_POST['type'])){
$type = $_POST['type'];
$input = $_POST;
}
if(isset($_GET['type'])){
$type = $_GET['type'];
$input = $_GET;
}
$class = $class.$type;
if (class_exists($class)) {
$obj = new $class($input);
$obj->getView();
$obj->response();
}
}
}
}
?>
I generated with Admin generator this:
abstract class autoNewsActions extends sfActions
{
public function preExecute()
{
$this->configuration = new newsGeneratorConfiguration();
if (!$this->getUser()->hasCredential($this->configuration->getCredentials($this->getActionName())))
{
$this->forward(sfConfig::get('sf_secure_module'), sfConfig::get('sf_secure_action'));
}
$this->dispatcher->notify(new sfEvent($this, 'admin.pre_execute', array('configuration' => $this->configuration)));
$this->helper = new newsGeneratorHelper();
parent::preExecute();
}
public function executeIndex(sfWebRequest $request)
{
// sorting
if ($request->getParameter('sort') && $this->isValidSortColumn($request->getParameter('sort')))
{
$this->setSort(array($request->getParameter('sort'), $request->getParameter('sort_type')));
}
// pager
if ($request->getParameter('page'))
{
$this->setPage($request->getParameter('page'));
}
$this->pager = $this->getPager();
$this->sort = $this->getSort();
}
public function executeFilter(sfWebRequest $request)
{
$this->setPage(1);
if ($request->hasParameter('_reset'))
{
$this->setFilters($this->configuration->getFilterDefaults());
$this->redirect('#news');
}
$this->filters = $this->configuration->getFilterForm($this->getFilters());
$this->filters->bind($request->getParameter($this->filters->getName()));
if ($this->filters->isValid())
{
$this->setFilters($this->filters->getValues());
$this->redirect('#news');
}
$this->pager = $this->getPager();
$this->sort = $this->getSort();
$this->setTemplate('index');
}
public function executeNew(sfWebRequest $request)
{
$this->form = $this->configuration->getForm();
$this->news = $this->form->getObject();
}
public function executeCreate(sfWebRequest $request)
{
$this->form = $this->configuration->getForm();
$this->news = $this->form->getObject();
$this->processForm($request, $this->form);
$this->setTemplate('new');
}
public function executeEdit(sfWebRequest $request)
{
$this->news = $this->getRoute()->getObject();
$this->form = $this->configuration->getForm($this->news);
}
public function executeUpdate(sfWebRequest $request)
{
$this->news = $this->getRoute()->getObject();
$this->form = $this->configuration->getForm($this->news);
$this->processForm($request, $this->form);
$this->setTemplate('edit');
}
public function executeDelete(sfWebRequest $request)
{
$request->checkCSRFProtection();
$this->dispatcher->notify(new sfEvent($this, 'admin.delete_object', array('object' => $this->getRoute()->getObject())));
if ($this->getRoute()->getObject()->delete())
{
$this->getUser()->setFlash('notice', 'The item was deleted successfully.');
}
$this->redirect('#news');
}
protected function processForm(sfWebRequest $request, sfForm $form)
{
$form->bind($request->getParameter($form->getName()), $request->getFiles($form->getName()));
if ($form->isValid())
{
$notice = $form->getObject()->isNew() ? 'The item was created successfully.' : 'The item was updated successfully.';
try {
$news = $form->save();
} catch (Doctrine_Validator_Exception $e) {
$errorStack = $form->getObject()->getErrorStack();
$message = get_class($form->getObject()) . ' has ' . count($errorStack) . " field" . (count($errorStack) > 1 ? 's' : null) . " with validation errors: ";
foreach ($errorStack as $field => $errors) {
$message .= "$field (" . implode(", ", $errors) . "), ";
}
$message = trim($message, ', ');
$this->getUser()->setFlash('error', $message);
return sfView::SUCCESS;
}
$this->dispatcher->notify(new sfEvent($this, 'admin.save_object', array('object' => $news)));
if ($request->hasParameter('_save_and_add'))
{
$this->getUser()->setFlash('notice', $notice.' You can add another one below.');
$this->redirect('#news_new');
}
else
{
$this->getUser()->setFlash('notice', $notice);
$this->redirect(array('sf_route' => 'news_edit', 'sf_subject' => $news));
}
}
else
{
$this->getUser()->setFlash('error', 'The item has not been saved due to some errors.', false);
}
}
protected function getFilters()
{
return $this->getUser()->getAttribute('news.filters', $this->configuration->getFilterDefaults(), 'admin_module');
}
protected function setFilters(array $filters)
{
return $this->getUser()->setAttribute('news.filters', $filters, 'admin_module');
}
protected function getPager()
{
$pager = $this->configuration->getPager('News');
$pager->setQuery($this->buildQuery());
$pager->setPage($this->getPage());
$pager->init();
return $pager;
}
protected function setPage($page)
{
$this->getUser()->setAttribute('news.page', $page, 'admin_module');
}
protected function getPage()
{
return $this->getUser()->getAttribute('news.page', 1, 'admin_module');
}
protected function buildQuery()
{
$tableMethod = $this->configuration->getTableMethod();
if (null === $this->filters)
{
$this->filters = $this->configuration->getFilterForm($this->getFilters());
}
$this->filters->setTableMethod($tableMethod);
$query = $this->filters->buildQuery($this->getFilters());
$this->addSortQuery($query);
$event = $this->dispatcher->filter(new sfEvent($this, 'admin.build_query'), $query);
$query = $event->getReturnValue();
return $query;
}
protected function addSortQuery($query)
{
if (array(null, null) == ($sort = $this->getSort()))
{
return;
}
if (!in_array(strtolower($sort[1]), array('asc', 'desc')))
{
$sort[1] = 'asc';
}
$query->addOrderBy($sort[0] . ' ' . $sort[1]);
}
protected function getSort()
{
if (null !== $sort = $this->getUser()->getAttribute('news.sort', null, 'admin_module'))
{
return $sort;
}
$this->setSort($this->configuration->getDefaultSort());
return $this->getUser()->getAttribute('news.sort', null, 'admin_module');
}
protected function setSort(array $sort)
{
if (null !== $sort[0] && null === $sort[1])
{
$sort[1] = 'asc';
}
$this->getUser()->setAttribute('news.sort', $sort, 'admin_module');
}
protected function isValidSortColumn($column)
{
return Doctrine_Core::getTable('News')->hasColumn($column);
}
}
how can i make add for this clause WHERE id > 10 for list in index? maybe in generator.yml?
Use the table_method generator.yml option.
In generator.yml:
config:
list:
table_method: buildQueryForAdminIndex
In NewsTable:
public function buildQueryForAdminIndex(Doctrine_Query $q)
{
$q->addWhere($q->getRootAlias() . '.id > ?', 10);
return $q;
}
I should note that hardcoding that id is poor form. It should be abstracted so that it is clear why the value is 10.
I am new to Zend and have been attempting to follow the Zend Quick Start Guide's example of using Data Mappers and extending Zend_Db_Table_Abstract. I think I've grasped the general concepts, but I am now wondering, how I would go about modifying the guide's example code to allow for multiple tables.
Here is the part of the code I am currently interested in modifying:
protected $_dbTable;
public function setDbTable($dbTable)
{
if (is_string($dbTable)) {
$dbTable = new $dbTable();
}
if (!$dbTable instanceof Zend_Db_Table_Abstract) {
throw new Exception('Invalid table data gateway provided');
}
$this->_dbTable = $dbTable;
return $this;
}
public function getDbTable()
{
if (null === $this->_dbTable) {
$this->setDbTable('Application_Model_DbTable_Guestbook');
}
return $this->_dbTable;
}
I have changed it to this:
protected $_dbTables;
public function setDbTable($dbTable, $tableName)
{
if (is_string($dbTable)) {
$dbTable = new $dbTable();
}
if (!$dbTable instanceof Zend_Db_Table_Abstract) {
throw new Exception('Invalid table data gateway provided');
}
$this->_dbTables[$tableName] = $dbTable;
return $this;
}
public function getDbTables()
{
if (null === $this->_dbTables) {
$this->setDbTable('Application_Model_DbTable_Courses', 'courses');
$this->setDbTable('Application_Model_DbTable_CourseTimes', 'course_times');
}
return $this->_dbTables;
}
Is this a correct way to go about implementing multiple tables within the Data Mapper pattern or would you do it differently? Thanks for your help in advance!
Assuming that you want to return data from related tables, you should either add queries with joins to one Zend_Db_Table or use Zend_Db_Table_Relationships to fetch associated data. The benefit of using Joins is that you will only do one query over many when using Relationships. The drawback is that joined tables wont return Zend_Db_Table_Row objects (iirc), but since you are going to map them onto your Domain objects anyway, it's not that much of an issue.
Structurally, you can do like I suggested in How to change Zend_Db_Table name within a Model to insert in multiple tables. Whether you create a Gateway of Gateways or simply aggregate the Table Gateways in the DataMapper directly is really up to you. Just compose them as you see fit.
I'm not sure if it's the best practice, but, this is my abstract mapper:
<?php
abstract class Zf_Model_DbTable_Mapper
{
protected $_db;
protected $_dbTable = null;
protected $_systemLogger = null;
protected $_userLogger = null;
public function __construct()
{
$this->_systemLogger = Zend_Registry::get('systemLogger');
$this->_userLogger = Zend_Registry::get('userLogger');
// Set the adapter
if(null !== $this->_dbTable)
{
$tableName = $this->_dbTable;
$this->_db = $this->$tableName->getAdapter();
}
}
public function __get($value)
{
if(isset($this->$value))
{
return $this->$value;
}
$dbTable = 'Model_DbTable_' . $value;
$mapper = 'Model_' . $value;
if(class_exists($dbTable))
{
return new $dbTable;
}
elseif(class_exists($mapper))
{
return new $mapper;
}
else
{
throw new Exception("The property, DbTable or Mapper \"$value\" doesn't exists");
}
}
public function __set($key,$value)
{
$this->$key = $value;
}
public function getById($id)
{
$resource = $this->getDefaultResource();
$id = (int)$id;
$row = $resource->fetchRow('id =' . $id);
if (!$row) {
throw new Exception("Count not find row $id");
}
return $row;
}
public function getAll()
{
$resource = $this->getDefaultResource();
return $resource->fetchAll()->toArray();
}
public function save(Zf_Model $Model)
{
$dbTable = $this->getDefaultResource();
$data = $Model->toArray();
if(false === $data) return false;
if(false === $Model->isNew())
{
if(1 == $dbTable->update($data, 'id =' . (int)$Model->getId()))
{
return $Model;
}
}
else
{
$id = $dbTable->insert($data);
if($id)
{
$Model->setId($id);
return $Model;
}
}
return false;
}
public function remove($id)
{
return $this->getDefaultResource()->delete('id =' . (int) $id);
}
protected function getDefaultResource()
{
if(empty($this->_dbTable))
{
throw new Exception('The $_dbTable property was not set.');
}
$classname = 'Model_DbTable_' . $this->_dbTable;
if(!class_exists($classname))
{
throw new Exception("The Model_DbTable_\"$classname\" class was not found.");
}
return new $classname;
}
protected function getDefaultModel()
{
return current($this->_models);
}
protected function getResources()
{
return $this->_resources;
}
}
And this is one for my implemented mappers:
<?php
class Model_TwitterPostsMapper extends Zf_Model_DbTable_Mapper
{
/*
* Data Source
* #var string Zend_Db_Table name
*/
protected $_dbTable = 'TwitterPosts';
public function recordExists($Item)
{
$row = $this->TwitterPosts->fetchRow($this->TwitterPosts->select()->where('status_id =?', $Item->getSource()->getStatusId()));
if($row)
{
return $row->id;
}
return false;
}
public function getLastUpdate($options)
{
$select = $this->TwitterPosts->select()
->setIntegrityCheck(false)
->from(array('t' => 'twt_tweets'), 't.created_at')
->join(array('u' => 'twt_users'), 't.user_id = u.id', '')
->order('t.created_at DESC');
if($options['user_id'])
{
$select->where("t.user_id = ?", $options['user_id']);
}
if($options['terms'])
{
if(is_array($options['terms']))
{
$condition = '';
foreach($options['terms'] as $i => $term)
{
$condition .= ($i > 0) ? ' OR ' : '';
$condition .= $this->getAdapter()->quoteInto('content LIKE ?',"%$term%");
}
if($condition)
{
$select->where($condition);
}
}
}
return $this->TwitterPosts->fetchRow($select)->created_at;
}
public function getSinceId($term = null)
{
$select = $this->TwitterPosts->select()->setIntegrityCheck(false)
->from('twt_tweets_content', 'status_id')
->where('MATCH(content) AGAINST(? IN BOOLEAN MODE)', "$term")
->order('status_id ASC')
->limit(1);
//echo $select; exit;
$tweet = $this->TwitterPosts->fetchRow($select);
if(null !== $tweet) return $tweet->status_id;
return 0;
}
public function getAllByStatusId($statuses_id)
{
$select = $this->TwitterPosts->select()
->setIntegrityCheck(false)
->from(array('t' => 'twt_tweets'), array('t.id', 't.user_id', 't.status_id','t.user_id'))
->join(array('u' => 'twt_users'), 't.user_id = u.id', array('u.screen_name', 'u.profile_image'))
->where('status_id IN(?)', $statuses_id);
$rows = $this->TwitterPosts->fetchAll($select);
$Posts = array();
foreach($rows as $row)
{
// Here we populate the models only with the specific method return data
$data = $row->toArray();
$Post = new Model_TwitterPost($data['id']);
$Post->populate($data);
$User = new Model_TwitterUser($data['user_id']);
$User->populate($data);
$Post->setUser($User);
$Posts[] = $Post;
}
return $Posts;
}
public function getAllSince($since_id)
{
$select = $this->TwitterPosts->select()
->setIntegrityCheck(false)
->from(array('t' => 'twt_tweets'), array('t.status_id','t.user_id'))
->join(array('u' => 'twt_users'), 't.user_id = u.id', array('u.screen_name', 'u.profile_image'))
->where('status_id > ?', $since_id)
->order('t.datetime DESC');
$rows = $this->TwitterPosts->fetchAll($select);
$Posts = array();
foreach($rows as $row)
{
// Here we populate the models only with the specific method return data
// TODO: This is not a truly lazy instatiation, since there's no way to get the not setted properties
$data = $row->toArray();
$Post = new Model_TwitterPost($data);
$User = new Model_TwitterUser($data);
$Post->setUser($User);
$Posts[] = $Post;
}
return $Posts;
}
public function getTotalRatedItems($options)
{
$options = $this->prepareOptions($options);
$select = $this->TwitterPosts->select()
->setIntegrityCheck(false)
->from(array('t' => 'twt_tweets'), array('COUNT(DISTINCT t.id) AS total','r.rate'))
->join(array('u' => 'twt_users'), 't.user_id = u.id', '')
->join(array('r' => 'twt_tweets_rate'), 't.id = r.tweet_id', array('r.rate'))
->group('r.rate')
->order('t.datetime DESC');
$select = $this->prepareSelect($select, $options);
$rates = $this->TwitterPosts->fetchAll($select)->toArray();
$itemsRated = array('Green' => 0, 'Yellow' => 0, 'Orange' => 0, 'Red' => 0, 'Gray' => 0);
foreach ($rates as $rate)
{
$itemsRated[$rate['rate']] = $rate['total'];
}
return $itemsRated;
}
public function getUsersActivity($options)
{
$options = $this->prepareOptions($options);
$select = $this->TwitterPosts->select()
->setIntegrityCheck(false)
->from(array('t' => 'twt_tweets'), array('COUNT(DISTINCT t.id) AS total','DATE(t.datetime) AS datetime'))
->join(array('u' => 'twt_users'), 't.user_id = u.id', '')
->joinLeft(array('r' => 'twt_tweets_rate'), 't.id = r.tweet_id', '')
->group('t.user_id')
->order('t.datetime DESC');
$select = $this->prepareSelect($select, $options);
$activity = $this->TwitterPosts->fetchAll($select)->toArray();
return $activity;
}
public static function prepareOptions($options)
{
if(!is_array($options))
{
$options = array();
}
date_default_timezone_set('America/Sao_Paulo');
if(Zend_Date::isDate($options['start_date']))
{
$date = new Zend_Date($options['start_date']);
$date->setTime('00:00:00');
$date->setTimezone('UTC');
$options['start_date'] = $date->toString('yyyy-MM-dd HH:mm:ss');
}
if(Zend_Date::isDate($options['end_date']))
{
$date = new Zend_Date($options['end_date']);
$date->setTime('23:59:59');
$date->setTimezone('UTC');
$options['end_date'] = $date->toString('yyyy-MM-dd HH:mm:ss');
}
date_default_timezone_set('UTC');
$options['mainTerms'] = array();
if(!empty($options['terms']) && !is_array($options['terms']))
{
$options['mainTerms'] = explode(' ', $options['terms']);
}
if(!is_array($options['terms']))
{
$options['terms'] = array();
}
if($options['group_id'] || $options['client_id'])
{
$TwitterSearches = new Model_DbTable_TwitterSearches();
$options['terms'] = array_merge($TwitterSearches->getList($options),$options['terms']);
if(empty($options['terms']))
{
$options['terms'] = array();
}
}
return $options;
}
public static function prepareSelect($select, $options)
{
if($options['start_date'])
{
$select->where('t.datetime >= ?', $options['start_date']);
}
if($options['end_date'])
{
$select->where('t.datetime <= ?', $options['end_date']);
}
foreach($options['mainTerms'] as $mainTerm)
{
$select->where('t.content LIKE ?', "%$mainTerm%");
}
if($options['user_id'])
{
$select->where("t.user_id = ?", $options['user_id']);
}
if($options['terms'])
{
$select->where('MATCH (t.content) AGASINT(?)', $options['terms']);
}
if($options['rate'])
{
if($options['rate'] == 'NotRated')
{
$select->where('r.rate IS NULL');
}
else
{
$select->where('r.rate = ?', $options['rate']);
}
}
if($options['last_update'])
{
$select->where('t.created_at > ?', $options['last_update']);
}
if($options['max_datetime'])
{
$select->where('t.created_at < ?', $options['max_datetime']);
}
return $select;
}
}
The Model:
<?php
class Model_TwitterPost extends Zf_Model
{
private $_name = 'twitter';
protected $_properties = array(
'id',
'status_id',
'user_id',
'content'
);
protected $_User = null;
public function setUser(Zf_Model $User)
{
$this->_User = $User;
}
public function getUser()
{
return $this->_User;
}
public function getPermalink()
{
return 'http://twitter.com/' . $this->screen_name . '/' . $this->status_id;
}
public function hasTerm($term)
{
if(preg_match("/\b$term\b/i", $this->getContent()))
{
return true;
}
return false;
}
public function getEntityName()
{
return $this->_name;
}
public function getUserProfileLink()
{
return $this->getUser()->getProfileLink() . '/status/' . $this->getStatusId();
}
}
Abstract model (Generic Object):
<?php
abstract class Zf_Model
{
protected $_properties = array();
protected $_modified = array();
protected $_data = array();
protected $_new = true;
protected $_loaded = false;
public function __construct($id=false)
{
$id = (int)$id;
if(!empty($id))
{
$this->_data['id'] = (int)$id;
$this->setNew(false);
}
}
public function populate($data)
{
if(is_array($data) && count($data))
{
foreach($data as $k => $v)
{
if(in_array($k,$this->_properties))
{
$this->_data[$k] = $v;
}
}
}
$this->setLoaded(true);
}
public function setNew($new=true)
{
$this->_new = (bool)$new;
}
public function isNew()
{
return $this->_new;
}
public function setLoaded($loaded = true)
{
$this->_loaded = (bool)$loaded;
}
public function isLoaded()
{
return $this->_loaded;
}
public function __call($methodName, $args) {
if(method_exists($this, $methodName))
{
return $this->$methodName($args);
}
$property = $methodName;
if (preg_match('~^(set|get)(.*)$~', $methodName, $matches))
{
$filter = new Zend_Filter_Word_CamelCaseToUnderscore();
$property = strtolower($filter->filter($matches[2]));
if(in_array($property, $this->_properties))
{
if('set' == $matches[1])
{
$this->_data[$property] = $args[0];
if(true === $this->isLoaded())
{
$this->_modified[$property] = true;
}
return $this;
}
elseif('get' == $matches[1])
{
if(array_key_exists($property, $this->_data))
{
return $this->_data[$property];
}
throw new Exception("The property $property or $methodName() method was not setted for " . get_class($this));
}
}
}
throw new Exception("The property '$property' doesn't exists.");
}
public function __get($key)
{
if(isset($this->_data[$key]))
{
return $this->_data[$key];
}
return $this->$key;
}
public function __set($key,$value)
{
if(array_key_exists($key,$this->_properties))
{
$this->_data[$key] = $value;
return;
}
$this->$key = $value;
}
public function getId()
{
return (!$this->_data['id']) ? null : $this->_data['id'];
}
public function toArray()
{
// If it's a new object
if(true === $this->isNew())
{
return $this->_data;
}
// Else, if it's existing object
$data = array();
foreach($this->_modified as $k=>$v)
{
if($v)
{
$data[$k] = $this->_data[$k];
}
}
if(count($data))
{
return $data;
}
return false;
}
public function reload()
{
$this->_modified = array();
}
}