One line way to find an attribute - Yii - php

I've recently been using the controller to pass in a couple of values into my view. In my controller this is what it looks like when I pass in values from the controller to the view.
public function actionProcessPayment($id)
{
// if the account id was passed in
if(isset($_POST['listF']))
{
$account_id = $_POST['listF'];
// total due before payment
$totaldue = Recipient::model()->totaldue($id);
$result = Recipient::model()->MakePayment($id, $account_id);
if($result == 'not enough money')
{
Yii::app()->user->setFlash('not enough money', "This account does not have enough money
to make that transaction!");
$this->redirect(array('recipient/index', 'id' => $id));
}
else
$this->render('paysummary',array(
'id'=>$id,
'totaldue'=>$totaldue,
'numpeople'=>Paylist::model()->NumIndv($id),
'user_id'=>Login::model()->getUserId(),
'accountname'=>Account::model()->AccountName($account_id),
'accountbalance'=>Account::model()->AccountBalance($account_id),
''
));
}
Now, in order to get the account name (for example), I've created a function in the model called AccountName that takes in the account id as a parameter.
Like so
public function AccountName($id)
{
$model = Account::model()->findByPk($id);
return $name = $model->name;
}
This is working fine, but I feel like I am programming in a very roundabout way. Is there a way to change this to be one line of code? Is this how it should be called in the controller?

public function actionProcessPayment($id)
{
// if the account id was passed in
if(isset($_POST['listF']))
{
$account_id = $_POST['listF'];
// total due before payment
$totaldue = Recipient::model()->totaldue($id);
$result = Recipient::model()->MakePayment($id, $account_id);
$model = Account::model()->findByPk( $account_id );// <<---
if($result == 'not enough money')
{
Yii::app()->user->setFlash('not enough money', "This account does not have enough money
to make that transaction!");
$this->redirect(array('recipient/index', 'id' => $id));
}
else
$this->render('paysummary',array(
'id'=>$id,
'totaldue'=>$totaldue,
'numpeople'=>Paylist::model()->NumIndv($id),
'user_id'=>Login::model()->getUserId(),
'accountname'=>$model->name,// <<---
'accountbalance'=>$model->balance, // <<---
''
));
}

You can simply pass model to view as a param:
$account = Account::model()->findByPk($account_id);
$this->render('paysummary',array(
'id'=>$id,
'totaldue'=>$totaldue,
'numpeople'=>Paylist::model()->NumIndv($id),
'user_id'=>Login::model()->getUserId(),
'account'=>$account,
''
));
Then in the view:
<?php echo $account->name; ?>

Related

How do I set a variable `true` when updating the database has been successful?

On a blog I'm coding the admin can give an 'author'-permission to users.
When the update of the db table has been successful and their permission has been set to 'author' the admin will be headed back to the list of all current authors.
I want a message("Author has been added." for e.g) to appear on this site when it has been successful.
Of course the possibility of the db-update not working is minimal I think, but I want this case to be considered.
To do this I wanted to set a $newAuthor true when the database has been updated, but it didn't worked trying it with an if.
Here are the functions in the AdminController and the UserRepository with the db query:
//AdminController
public function permissionAuthor()
{
$id = $_GET['id'];
$permission = "author";
$newAuthor = false;
if($this->userRepository->changePermission($id, $permission)) {
$newAuthor = true;
}
header("Location: authors");
}
//UserRepository
public function changePermission($id, $permission)
{
$table = $this->getTableName();
$stmt = $this->pdo->prepare(
"UPDATE `{$table}` SET `permission` = :permission WHERE `id` = :id");
$changedPermission = $stmt->execute([
'id' => $id,
'permission' => $permission
]);
return $changedPermission;
}
// authors.php / the view
<?php if(isset($newAuthor) && $newAuthor == true):?>
<p class="error">Author has been added.</p>
<?php endif;?>
How can I achieve that $newAuthor will only be set to true when the function that updates the database has been successful and the message to be displayed in the view?
EDIT
I tried it with returning $changedPermission in the UserRepository. It might be wrong because it hasn't changed anything.
You can either check the permission before changing it and see if there's a difference, or just check if the UPDATE request worked successfully.
Since the prototype: public PDOStatement::execute ([ array $input_parameters ] ) : bool
You can check if the request has been successful by verifying the return value of the execute function like that:
$result = $stmt->execute([
'id' => $id,
'permission' => $permission
]);
if ($result == FALSE)
echo 'ERROR';
else
echo 'ok';
Also directly put $newAuthor = $this->userRepository->changePermission($id, $permission); in permissionAuthor function.
But one more thing, I don't see where you are calling your permissionAuthor function in your code ? Are you sure it's executed ?

Codeigniter 3: update Sql table column via GET superglobal

I am working on a Register and Login application with CodeIgniter 3 and Bootstrap.
In my "users" table I have an "active" column that can take either 0 or 1 as value.
I want to be able to change the value of the "active" column corresponding to a user from 0 to 1 (activate the user) by clicking a link in my users view:
The "Activate" button code in the users view:
<span class="glyphicon glyphicon-ok"></span> Enable
Still in the users view every table row has the id of the user:
<tr id="<?php echo $user->id ?>">
In my Usermodel model I have:
public function activateUser($user_id) {
$query = $this->db->get_where('users', ['id' => $user_id]);
return $query->row();
}
In my User controller I have:
public function activate($user_id) {
$this->load->model('Usermodel');
$user = $this->Usermodel->activateUser($user_id);
if ($user->active == 0) {
echo 'activate user';
} else {
echo 'user already active';
}
}
The url users/activate/1 returns "user already active" , while users/activate/2 returns "activate user", as expected. Being new to Codeigniter, I have tried numerous versions of the code above that resulted in errors:
public function activateUser($user_id) {
$query = $this->db->get_where('users', ['id' => $user_id])->update('users', $data);
return $query->row();
}
is one of those versions resulting in errors.
Can you please tell me what shall I change in the code to make work as desired?
If I understand correctly, activateUser should update the database row for that user and then return all updated user information. You are trying to mash two queries together that should be separate. Just take it in two steps:
public function activateUser($user_id) {
$user = null;
$updateQuery = $this->db->where('id', $user_id)->update('users', ['active' => 1]);
if ($updateQuery !== false) {
$userQuery = $this->db->get_where('users', ['id' => $user_id]);
$user = $userQuery->row();
}
return $user;
}
I put in a little bit of error checking; if for instance the user id was not valid this will return null.
Based on that error checking, your controller code might look something like:
public function activate($user_id) {
$this->load->model('Usermodel');
$user = $this->Usermodel->activateUser($user_id);
// $user->active will always be 1 here, unless there was an error
if (is_null($user) {
echo 'error activating user - check user id';
} else {
// I was assuming you would want to do something with the user object,
// but if not, you can simply return a success message.
echo 'user is now active';
}
}

Avoid similar controller actions

I am building a bundle for private messages between my users.
Here is my inbox action from my controller. What it does is fetches the current user's messages, it passes the query to KNPpaginator to display a part of them. I also save how many results to be displayed on the page in the database. One form is a dropdown that sends how many results to display per page. The other form is made of checkboxes and a dropdown with actions. Based on which action was selected, I pass the id's of the messages(selected checkboxes id's) to another function called markAction(which is also a page that can mark one single message by going to the specific url)
public function inboxAction(Request $request)
{
$messages = $this->getDoctrine()->getRepository('PrivateMessageBundle:Message');
$mymsg = $messages->findMyMessages($this->getUser());
$message_settings = $this->getDoctrine()->getRepository('PrivateMessageBundle:MessageSettings');
$perpage = $message_settings->findOneBy(array('user' => $this->getUser()));
$pagerform = $this->createForm(new MessageSettingsType(), $perpage);
$pagerform->handleRequest($request);
if ($pagerform->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($perpage);
$em->flush();
}
$paginator = $this->get('knp_paginator');
$pagination = $paginator->paginate(
$mymsg,
$request->query->get('page', 1)/*page number*/,
$perpage ? $perpage->getResPerPage() : 10/*limit per page*/,
array('defaultSortFieldName' => 'a.sentAt', 'defaultSortDirection' => 'desc')
);
$form = $this
->createForm(
new ActionsType(),
$mymsg->execute()
);
$form->handleRequest($request);
if ($form->isValid()) {
$data = $form->getData();
$ids = array();
foreach ($data['checkboxes'] as $checkbox) {
$ids[] = $checkbox->getId();
}
$action = $data['inboxactions'];
$this->markAction($action, $ids);
return $this->redirectToRoute('private_message_inbox');
}
return $this->render(
'#PrivateMessage/inbox.html.twig',
array(
'messageList' => $pagination,
'form' => $form->createView(),
'pagerform' => $pagerform->createView(),
)
);
}
And the mark action user in my inbox controller. Based on one parameter, I apply the respective action to the second parameter, which is one message if the page was called through routing, and can be an array of messages if called through my inboxAction. I do a few consistency checks, and then mark my message.
public function markAction($action, $msgs)
{
if (!$msgs) {
$this->addFlash(
'error',
'Select at least one message!'
);
return;
} else {
if (!$action) {
$this->addFlash(
'error',
'Select one action to apply to your items!'
);
return;
} else {
$messages = $this->getDoctrine()->getRepository('PrivateMessageBundle:Message');
$em = $this->getDoctrine()->getManager();
$msg = $messages->findBy(array('receiver' => $this->getUser(), 'id' => $msgs));
$good = 0;
foreach ($msg as $isforme) {
$good++;
switch ($action) {
case 'spam': {
if ($isforme->getIsSpam() == false) {
$isforme->setIsSpam(true);
if (!$isforme->getSeenAt()) {
$isforme->setSeenAt(new \DateTime('now'));
}
$em->persist($isforme);
}
break;
}
case 'unspam': {
if ($isforme->getIsSpam() == true) {
$isforme->setIsSpam(false);
$em->persist($isforme);
}
break;
}
case 'viewed': {
if ($isforme->getSeenAt() == false) {
$isforme->setSeenAt(new \DateTime('now'));
$em->persist($isforme);
}
break;
}
case 'unviewed': {
if ($isforme->getSeenAt() != false) {
$isforme->setSeenAt(null);
$em->persist($isforme);
}
break;
}
default: {
$this->addFlash(
'error',
'There was an error!'
);
return;
}
}
$em->flush();
}
$this->addFlash(
'notice',
$good.' message'.($good == 1 ? '' : 's').' changed!'
);
}
}
if ($action == 'unspam') {
return $this->redirectToRoute('private_message_spam');
} else {
return $this->redirectToRoute('private_message_inbox');
}
}
Being kind of new to symfony, I'm not sure how good my markAction function is. I feel like it can be simplier, but I'm not sure how to make it.
Now, my actual question. How can I render other pages of my bundle, like Sent or Spam messages? The only lines from the inboxAction that I have to change are
$mymsg = $messages->findMyMessages($this->getUser());
to have it return spam or sent messages by the user, for instance.
and
return $this->render(
'#PrivateMessage/inbox.html.twig',...
so I actually return the respective page's view. I have already made the other pages and copied the code in the other actions, but I think I can make it so I write this code a single time, but don't know how.
Everything else is EXACTLY the same. How can I not copy and paste this code in all of the other actions and make it a bit more reusable?
You could strart to change your routing more dynamic:
# app/config/routing.yml
mailclient:
path: /mailclient/{page}
defaults: { _controller: AppBundle:Mailclient:index, page: "inbox" }
Resulting that this routes:
/mailclient
/mailclient/inbox
/mailclient/sent
/mailclient/trash
will all call the same action.
Now your method (Action) will get an extra parameter:
public function indexAction($page, Request $request)
{
// ...
}
Through this parameter you know what the user likes to see. Now you can start to write your code more dynamic. You can consider to add some private functions to your controller class that you can call from the indexAction or
you could simply create your own classes too.

how to insert a value to a foreign key using session without overriding the other sessions in codeigniter?

I hope you're doing fine. Can somebody help me with my problem? I have 2 tables. The other one is for customers, it has an auto-increment value for customer_id. The other table is for orders, it has an auto-increment also for its orders_id and a foreign key from the other table (customers).
When I insert a new customer, if it is successful, I want the page to be redirected to the add new order page. In inserting new order, the customer_id field in my orders table should have the same value as the newly added customer. Adding customer and adding new order is of different function in my controller. I am having an error 1452 when inserting the new order, which means the value inserted for the foreign key customers_id in the orders table is different with the value in the other table (customers).
Now, I've got this solution using session. My problem is the other session for getting the last id is overriding the session for logging in.
Here's some code snippets from my controller:
Class MyController extends CI_Controller
{
function __construct()
{
parent::__construct();
$this->c_id = 0;
if($this->session->userdata('logged_in'))
{
$session_data = $this->session->userdata('logged_in');
$data['username'] = $session_data['username'];
if($session_data['username'] == 'administrator'){
$this->load->database('sample');
$this->load->model('samplemodel_model');
$this->load->library('form_validation');
} else {
redirect('home', 'refresh');
}
} else {
redirect('login', 'refresh');
}
}
public function index() {
if($this->session->userdata('logged_in'))
{
$session_data = $this->session->userdata('logged_in');
$data['username'] = $session_data['username'];
//code for validation here
$customers = $this->samplemodel_model->get_entries('customers');
if($this->form_validation->run() == FALSE) {
//Field validation failed.
} else {
//Insert $data
//$data = array('xxxxxx');
//data is something like that
$this->create($data);
}
}
else
{
//If there's no session it will redirect to login page
}
}
//add new orders
public function addOrders() {
if($this->session->userdata('last_inserted_id')) //if I use this session, I can get the last inserted ID but the session data for the login will not be retrieved.
{
$session_data = $this->session->userdata('last_inserted_id');
$orders = $this->samplemodel_model->get_entries('orders');
if($this->form_validation->run() == FALSE) {
//Field validation failed.
} else {
//Insert data
$data = array('customer_id' => $session_data['customer_id'],
'order_type' => $this->input->post('order_type'));
$this->createItem($data);
}
}
else
{
//If no session, redirect to login page
redirect('login', 'refresh');
}
}
//create customer
public function create($data) {
//Insert data
$customers = $this->samplemodel_model->get_entries('customers');
//$data = array(xxxxx);
//somethin' like that for data array
$this->load->samplemodel_model->create('customers', $data);
//***********************************************************//
// get and save last id inserted //
//***********************************************************//
//query the database
$result = $this->samplemodel_model->get_last_inserted($this->db->insert_id());
if($result)
{
$sess_array = array();
foreach($result as $row)
{
$sess_array = array('customer_id' => $row->customer_id);
$this->session->set_userdata('last_inserted_id', $sess_array);
}
return TRUE;
}
else
{
echo "<script type='text/javascript'>alert('error');</script>";
return false;
}
session_start('last_inserted_id');
//********************************************************//
// end //
//********************************************************//
redirect('myController/addOrders', 'refresh');
}
public function createItem($data) {
//Insert data
$orders = $this->samplemodel_model->get_entries('orders');
$data = array('customer_id' => $session_data['customer_id'],
'order_type' => $this->input->post('order_type'));
$this->load->samplemodel_model->create('orders', $data);
//I'm not so sure if it is in this function that I should place the unset for the session 'last_inserted_id'
redirect('home', 'refresh');
}
}
And in my model, I inserted another function which helps me saving the last id inserted. Here's it:
public function get_last_inserted($id)
{
$this -> db -> select('customer_id');
$this -> db -> from('customers');
$this -> db -> where('customer_id', $id);
$this -> db -> limit(1);
$query = $this -> db -> get();
if($query -> num_rows() == 1)
{
return $query->result();
}
else
{
return false;
}
}
PLEEEASE! HELP :'( I would really appreciate if you have any other ideas. THANK YOU SOOOOO MUCH!
The issue is that you're redirecting, Each HTTP request is it's own process with it's own variables, and each request can't access the variables set in other requests.
Try passing the customer ID as a parameter to addOrders(), you can then use the codeigniter way of passing params around :
http://www.example.com/controller/method/paramter
Check the docs :
https://ellislab.com/codeigniter/user-guide/general/controllers.html
under the segment : Passing URI Segments to your Functions
Other possible solution : Store the customerID in the session, or in a user object you instantiate when you create a new user, but that's more dependent of the use case.

how to validate duplicate email in magento admin on edit and add in custom module

I need to validate duplicate email in magento on edit and add action. Basically on edit if i changed email id if that is available in database then i need to got message duplicate email.... if I add then i also want to validate duplicate email in magento.
my save function in admin
public function saveAction()
{
if ($this->getRequest()->getPost())
{
try {
$postData = $this->getRequest()->getPost();
$currentTimestamp = time();
$postData['updated_at']= $currentTimestamp;
$postData['seller_other_sale_sites'] = implode(',',$postData['seller_other_sale_sites']);
$sellerModel = Mage::getModel('seller/seller');
if( $this->getRequest()->getParam('id') <= 0 )
$sellerModel->setCreatedTime(
Mage::getSingleton('core/date')
->gmtDate()
);
$sellerModel
->addData($postData)
->setUpdateTime(
Mage::getSingleton('core/date')
->gmtDate())
->setId($this->getRequest()->getParam('id'))
->save();
Mage::getSingleton('adminhtml/session')
->addSuccess('successfully saved');
Mage::getSingleton('adminhtml/session')
->settestData(false);
$this->_redirect('*/*/');
return;
} catch (Exception $e){
Mage::getSingleton('adminhtml/session')
->addError($e->getMessage());
Mage::getSingleton('adminhtml/session')
->settestData($this->getRequest()
->getPost()
);
$this->_redirect('*/*/edit',
array('id' => $this->getRequest()
->getParam('id')));
return;
}
}
$this->_redirect('*/*/');
}
I need to validate that on save function
Create a function in helper class that takes $email as parameter
public function customerExists($email, $websiteId = null)
{
$customer = Mage::getModel('customer/customer');
$customer->setWebsiteId($websiteId);
$customer->loadByEmail($email);
if ($customer->getId()) {
return $customer;
}
return false;
}
Before you perform save operation, use the helper function this way.
Mage::helper('modulename')->customerExists($email, $websiteId);
If a customer is already there it will return the customer object and if it doesn't, it will return false. So you can write remaining code/throw exception/ set error message accordingly.
from Mage_Customer_Model_Resource_Customer this code checks for unique email _beforeSave before save (unless updating an existing customer in which case it checks for duplicates on just that customer).
This is within the Mage system, but doesn't use any models.
$adapter = $this->_getWriteAdapter();
$bind = array('email' => $customer->getEmail());
$select = $adapter->select()
->from($this->getEntityTable(), array($this->getEntityIdField()))
->where('email = :email');
if ($customer->getSharingConfig()->isWebsiteScope()) {
$bind['website_id'] = (int)$customer->getWebsiteId();
$select->where('website_id = :website_id');
}
if ($customer->getId()) {
$bind['entity_id'] = (int)$customer->getId();
$select->where('entity_id != :entity_id');
}
$result = $adapter->fetchOne($select, $bind);
if ($result) {
throw Mage::exception(
'Mage_Customer', Mage::helper('customer')->__('This customer email already exists'),
Mage_Customer_Model_Customer::EXCEPTION_EMAIL_EXISTS
);
}

Categories