problem with using extract php function? - php

<?php
function check($user_id, $topic_id){
$query = mysql_query("SELECT user_id, topic_id FROM sa where topic_id='$topic_id' and user_id='$user_id'");
if (mysql_num_rows($query)==1){
return 'you have already voted';
}
else {
$against = ' <li>
<button type="submit" value="Actions" class="against" title="against">
<i></i><span>Against</span></button>
</li>';
$support ='<li>
<button type="submit" value="Actions" class="support" title="support">
<i></i>
<span>Support</span>
</button>
</li>';
return compact('support', 'against');
}
extract(check($_SESSION['user_id'], $topicId));
echo $against;
echo $support;
?>
i keep getting this error:
Warning: extract() [function.extract]: First argument should be an array

The extract function expects an array. You're passing it the results of your check function, which is sometimes an array
return compact('support', 'against');
but sometimes a string.
return 'you have already voted';
So, I imagine you're seeing the error when the first return statements is executed.

Maybe something like this is better:
function check($user_id, $topic_id){
$query = mysql_query("SELECT user_id, topic_id FROM sa where topic_id='$topic_id' and user_id='$user_id'");
if (mysql_num_rows($query)==1){
return array('error'=>'you have already voted');
}
else {
$against = ' <li>
<button type="submit" value="Actions" class="against" title="against">
<i></i><span>Against</span></button>
</li>';
$support ='<li>
<button type="submit" value="Actions" class="support" title="support">
<i></i>
<span>Support</span>
</button>
</li>';
return compact('support', 'against');
}
}
$result = check($_SESSION['user_id'], $topicId);
if(isset($result['error'])) {
echo $result['error'];
}
else {
echo $result['against'];
echo $result['support'];
}
You could also consider to use exceptions.

First, function definition is not closed in your code (no closing "}")
Second, your function returns string if user has already voted - in this case PHP would obviously say "First argument should be an array" on extract() function call.
Generally, I'd recommend not to use compact-extract construction, but use structures or associative arrays as return value instead. In this case behavior would be much clearer.

So as it suggests: Warning: extract() [function.extract]: First argument should be an array
Try following:
$arr = check($_SESSION['user_id'], $topicId);
if(is_array($arr)) {
extract($arr);
echo $against;
echo $support;
} else {
echo $arr;
}

Related

Error code "Invalid argument supplied for foreach()" when using json_encode (oop, php)

I'm trying to create a to do list. When creating new posts it should encode the information to json and put the information in a json array. But somehow it seems the information isn't encoded correctly and when trying to print the posts I get the error message "Invalid argument supplied for foreach()". I just can't find where the mistake is.
I'm fairly new at this so to complex answers might be to hard for me to understand.
Edit:
Adding the whole freaking code. Something is seriously wrong. 🤦‍♀️
index:
<?php
spl_autoload_register(function ($class) {
include $class . '.class.php';
});
$allPosts = new Lista;
if(isset($_REQUEST['addNewPost'])){
$allPosts->addNewPost($_REQUEST['ett'], $_REQUEST['tva'], $_REQUEST['tre']);
}
?>
<?php $page_title = "Att göra lista";
include("includes/header.php");
?>
<?php
include("includes/sidebar.php");
?>
<h2>Min att göra lista</h2>
<form action="<?php echo $_SERVER['PHP_SELF'];?>" method="post">
Uppgift: <input type="text" name="ett"/><br/>
Utfarare: <input type="text" name="tva"/><br/>
Senast: <input type="text" name="tre"/><br/>
<input type="submit" name="addNewPost" value="Lägg till post"/>
</form>
<?php
//Loopa igenom array
foreach ($allPosts->getTheList() as $key=>$val) {
echo "<section id='postPart'>" . $val->getEtt() . "<br/>" . $val->getTva(). " " . $val->getTre(). "</section><section id='buttonPart'><button type='button' name='klar'>Avklarad!</button> <button type='button' name='deletePost'>Ta bort</button>\n";
}
//echo "<section id='postPart'>" . $_REQUEST['one'] . "<br/>" . $_REQUEST['two'] . " " . $_REQUEST['three'] . "</section><section id='buttonPart'><button type='button' name='klar'>Avklarad!</button> <button type='button' name='deletePost'>Ta bort</button>\n";
var_dump($allPosts);
?>
</body>
</html>
Class: Lista:
<?php
class Lista{
public $theList=[];
function __construct(){
if(file_exists("text.json")>0)
$this->theList = json_decode(file_get_contents('text.json'), true);
}
function addNewPost($ett, $tva, $tre){
$posten = new Post ($ett, $tva, $tre);
array_push ($this->theList, $posten);
$jsonStr = json_encode($this->theList);
file_put_contents("text.json", $jsonStr);
}
function getTheList( ){
return $this->theList;
}
}
Class Post:
<?php
class Post{
public $ett;
public $tva;
public $tre;
function __construct ($ett, $tva, $tre){
$this->ett = $ett;
$this->tva = $tva;
$this->tre = $tre;
}
function getEtt():string{
return $this->ett;
}
function getTva(){
return $this->tva;
}
function getTre(){
return $this->tre;
}
}
Besides the typo, to json_encode an array of objects your need to make an exporter method which returns an array of each property or implement JsonSerializable
<?php
class Post implements JsonSerializable {
protected $whatIs = ' ';
protected $whoIs = ' ';
protected $whenIs = ' ';
function __construct($what,$who,$when){
$this->whatIs=$what;
$this->whoIs=$who;
$this->whenIs=$when;
}
public function jsonSerialize()
{
return get_object_vars($this);
}
}
$arr = [];
$arr[] = new Post(1,2,3);
echo json_encode($arr);
Result:
[{"whatIs":1,"whoIs":2,"whenIs":3}]
I think your problem is on this line:
$jsonStr = json_encode($this->$thePost, JSON_PRETTY_PRINT);
You might be trying to do this :
$jsonStr = json_encode($thePost, JSON_PRETTY_PRINT);
Since $thePost is an object, and not a property of your class. It could work if $thePost is a string that match a property name.

PHP if variable contains string or multiple words

I have these two variables
$page_title = '[[+pagetitle]]';
$title_match = 'Marketing Campaign Calendar';
The first is pulling the name of an asset or page and the second are three words I want to search for within those titles. I currently have this if statement which works perfectly as is but I need to add another condition.
if(in_array($content_name, $open_modal_types)) {
// Return view / download buttons
return '<div class="button-group">
<a href="[[~[[+id]]]]"
class="button secondary open-modal"
data-mfp-src="#document-modal"
data-title="[[+pagetitle]]"
data-type="' . $content_name . '"
>View</a>
<a href="[[~[[+id]]]]" class="button secondary" download>Download</a>
</div>';
}
else if($is_binary == '1') {
// Return download button
return '<a href="[[~[[+id]]]]" class="button secondary" download>Download</a>';
}
So I'm trying to accomplish something like this:
if(in_array($content_name, $open_modal_types)) {
// Return view / download buttons
if($page_title contains all of the words in $title_match) {
return "something";
}else{
return '<div class="button-group">
<a href="[[~[[+id]]]]"
class="button secondary open-modal"
data-mfp-src="#document-modal"
data-title="[[+pagetitle]]"
data-type="' . $content_name . '"
>View</a>
<a href="[[~[[+id]]]]" class="button secondary" download>Download</a>
</div>';
}
}
else if($is_binary == '1') {
// Return download button
return '<a href="[[~[[+id]]]]" class="button secondary" download>Download</a>';
}
I've tried using strpos and preg_match but couldn't get it to work. I don't know if I have too many if statements or what. Any suggestions will be helpful.
Thanks
You can use a function like this
<?php
$words = "test1 test2 test3";
function containsAllWords($title, $words) {
$arrWords = explode(" ", $words);
foreach ($arrWords as $word) {
if (strpos($title, $word) === false) {
return false; // one word is not found, so it doesn't contain ALL
}
}
return true; // if we got here, it contains all the words
}
var_dump(containsAllWords("test1 test2 test4", $words)); // false
var_dump(containsAllWords("test1 test2 test3 test4", $words)); // true
may be instead of this
if($page_title contains all of the words in $title_match)
use preg_match:
$title_match = '('.str_replace(' ',')&(', $title_match).')';
if(preg_match('/'.$title_match.'/i', $title_match))
But you should be sure that $title_match not contains special symbols, or filter it by \
So the site I am working on is built in Modx which is fairly new to me. Instead of my original solution I was trying to attempt, I created a new content type within the CMS and wrote my modifications for that content type only. This makes much better sense than what I was trying to do before.
Any other Modx users out there, feel free to reach out to me if you want more details on my solution and what I was trying accomplish.
Thanks to those for trying to help.

In database table there is no rows means getting error Undefined variable: results using codeigniter

In database table there is no rows means getting error Undefined variable: results using codeigniter,in case there is no row or empty table is there means i want to display view page
controller
$data['breview'] = $this->Profile_model->review();
$this->load->view('supplierreview', $data);
Model
public function review() {
$this->db->select('*');
$this->db->from('reviews');
$this->db->join('supplier_otherdetails', 'supplier_otherdetails.supplierid_fk = reviews.supplier_id');
$this->db->join('customer_registration', 'reviews.customer_id=customer_registration.id');
$this->db->join('sub3_category', 'reviews.product_id=sub3_category.id');
$this->db->where('supplierid_fk', $this->session->id);
$query = $this->db->get();
if ($query->num_rows() > 0) {
$results = $query->result();
}
return $results;
}
view page
<?php
foreach ($breview as $row) {
?>
<div class="reviewsection">
<img src="<?php echo 'data:image;base64,' .$row->product_image; ?>" class="img-circle img-user" alt="" width="50px;" height="50px;"/>
<span class="starfont"><botton class="btn btn-danger"> <?php echo $row->ratings; ?> <span class="fa fa-star starfont"></span></botton> </span>
<div class="content-left">
<p><b>Product Name:<?php echo $row->product_name; ?></b></p>
<p><?php echo $row->review_msg; ?></p>
<?php $buyer_review = strtotime($row->review_date);?>
<?php $date=date('d-F-Y',$buyer_review); ?>
<p>Buyer Name : <?php echo $row->first_name; ?> <?php echo $date ; ?></p>
</div>
</div>
<?php } ?>
$results is not defined.
Please add $results = [];
Here you go:
$results = [];
if ($query->num_rows() > 0) {
$results = $query->result();
}
return $results;
In my model, in most cases, i do the following
public function my_function() {
//$qry = YOUR_QUERY
if ($qry->num_rows() > 0) //or ==1 or whatever, depends on your structure
return $qry->result_array(); // or row_array, depends on your structure
return FALSE;
}
Then in your controller you can check if the result is FALSE or EMPTY like:
$result_from_model = $this->my_model->my_function();
if($result_from_model && !empty($result_from_model)) {
//your code here
}
You can use the following code :
return (is_array($results)?$results:array());
Hope it works.
All the answers given so far are good. Here is yet another way to do it. It's essentially the same as the accepted answer only using a ternary instead of if.
$query = $this->db->get();
return $query->num_rows() > 0 ? $query->result() : array();
}

