Is this a valid way to check if db_row exists? - zend-framework

I am working with Zend and I needed to check whether a row in the DB already exists (A simple solution to get rid of the duplicate key error I was getting). I tried several things but nothing seemed to work... (for example the Zend_Validate_Db_NoRecordExists method)
So I wrote the following the code and I was wondering if this is a valid way to do it, or if I should do things differently:
In the model:
$where = $condition = array(
'user_id = ' . $user_id,
'page_id = ' . $page_id
);
$check = $this->fetchRow($where);
if(count($check) > 0) {
return null;
}else{
// Here I create a new row, fill it with data, save and return it.
}
And then in my view:
if($this->result != null) { /* do stuff */ }else{ /* do other stuff */ }
It does work but it does seem to take more time (duh, because of the extra query) and I am a bit unsure whether I should stick with this..
Any recommendation is welcome :)

Assuming you have coded your function in your controller
$row = $this->fetchRow($where); //If no row is found then $row is null .
if(!$row)
{
$row = $dbTb->createNew($insert); //$insert an associative array where it keys map cols of table
$row->save();
$this->view->row_not_found = true;
}
return $row;
In your view you can do this
if($this->row_not_found)
{
}else {
}

Related

Access an array item in Perl after generating that array

Hello I want to access an specific array item based in a condition previously checked. I leave the code here:
elsif (scalar(#{$boss->bosses}) > 1) {
foreach my $pa (#{$boss->bosses}) {
my $p = My::Model::Group->new(id => $pa->group_id);
push(#$groups, $p);
$valid_pass = 1 if ($pa->checkPassword($self->param('password')));
}
if ($valid_pass) {
my $pa_id = $pa->id;
my $pa_partner_id = $pa->group_id;
}
else {
}
}
What I want to do is, if that if in the array that comes, I check if the password is correct, so if it's correct, then I want to take the id and the group_id of the array item to use it in a function to be able to log them in.
Your for loop is doing two things at once: producing a list of My::Model::Group objects in #$groups, and finding the first boss whose password checks out.
I suggest that you split them up into two clear operations, and the List::Util modules first operator is ideal for the second task
Here's how it would look. I've extracted the result of the method call $boss->bosses into a variable $bosses to avoid repeated calls to the method
Note that you don't need to apply scalar to an array when checking its size. The > and all the other comparators impose scalar context anyway
I've taken much of my code from your question, and I'm a little concerned that you extract values for $pa_id and $pa_partner_id and then just discard them. But I imagine that you know what you really want to do here
use List::Util 'first';
my $bosses = $boss->bosses;
if ( ... ) {
...;
}
elsif ( #$bosses > 1 ) {
#$groups = map { My::Model::Group->new( id => $_->group_id ) } #$bosses;
my $password = $self->param( 'password' );
my $pa = first { $_->checkPassword( $password ) } #$bosses;
if ( $pa ) {
my $pa_id = $pa->id;
my $pa_partner_id = $pa->group_id;
}
else {
...;
}
}

What are the reordering columns on laravel-backpack?

In the official documentation, the following columns are mentioned :
parent_id
lft
rgt
depth
I haven't found any explanation of their types in the documentation. Could someone help me and tell me what they are ?
I also want to know if they are all mandatory if I only want to reorder a list of items (I don't need any nesting).
Edit: As this question is quite popular, I've updated the documentation with the correct info.
The reordering id columns should be integer or INT(10) if you're not using a migration.
Unfortunately they're all mandatory, yes. But if you're on a very strict DB schema, you could eliminate all of them except the "lft" column by adding this method to your EntityCrudController (basically overwriting the one in Backpack\CRUD\app\Http\Controllers\CrudFeatures\Reorder):
public function saveReorder()
{
$this->crud->hasAccessOrFail('reorder');
$all_entries = \Request::input('tree');
if (count($all_entries)) {
$count = 0;
foreach ($all_entries as $key => $entry) {
if ($entry['item_id'] != '' && $entry['item_id'] != null) {
$item = $this->crud->model->find($entry['item_id']);
$item->lft = empty($entry['left']) ? null : $entry['left'];
$item->save();
$count++;
}
}
} else {
return false;
}
return 'success for '.$count.' items';
}

Zend Framework, echo message if (!$row) not working

This should be straight forward if the row count is 0 I want to echo a message. Here is what I have:
public function getClubComment($id) {
$id = (int) $id;
$row = $this->fetchRow('club_id = ' . $id);
if (!$row) {
echo 'No comments';
}
return $row->toArray();
var_dump($row);
}
maybe try something like:
//not sure if this will work as I don't do this kind of request anymore
public function getClubComment($id) {
$id = (int) $id;
$row = $this->fetchRow('club_id = ?', $id);
if (!$row) {echo 'No comments';}
return $row->toArray();
var_dump($row);
}
I think you'll be happier doing something like this, takes most of the guess work out.
public function getClubComment($id) {
$id = (int) $id;
//create instance of Zend_Db_Select object
$select = $this select();
$select->where('club_id = ?', $id);
//fetchRow using Zend_Db_Select object
$row = $this->fetchRow($select);
//fetchRow() returns NULL so may as well test for that.
if ($row === NULL) {
throw new Zend_Db_Table_Exception();
}
return $row->toArray();
var_dump($row);
}
Zend_Db_Select is really useful to use in the models as it normally takes care of properly quoting values and it very easy to build a fairly complex sql query with any sql. In this example I used discrete lines for each part of the select() but I could as easily have strung them all together. I personally like each line separate so I can change or troubleshoot easily.
fetchRow returns an object, even if there is no results, that is why the condition in the if statement is always false, try this
if (!count($row))

How can I set the order of Zend Form Elements and avoid duplicates

In Zend Form, if two elements have the same order, then Zend will totally ignores the second element (instead of displaying it under the first). Take the following code as an example. Notice that the City and Zip Code elements have the same order of 4
$address = new Zend_Form_Element_Textarea('address');
$address->setLabel('Address')
->setAttrib('cols', 20)
->setAttrib('rows', 2)
->setOrder(3)
;
$city = new Zend_Form_Element_Text('city');
$city->setLabel('City')
->setOrder(4)
;
$postal = new Zend_Form_Element_Text('postal');
$postal->setLabel('Zip Code')
->setOrder(4);
When this form renders, the Zip Code element is nowhere to be found.
If I want to set elements like a buttons dynamically, but tell it to render at the end of the form, how would I do this and not run into the problem of having two elements with the same order?
public function addSubmitButton($label = "Submit", $order = null)
{
$form_name = $this->getName();
// Convert Label to a lowercase no spaces handle
$handle = strtolower(str_replace(" ","_",$label));
$submit = new Zend_Form_Element_Submit($handle);
$submit->setLabel($label)
->setAttrib('id', $form_name . "_" . $handle)
;
///////// Set the button order to be at the end of the form /////////
$submit->setOrder(??????);
$this->addElement($submit);
}
If you really need to use the setOrder() method, I'd work with order numbers 10, 20, 30, 40, ... This way it will be easy to add elements in between already set Elements.
Furthermore, in order to avoid using order-numbers twice, you could use an array, where you store all the numbers from 1 to X. Whenever you set an order number, you set it via a method called getOrderNumberFromArray() which returns the next higher or lower order number still available in the array and unsets this array element.
Alternatively, and maybe even better, you could do getOrder() on the element you want to have before the new element, then increment this order number by X and then loop through the existing form elements and check that the order number doesn't exist yet.
Or you could just use getOrder() on the Element you want to show before and after the new element and make sure you don't use the same order numbers for the new element.
Sorry to be late to the question. What I did was extend Zend_Form and override the _sort() method as follows:
/**
* Sort items according to their order
*
* #return void
*/
protected function _sort()
{
if ($this->_orderUpdated) {
$items = array();
$index = 0;
foreach ($this->_order as $key => $order) {
if (null === $order) {
if (null === ($order = $this->{$key}->getOrder())) {
while (array_search($index, $this->_order, true)) {
++$index;
}
$items[$index][]= $key;
++$index;
} else {
$items[$order][]= $key;
}
} else {
$items[$order][]= $key;
}
}
ksort($items);
$index = 0;
foreach($items as $i=>$item){
foreach($item as $subItem){
$newItems[$index++]=$subItem;
}
}
$items = array_flip($newItems);
asort($items);
$this->_order = $items;
$this->_orderUpdated = false;
}
}
This differs from the original sort method by putting the items in an array based off of their index and then doing a depth-first traversal to flatten the array.
Try this code:
$elements = array();
$elements[] = new Zend_Form_Element_Textarea('address');
......
$elements[] = new Zend_Form_Element_Text('city');
.......
$elements[] = new Zend_Form_Element_Submit($handle);
.....
$this->addElements($elements);
All you need to do is add them in the order you want them to show
what i would do is - use a temp array for that - in that keep the element names in desired order (don't mind the keys). Then use foreach like this:
foreach(array_values($tempArray) as $order => $name) {
$form->$name->setOrder($order+1);
}
Note the array_values - it will return the values as numbered array ;) Not sure if setOrder(0) works - that's why there is +1

Indexing Adds/Changes not working using Lucene in Zend Framework

I am pretty new to programming and definitely to Zend/Lucene indexing. From what I can tell, though, my code is correct. I feel like I may be overlooking a step or something trying to upload changes and adds to the database so that they appear in the search on my website. I'm not getting any kind of an error message though. Below is the code from the controller. I guess let me know if you need anything else to help this make sense. Thanks in advance for any direction you can give.
class SearchController extends Zend_Controller_Action
{
public function init()
{
$auth = Zend_Auth::getInstance();
if($auth->hasIdentity()) {
$this->view->identity = $auth->getIdentity();
}
}
public function indexAction()
{
// action body
}
public function buildAction()
{
// create the index
$index = Zend_Search_Lucene::open(APPLICATION_PATH . '/indexes');
$page = $this->_request->getParam('page');
// build product pages
if ($page == 'search') {
$mdl = new Model_Search();
$search = $mdl->fetchAll();
if ($search->count() > 0) {
foreach ($search as $s) {
$doc = new Zend_Search_Lucene_Document();
$doc->addField(Zend_Search_Lucene_Field::unIndexed('id', $s->id));
$doc->addField(Zend_Search_Lucene_Field::text('name', $s->name));
$doc->addField(Zend_Search_Lucene_Field::text('uri', $s->uri));
$doc->addField(Zend_Search_Lucene_Field::text('description', $s->description));
$index->addDocument($doc);
}
}
$index->optimize();
$this->view->indexSize = $index->numDocs();
}
}
public function resultsAction()
{
if($this->_request->isPost()) {
$keywords = $this->_request->getParam('query');
$query = Zend_Search_Lucene_Search_QueryParser::parse($keywords);
$index = Zend_Search_Lucene::open(APPLICATION_PATH . '/indexes');
$hits = $index->find($query);
$this->view->results = $hits;
$this->view->keywords = $keywords;
} else {
$this->view->results = null;
}
}
}
Lucene indexes won't stay in sync with your database automatically, you either need to rebuild the entire index or remove and re-add the relevant documents when they change (you cannot edit an existing document).
public function updateAction()
{
// something made the db change
$hits = $index->find("name: " . $name);
foreach($hits as $hit) {
$index->delete($hit->id)
}
$doc = new Zend_Search_Lucene_Document();
// build your doc
$index->add($doc);
}
Note that lucene documents had their own internal id property, and be careful not to mistake it for an id keyword that you provide.