Is it Yii or is it me who is wrong? - php

Hi there I have written a code that ietrates through whole array and copies the images to a folder and inserts data in record. Now funny thing is that $model->save()does not show error it returns true. and program never goes into else
now what happens loop continues to run and completes its ietration without breaking. I can not guess who is wrong. greater chances are me as i am most of time :)
here is code
protected function saveImage($formData,$model)
{
if ($formData === null)
return;
$idx=0;
foreach($formData['title'] as $image)
{
$model->title = $image;
$file= dirname(Yii::app()->request->scriptFile) . DIRECTORY_SEPARATOR
. DIRECTORY_SEPARATOR .'images\hotelImages'. DIRECTORY_SEPARATOR
. $model->hotel->name;
$model->image = Yii::app()->baseUrl. "/images/hotelImages/".$_FILES['HotelImages']['name'][$idx];//image path
if($model->save())
{
echo $idx.'<br /> it was sucess<br />';
If(file_exists($file))
{
copy($_FILES['HotelImages']['tmp_name'][$idx],$file."/".$_FILES['HotelImages']['name'][$idx]);
}
else
{
mkdir($file);
copy($_FILES['HotelImages']['tmp_name'][$idx],$file."/".$_FILES['HotelImages']['name'][$idx]);
}
$idx++;
}//if there was error
else
{
print_r($model->getErrors());
yii::app()->end();
return FALSE;
}
echo '<br />end reached <br />';
}
yii::app()->end();
return true;
}
var_dump for $formdata is
array
(
'title' => array
(
'0' => 'title1'
'1' => 'title2'
)
)
No mater what ever the ietration count for foreach loop database gets only single row

The save() method inserts a record into the database if it doesn't exist yet, and otherwise updates that same database record.
$model is being passed in as a method parameter, and I'm just assuming here that its title attribute is not the primary key.
In other words, you keep updating the same database record over and over, which is why you only see one record in the database.

#fivedigit's analysis is correct. My suggested fix would be to reduce the complexity of this method. Put everything inside the foreach in its own method (e.g. saveImage), then do something like:
foreach($formData['title'] as $image) {
$this->saveImage($image, new Image);
}
This method is a bit of a super-method, and you might find it easier to break it out into different methods. Perhaps use a component to handle the file copying, instead of filling up the controller.

And once again I am wrong :)
Issue was that in each foreach ietration the $model was previous and New instant of $model was not created and yii thought that hey its old one probably this Geek is updating it. so that is it.it updates in database.
just did
$model = new HotelImages;
before populating them
I thank fivedigit for Just an idea.
I have a strong believe on this
Most people says Little knowledge is dangerous...well that is true for
all except for programmers. Programmers are rare species and what it all takes is
a little idea/hint to do the thing

Yii CActiveRecord has a variable isNewRecord, its value is true when an object is created and remains true until a find or save function is not called. When a model calls save function, isNewRecord set to false.
So in your case you need to set this variable "isNewRecord" true each time before save function called or create a new model each time than call the save function.
See the changes in your code::
$model->setIsNewRecord(True); // changes code line
protected function saveImage($formData,$model)
{
if ($formData === null)
return;
$idx=0;
foreach($formData['title'] as $image)
{
$model->setIsNewRecord(True); // for each new record
$model->title = $image;
$file= dirname(Yii::app()->request->scriptFile) . DIRECTORY_SEPARATOR
. DIRECTORY_SEPARATOR .'images\hotelImages'. DIRECTORY_SEPARATOR
. $model->hotel->name;
$model->image = Yii::app()->baseUrl. "/images/hotelImages/".$_FILES['HotelImages']['name'][$idx];//image path
if($model->save())
{
echo $idx.'<br /> it was sucess<br />';
If(file_exists($file))
{
copy($_FILES['HotelImages']['tmp_name'][$idx],$file."/".$_FILES['HotelImages']['name'][$idx]);
}
else
{
mkdir($file);
copy($_FILES['HotelImages']['tmp_name'][$idx],$file."/".$_FILES['HotelImages']['name'][$idx]);
}
$idx++;
}//if there was error
else
{
print_r($model->getErrors());
yii::app()->end();
return FALSE;
}
echo '<br />end reached <br />';
}
yii::app()->end();
return true;
}

Related

value stored as array in the database getting deleted while adding new values into the same array while updating