[] operator not supported for strings. It happens JUST in one page [duplicate]

This question already has answers here:
Fatal error: [] operator not supported for strings
(9 answers)
Closed 7 years ago.
I wrote (thanks to Stackoverflow help, too) a PHP script (called wunder_temp.php) which shows the temperature and location for a given number of Weatherunderground.com Stations.
I included this script in my footer, and it works well BUT on a single page.
If I open http://www.flapane.com/guestbook/guestbook.php the temperatures won't be shown in my footer, and error.log says:
[09-Sep-2012 09:46:45 UTC] PHP Fatal error: [] operator not supported for strings in /home/xxx/public_html/wunder_temp.php on line 47
$display = file($cachename, FILE_IGNORE_NEW_LINES); //ignore \n for non-reporting stations
foreach ($display as $key=>$value){
if($key % 2 == 0){
$temperature[] = $value; // EVEN (righe del file cache pari)
}else{
$location[] = $value; // ODD - **HERE IS LINE 47**
}
}
The weird thing is that guestbook.php is the ONLY page of my website where wunder_temp.php doesn't work.
What the above code does is reading the cachefile and put in a $temperature[] array the even lines and in $location[] array the odd lines.
Here's a sample from my cachefile:
26.8
Stadio San Paolo di Napoli, Napoli
24.4
Pozzuoli
Honestly I don't know why I see that errors just on my guestbook page.
It turns out that the "culprit" is the function loadmore.php which loads the guestbook comments (and which is included in guestbook.php) using a twitter-style ajax function. If I don't include it, wunder_temp.php works well, and it doesn't produce any error.
loadmore.php:
<div id='contcomment'>
<div class="timeline" id="updates">
<?php
$sql=mysql_query("select * from gbook_comments ORDER BY id DESC LIMIT 9");
while($row=mysql_fetch_array($sql))
{
$msg_id=$row['id'];
$name=$row['name'];
$url=$row['url'];
$email=$row['email'];
$location=$row['location'];
$date= strtotime($row['dt']); //unix timestamp
$country_code=$row['country_code'];
$message=$row['body'];
$link_open = '';
$link_close = '';
if($url){
// If the person has entered a URL when adding a comment,
// define opening and closing hyperlink tags
$link_open = '<a href="'.$url.'" target="_blank" rel="nofollow">';
$link_close = '</a>';
}
// Needed for the default gravatar image:
$url_grav = 'http://'.dirname($_SERVER['SERVER_NAME'].$_SERVER["REQUEST_URI"]).'/img/default_avatar.gif';
// Show flags
$image = strtolower($country_code) . ".png";
if (file_exists("./img/flags/" . $image)){
$show_image = true;
$image_link = "<img src='/guestbook/img/flags/$image' alt='user flag' />";
}else{
$show_image = false;
}
echo '<div class="comment">
<div class="avatar">
'.$link_open.'
<img src="http://www.gravatar.com/avatar/'.md5($email).'?size=50&default='.urlencode($url_grav).'" alt="gravatar icon" />
'.$link_close.'
</div>
<div class="name">'.$link_open.$name.$link_close.' </div><div class="location"><i>(da/from '.$location.' '.$image_link.' )</i></div>
<div class="date" title="Added at '.date('H:i \o\n d M Y',$date).'">'.date('d M Y',$date).'</div>
<p>'.$message.'</p>
</div>' ;
} ?>
</div>
<div id="more<?php echo $msg_id; ?>" class="morebox">
Carica Commenti più vecchi / Load older entries
</div>
</div>
ajax_more.js AJAX twitter-style load-more-comments function:
$(function() {
//More Button
$('.more').live("click",function()
{
var ID = $(this).attr("id");
if(ID)
{
$("#more"+ID).html('<img src="moreajax.gif" />');
$.ajax({
type: "POST",
url: "ajax_more.php",
data: "lastmsg="+ ID,
cache: false,
success: function(html){
$("div#updates").append(html);
$("#more"+ID).remove();
}
});
}
else
{
$(".morebox").html('Nessun altro commento / No more comments');
}
return false;
});
});
ajax_more.php (needed by the above script):
<?
include "connect.php";
if(isSet($_POST['lastmsg']))
{
$lastmsg=$_POST['lastmsg'];
$lastmsg=mysql_real_escape_string($lastmsg);
$result=mysql_query("select * from gbook_comments where id<'$lastmsg' order by id desc limit 9");
$count=mysql_num_rows($result);
while($row=mysql_fetch_array($result))
{
$msg_id=$row['id'];
$name=$row['name'];
$url=$row['url'];
$email=$row['email'];
$location=$row['location'];
$date= strtotime($row['dt']); //unix timestamp
$country_code=$row['country_code'];
$message=$row['body'];
$link_open = '';
$link_close = '';
if($url){
// If the person has entered a URL when adding a comment,
// define opening and closing hyperlink tags
$link_open = '<a href="'.$url.'" target="_blank" rel="nofollow">';
$link_close = '</a>';
}
// Needed for the default gravatar image:
$url_grav = 'http://'.dirname($_SERVER['SERVER_NAME'].$_SERVER["REQUEST_URI"]).'/img/default_avatar.gif';
// Show flags
$image = strtolower($country_code) . ".png";
if (file_exists("./img/flags/" . $image)){
$show_image = true;
$image_link = "<img src='/guestbook/img/flags/$image' alt='user flag' />";
}else{
$show_image = false;
}
echo '<div class="comment">
<div class="avatar">
'.$link_open.'
<img src="http://www.gravatar.com/avatar/'.md5($email).'?size=50&default='.urlencode($url_grav).'" alt="gravatar icon" />
'.$link_close.'
</div>
<div class="name">'.$link_open.$name.$link_close.' </div><div class="location"><i>(da/from '.$location.' '.$image_link.' )</i></div>
<div class="date" title="Added at '.date('H:i \o\n d M Y',$date).'">'.date('d M Y',$date).'</div>
<p>'.$message.'</p>
</div>' ;
}
?>
<div id="more<?php echo $msg_id; ?>" class="morebox">
Carica Commenti più vecchi / Load older entries
</div>
<?php
}
?>
Any help is appreciated
$location is already a string on that page. This is why you properly initialize variables before you use them:
$temperature = $location = array();
foreach ($display as $key => $value){
if ($key % 2 == 0){
$temperature[] = $value;
} else {
$location[] = $value;
}
}
Even better, separate your variable scopes better so you don't get a name clash like that. Use functions and classes with their private variable scopes and don't put everything in the global scope.
It seems a matter of variable scope.
When you include loadmore.php in guestbook.php you are implicitly declaring $location as a string:
$location=$row['location'];
So this line of your loop:
$location[] = $value; // ODD - **HERE IS LINE 47**
is not implicitly declaring a new array variable on the first iteration but trying to append $value to the previously declared string variable, hence the error.
Try giving a different name to $location either in loadmore.php or guestbook.php or making loadmore.php a function (so it runs in its own scope) and then call it from your guestbook.php script after including its code on it. Or use explicit declaration of $location variable if you want to reuse it as an array (just add $location = array(); before the loop).
I think that loadmore.php and/or ajaxmore.php are setting a global variable ($location) to a string. When the guestbook page tries to index this variable you get the error.
Solution: use functions and local variables.
$location=$row['location']; is the issue. Because PHP doesn't have block level scope, you are essentially pre-setting this variable and trying to set it's array index using []. Because it's a string, that will break.
You should always initialize your variables to avoid these kinds of conflicts:
i.e.
$location = array();
Rename $location for one of the scripts. You have $location=$row['location'] somewhere. Also, declare the variable when using it as an array:
$array = array();
$array[] = 'item'; // when you add an item here, $array will always accept an array push.