Here my problem is when i go for updating the values already stored in the database is getting deleted and only the newly added values are getting
here is my code
<script>
$(document).ready(function() {
if(destId=='bar3' || sourceId=='bar3') {
var itemvalue2 =Array();
$('ul#bar3 li').each(function() {
itemvalue2.push($(this).attr("value"));
});
document.getElementById("bar3-output").value=itemvalue2;
}
});
</script>
here is my view
<ul id="bar3" class="block__list block__list_tags">
<input type="hidden" id="bar3-output" name="all_active_menu3" class="form-control"
value="<?php if(!empty($team_info->members)) {
$tagsArray = explode(',', $team_info->members);
$tagsLinksArray = array();
foreach($tagsArray as $tag) {
$tagName = trim($tag);
$tagsLinksArray[]=$tagName;
}
$tagsLinks = implode(',', $tagsLinksArray);
echo $tagsLinks;}?>
">
</ul>
Here is my control
public function save_team($team_id = NULL)
{
$profile_data=$this->Teams_model->array_from_post(array('team_name'));
$this->Teams_model->_table_name = 'tbl_teams'; // table name
$this->Teams_model->_primary_key = 'team_id'; // $id
if (!empty($team_id)) {
$profile_data['members']=$this->input->post('all_active_menu3');
$this->Teams_model->save($profile_data, $team_id);
} else {
$profile_data['members']=$this->input->post('all_active_menu3');
$this->Teams_model->save($profile_data);
}
if (!empty($team_id)) {
$message = ('Team Info Updated');
} else {
$message = ('Team Info Saved');
}
$type = 'success';
set_message($type, $message);
redirect('admin/team/team_list'); //redirect page
}
the value in the database is not becoming stable i had used many ideas but didn't reached destination.hope your help please help me
I'm not certain how your code works but here is what my guess is and what is going wrong: You're just replacing the old value in both cases.
This seems to be the relevant code fragment.
$profile_data=$this->Teams_model->array_from_post(array('team_name'));
//...
if (!empty($team_id)) {
$profile_data['members']=$this->input->post('all_active_menu3');
$this->Teams_model->save($profile_data, $team_id);
} else {
$profile_data['members']=$this->input->post('all_active_menu3');
$this->Teams_model->save($profile_data);
}
The first assignment of $profile_data reads the current team data from the existing team. Your naming is a bit confusing as you're not actually reading any POST data it seems. The assignment within the if block that would fulfill the condition !empty($team_id) should update the team members and the false block should create a new team. Did you verify that $team_id gets set successfully?
I'm not certain about the structure of the team information but rather than a straight assignment using = in the true block you should be using += or manually combine the new and old data and do the assignment afterwards.
Using something like array_merge or a loop to create an intermittent object to hold the combined data should work here.

Sending Data to 2 MySQL tables - FuelPHP / PHP

I am adapting StationWagon (FuelPHP app) and so far it's working really well.
I have adapted it (with some help) to allow multiple images to be uploaded to the server. This is also working great.
However, I am thinking it would make more sense if I had 2 Tables: 1) Articles and 2) ArticleImages. I would use a Foreign Key to associate the Images with the Article. So when publishing an article it would add the article data to 'Articles' table and move each image to a new row in 'ArticleImages'.
So ultimately my 'ArticleImages' table could be:
ID | ImageURL | ArticleID
Portion of my 'articles.php' controller:
<?php
public function action_add()
{
$val = Model_Article::validate('add_article'); //<-- maybe its just me but i never saw any similar to this in fuelphp sorry about this if im wrong
// if your form validation is okay than continue with everyhing else
if ($val->run())
{
$article = Model_Article::forge();
// Custom configuration for this upload
$config = array(
'path' => DOCROOT.DS.'images',
'randomize' => true,
'ext_whitelist' => array('img', 'jpg', 'jpeg', 'gif', 'png'),
);
Upload::process($config);
// if a valid file is passed than the function will save, or if its not empty
if (Upload::is_valid())
{
// save them according to the config
Upload::save();
//if you want to save to tha database lets grab the file name
$value = Upload::get_files();
foreach($value as $files) {
print_r($files);
}
$article->filename = $value[0]['saved_as'];
}
$status = (Input::post('save_draft') ? 0 : 1);
if ( ! $val->input('category_id'))
{
$category_id = null;
}
else
{
$category_id = $val->validated('category_id');
}
$article->user_id = $this->user_id;
$article->category_id = $category_id;
$article->title = $val->validated('title');
$article->body = $val->validated('body');
$article->published = $status;
if ($article->save())
{
Session::set_flash('success', 'Article successfully added.');
}
else
{
Session::set_flash('error', 'Something went wrong, '.
'please try again!');
}
Response::redirect('articles/add');
}
$this->template->title = 'Add Article';
$this->template->content = View::forge('articles/add')
->set('categories', Model_Category::find('all'), false)
->set('val', Validation::instance('add_article'), false);
}
/* End of file articles.php */
You are trying to make a relation between Articles and ArticleImages. An ArticleImage belongs to an Article, while an Article has many ArticleImages. FuelPHP has functionality built in for what you are trying to achieve. Have a look at the FuelPHP docs on its Object Relational Mapper, especially the Belongs To and Has Many relations.
So when i made the code for you back a few days a go you only requested, one file input.
And no offense but you are doing it all wrong...
foreach($value as $files) {
print_r($files);
}
$article->filename = $value[0]['saved_as'];
should be
foreach($value as $files) {
$articleimg = Model_Articleimages::forge();
$articleimg->image_row_name = $files['saved_as']
}
To get you to understand
what you did here, $value = Upload::get_files(); yes this gets all the elements but since you need to loop trouh the elements you dont need it
Second
this $value[0]['saved_as'] only grabs the first image name, just the first one, and since you are in a loop now you need to refer to the $files variable as i shown you in the above example, just an example

Do in_array have a like function?

I have an array of people that is registered as online in a html file. I am using this so that each can have an image assigned to them. But when checking to see if using name is already in use the in_array function return false and allow the script to continue.
$user = "< img src='default.jpg' />John";
$explode = array("<img src='tress.jpg' />John");
if(in_array($user, $explode))
{
//show login script if user exists
}
else
{
//continue to script
}
Now the reason this is not working is because the john in the array is not identical to the john in $user. Is there anyway of checking that the name exists in the array? When responding please explain.
Instead of asking, "How do I solve this problem?", you need to start with, "Why am I having this problem?"
$user = "< img src='default.jpg' />John";
Is < img src='default.jpg' />John a user name? Why are you using it as one? I'm guessing there's some clever thought behind this like "Well, I always display a user's image with their name, so I'll just make the image part of their name. This is going to cause far more problems than it solves. This comes back to a big concept in computer science called separation of concerns. An image is not logically a part of a user name, so don't store it as one. If you always display them together, you can use functions to display a user's information in a standard way without making the image part of the user name.
So first off, remove the image from the name. There are several ways to store this separately.
I would suggest using a class:
class User {
public $name;
public $imageSource;
// The following functions are optional, but show how a class
// can be useful.
/**
* Create a user with the given name and URL to their image
*/
function __construct($name, $imageSource) {
$this->name = $name;
$this->imageSource = $imageSource;
}
/**
* Gets the HTML to display a user's image
*/
function image() {
return "<img src='". $this->imageSource ."' />";
}
/**
* Gets HTML to display to identify a user (including image)
*/
function display() {
return $this->image() . $this->name;
}
}
$user = new User("john", "default.jpg");
// or without the constructor defined
//$user = new User();
//$user->name = "john";
//$user->imageSource = "default.jpg";
echo $user->display();
You can use an "array" if you want to be a little lazier, but I don't recommend it in the general case, since you lose the cool features of classes (like those functions):
$user = array(
name => "john",
image => "<img src='default.jpg' />";
);
echo $user["image"] . $user["name"];
In your database (if you're using one), make them separate columns and then use one of the above data structures.
Now that you have this, it's easy to see if a user name is in a given list using a foreach loop:
function userNameInList($user, $users) {
for($users as $current) {
if($user->name == $current) {
return true;
}
}
return false;
}
$newUser = new User("John", "john.jpg");
$currentUsers = array("John", "Mary", "Bob");
if(userNameInList($newUser, $currentUsers) {
echo "Sorry, user name " . $newUser->name . " is already in use!";
}
If you're new to PHP, the normal for loop may be easier to understand:
function userNameInList($user, $users) {
for($i = 0; $i < count($users); ++i) {
$current = $users[$i];
if($user->name == $current) {
return true;
}
}
return false;
}
Let me know if any of this doesn't run, I don't write PHP very often anymore..

processing mysql assoc results through various classes

Hi I've recently started yet another project and my boss is insisting that we use the MVC model, the problem being that due to many articles showing different ways to do this we havent managed to agree on what a proper MVC model should look like.
So here's my problem for this project (whether this is the correct way to do it or not) I am using the following baseline rules
Controller classes manage both getting the data from the model classes and passing the data to the view classes and retrieving the view and displaying it
Model classes managhe all database actions and return the data using mysql_fetch_assoc
View classes create the views using the data etc.
So my issue is with processing the information from mysql_fetch_assoc normally you would do something like this (assuming we have already run a query)
while ($row = mysql_fetch_assoc($result)) {
echo $row["username"];
}
but as I'm processing the results in the view class rather than the model how do I cycle through all of the results when I have already passed the assoc array to the view, currently I'm getting a problem where it keeps looping through the results until it hits a memory size error so for some reason it isn't able to figure out how many results it needs to cycle through
My current code snippets are below sorry for the bad explainations.
Controller
require_once 'admin_model.php';
require_once 'admin_view.php';
class admin_controller {
public $model;
public $view;
public function __construct() {
$this->model = new admin_model;
$this->view = new admin_view;
}
public function get_group_view() {
$in_model = $this->model->get_group_view();
$in_view = $this->view->get_group_view ($in_model);
echo $in_view;
}
Model
class admin_model {
public function get_group_view() {
$query = mysql_query("
SELECT
group_id,
group_name
FROM
user_groups
");
return mysql_fetch_assoc($query);
}
}
View
class admin_view {
public function get_group_view($group_data) {
while($group_data) {
$output .= $group_data['group_id'] . '###' . $group_data['group_name'] . '<hr />';
}
return $output;
}
}
Which currently returns the error:
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 133693393 bytes)
So can someone please advise me on the best way to go through the results without moving 'mysql_fetch_assoc' function from the model class?
PS I know I'm probably doing MVC completely wrong but it works for us and we don't want to have to research and change our code yet again thanks.
You should not return the MySQL Result - you should do:
$return = array();
$query = mysql_query("SELECT group_id, group_name FROM user_groups");
while($row = mysql_fetch_assoc($query)) {
$return[] = $row;
}
mysql_free_result($row);
return $return;
And you should fix the $group_data bug per #Roman_S . The correct use, along with the above code is
public function get_group_view($group_data) {
$output = '';
foreach($group_data as $group) {
$output .= $group['group_id'] . '###' . $group['group_name'] . '<hr />';
}
return $output;
}
Finally you should migrate to MySQLi or PDO if possible.
You have en error here
while($group_data) {
$output .= $group_data['group_id'] . '###' . $group_data['group_name'] . '<hr />';
}
If $group_data is not empty - your loop will never end.
To give a suggestion on how to handle database control.
When using PDO for instance
$pdoInst = new PDO( .. );
and we have a method somewhere that validates every statement the $pdoInst produces
abstract class .. {
public static function validateStmt($stmt) {
if($stmt !== false) { .. }
// everything else you like, even error handling, log files, etc.
}
}
}
a prepared statement like the get_group_view method will look like the following
public function get_group_view {
$stmt = $pdoInst->prepare(" .. QUERY .. ");
// the return can be wrapped in a method to handle errors, etc, which can be done
// here or else where.
$stmt->execute() // returns true or false
return $stmt;
}
now for iteration
public function get_group_view($group_data) {
$output = "";
// validate the statement, can be done here or else where as said before
if($pdoInst::validateStmt($group_data)) {
// many ways how to iterate, foreach is just one.
foreach($group_data as $index => $group) {
$output .= $group['group_id'] . '###' . $group['group_name'] . '<hr />';
}
}
return $output;
}
The nicest thing about PDO is that you can extend the classes with custom ones. You can add functionality that adds more value to your Model.

$this->redirect display blank page in Cakephp

My code is :
public function join_membership()
{
$this->layout = 'colorbox';
$membership_id = $this->Cookie->read('membership_id');
$membership = $this->Membership->find('first', array('conditions'=>array('Membership.id'=>$membership_id)));
$this->set('membership',$membership);
if($this->request->is('post'))
{
if($this->JoinMembership->save($this->request->data['JoinMembership']))
{
$this->redirect(array('action' => 'member_login'));
}
}
}
This code save the data in database properly but after that it displays blank page, it doesn't redirect to the given function.
Thanks in advance....
In case anybody has trouble telling where their whitespace/output is (like I did), put this small block right before your $this->redirect call:
$file = '';
$line = '';
if (headers_sent($file, $line)) {
die('Output in ' . $file . ' at line ' . $line);
}
It will stop your controller action and print out the exact file and line where the whitespace/output is.
Try with the following code into your if condition.
$this->redirect(array('controller' => 'Controller_Name', 'action' => 'member_login'));
You can also try to print something into if condition you used. Also use the else part and also print something into else part. Check it in debug mode 2.
1) Is the member_login action located in the same controller as join_membership? If no then add the Controller => "Some_Controller" key value paire to the array.
2) If one does not work, check if the if condition is working like so
if($this->JoinMembership->save($this->request->data['JoinMembership']))
{
debug("in");exit();
$this->redirect(array('action' => 'member_login'));
}
}
You should see "in" message if the if condition is returning true.
Please note that you can use
$this->redirect("action_name");
$this->redirect("/controller_name/action_name");

Categories