(EDITED QUES) PHP - Call function within another function

I have referred to similar questions like this and have done exactly the same way as it should have been but no success. Hence I would appreciate if some one can help me with this
I have a file called view.php which calls a function from a class based on a switch case condition. This function displays the output on the page with few links. When clicked on the link it calls another function which sits in my first function. But obviously when I click my link, nothing happens. That's my code.
view.php
require_once(..'/functions.php');
$functions = new myfile_functions();
<form method="post" action="view.php"><div>
<p><select name="potentialareas" id="potentialareas">
<option style="font-weight:bold;" value="-1">Select an area to view </option>
<?php
foreach($accessareas as $accessarea){
echo "<option value='".$accessarea->id."'>".$accessarea->name. " - " . $accessarea->reporttype. "</option>";
}
?>
</select>
</p>
<p><input name="view" id="view" type="submit" value="View" title="view" /><br /></p>
</div></form>
<div style="border-top:1px dotted #ccc;"></div>
<?php
if(isset($_POST['view']))
{
$hierarchyid = $_POST['potentialareas'];
$reporttype = $DB->get_record_sql("some query");
switch($reporttype->reporttype)
{
case "D Report":
$functions->getDepartmentReport($hierarchyid);
break;
case "S Report":
$functions->getSectionReport($hierarchyid);
break;
case "A Report":
$functions->getAreaReport($hierarchyid);
break;
}
}
functions.php
class myfile_functions(){
function getDepartmentReport($departmentid)
{
global $USER, $CFG, $DB;
$dname = $DB->get_record_sql("some query");
$output = "<div id='actualreport'><p><b>" . $dname->name. " Department Report</b></p>";
$output .= "<p>Activities started: </p>";
$output .= "<p>Activities Completed: </p></div>";
$output .= "<div id='separator' style='border-top:1px dotted #ccc;'></div>";
$output .= "<div id='listofsections'><p><b><i>Select the following for a more detailed report.</i></b></p>";
$snames = $DB->get_records_sql('some query');
foreach($snames as $sname)
{$output .= "<p>" .$sname->name. " <a href='view.php?section=" .$sname->id. "' name='section'><i>view report</i></a></p>";
}
$output .= "</div>";
if(isset($_GET['section']))
{
$this->getSectionReport($_GET['section']);
}
echo $output;
}
function getSectionReport($sectionid)
{
global $USER, $CFG, $DB;
$sname = $DB->get_record_sql("some query");
$output = "<div id='actualreport'><p><b>" . $sname->name. " Report</b></p>";
$output .= "<p>Num Users: </p>";
$output .= "<p>Activities Completed: </p></div>";
$output .= "<div id='separator' style='border-top:1px dotted #ccc;'></div>";
$output .= "<div id='listofareas'><p><b><i>Select the following for a more detailed report.</i></b></p>";
$anames = $DB->get_records_sql('some query');
foreach($anames as $aname)
{$output .= "<p>" .$aname->name. " <a href='view.php?area=" .$aname->id. "' name='view' id='view'><i>view report</i></a></p>";
}
$output .= "</div>";
if(isset($_GET['area']))
{
$areaid = $_GET['area'];
$this->getAreaReport($areaid);
}
echo $output;
}
Similarly another function calling the above function, n so on.
function getAreaReport($id)
{ .. same content but calling another function...}
So when ever I click my view report link, I get the id appended id in my querystring, something like
http://mydomain.com/view.php?section=5
Ideally the contents of getSectionReport() should get printed but its not. Please point out what is it that I am doing wrong.
Thanks in advance.
What's your main method for displaying everything? At the moment you have three functions, all of which link to eachother in various ways, but it doesn't look as if you're instantiating anything first. The PHP is being fed a parameter in your URL, sure, but if a class isn't instantiated and a method declared, how does it know what you want it to do?
For myfile.php, maybe you should do something like:
class MyFile
{
public function other_function()
{
// Various stuff
return 'stuff';
}
public function other_other_function()
{
// Various other stuff
return 'other stuff';
}
public function page_view($file_id)
{
$var = $this->other_function($file_id);
return $this->other_other_function($var);
}
}
$class = new MyFile;
echo $class->page_view($_GET['id']);
If the two functions are part of a class (as your comment above hints), then the call should be written as
$this->getUserReport($id);
If you're accessing a sibling function inside the same class, use:
class ClassName
{
public function sibling_function()
{
return 'Hey bro!';
}
public function my_function()
{
return $this->sibling_function();
}
}
If not, use the standard:
public function my_function()
{
return sibling_function();
}
If you're still having trouble, make sure your class is properly instantiated. There's no point calling another function if you're not even instantiating the class first:
$obj = new ClassName;
echo $obj->my_function();

Categories