<?php
class ann {
public function __construct($context, $orgs_id, $created_at) {
$this->context = $context;
$this->orgs_id = $orgs_id;
$this->created_at = $created_at;
}
function create(){
$createann = mysql_query("INSERT INTO anns(context,
orgs_id, created_at)
VALUES('$this->context',
$this->orgs_id, '$this->created_at'");
if($createann) echo "Duyuru Başarıyla Eklendi"; else echo "Duyuru
Eklenemedi";
}
function read($id){
$readann = mysql_query("SELECT * FROM anns WHERE id = $id");
$context = mysql_result($readann,0, "context");
$orgs_id = mysql_result($readann,0, "orgs_id");
$created_at = mysql_result($readann,0,
"created_at");
$ann = new ann($context, $orgs_id, $created_at);
return $ann;
}
function update($id, $context){
$updateann = mysql_query("UPDATE anns SET context =
'$context' WHERE id = $id");
if($updateann) echo "Update success"; else echo
"Update failed";
}
function delete($id){
$deleteann = mysql_query("DELETE FROM anns WHERE id
= $id");
if($deleteann) echo "Delete success"; else echo "Delete not success";
}
//crud fonksiyonlari burda bitiyor
}
?>
There is something wrong with our logic here but we are very new to php. We tried to create rails like models, but it think something with our class-object notation is wrong. So the code did not work. We cannot even create any object with it.
Thank you guys
context, orgs_id and created_at must be should be first declared either as public, private or protected before you use them.
In your create method, you don't filter user input. This may cause to your application SQL injection, you have to you always filter user input. Use either mysql_real_escape_string or prepared statment by PDO.
You may check this tutorial.
two things (which maybe only apply to your codesample here):
In your sample, you dont close your
Class, because the last "}" is
commented out.
You never opened a connection to your database, so the query would fail.
a few observations:
declaring the attributes in the constructor is possible, but it's not elegant. I'd rather do:
class ann {
private $context;
private $orgs_id;
the "->" operator won't work inside a string. You'll need to concatenate the query:
"INSERT INTO anns(context,orgs_id, created_at) VALUES('".$this->context."',".$this->orgs_id".", '".$this->created_at."'"
but be careful on sql injection
The rest should be fine! Good Luck.
Related
first question here, because i'm stuck since this morning and i don't find a single way to fix my problem.
I'm trying to show every images listed in my DB (DB contains img name, img are stored in local files, each has been send in the same time via an input page).
The current code do not send any errors between thoses parts :
public function findall()
{
require_once ('Classes/ClasseDB.php');
$pdo = Database::connect();
$req = "SELECT IDphoto, nomImage, testCom FROM test";
$stmt = $pdo->query($req);
$CollectionPhotos = array();
while ($ligne = $stmt->fetch())
{
$LaPhoto = new ClasseTest($ligne["testCom"]);
array_push($CollectionPhotos, $LaPhoto);
}
return $CollectionPhotos;
}
public function get_nomImage()
{
return $this->nomImage;
}
And
Image List :
<?php
echo "test1 ";
require_once "Classes/ClasseTest.php";
$laPhoto = new ClasseTest;
$CollectionPhotos = $laPhoto -> findall();
$i = 0;
echo "test2 ";
while ($i < count($CollectionPhotos)){
// here is where it's broken ↓
echo $CollectionPhotos[$i]->get_nomImage(); //don't work :'(
//html <img __ > is removed in order to simplify
echo 'test3 '; //shows every items
$i++;
}
echo "test4 ";
?>
ClasseDB code here as asked :
<?php
class Database {
public static $conn = null;
public static function connect() {
if ( null == self::$conn ) {
try {
self::$conn = new PDO('mysql:host=localhost;dbname=myDB', 'root', '');
self::$conn->query("SET NAMES 'utf8'");
self::$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $e) {
die($e->getMessage());
}
}
return self::$conn;
}
}
?>
Each tests are shown, and 'test3' appears 10 times, so i know my loop repeats enough times.
Nb : this is like what we did in class...
So what is wronnnng, is that a newbie mistake, a misspelling or a bug (my pc has done everything to me so that's also possible) ?
In your SQL query, you select three columns:
SELECT IDphoto, nomImage, testCom FROM test
However, only one of these is actually referenced in your PHP code:
$LaPhoto = new ClasseTest($ligne["testCom"]);
You haven't shown the constructor of ClasseTest, so it's not clear where testCom is stored (if anywhere), but from its name, I suspect it is not in the nomImage property, which is what you later try to retrieve:
public function get_nomImage()
{
return $this->nomImage;
}
That property is presumably supposed to come from the nomImage column in the database, which you're not storing anywhere.
You can help yourself a lot by naming things more carefully and thinking about responsibilities. If you want an object representing a photo, the logical name for it would be Photo, and you would pass all the columns you've selected to its constructor:
$LaPhoto = new Photo($ligne["IDphoto"], $ligne["nomImage"], $ligne["testCom"]);
Your findAll method doesn't belong to a single photo, so you can either put it on a different class, like ChercheurPhoto:
$leChercheurPhoto = new ChercheurPhoto;
$CollectionPhotos = $leChercheurPhoto->findall();
Or, you can use a static method, which is a method on the class, not a particular instance of the class:
$CollectionPhotos = Photo::findall();
I'm having issues running this code here:
<?php
include_once "global.php";
class Project{
//Variable declarations
public $name;
public $pm;
public $members;
public $details;
//Not sure if dates are necessary yet
//$startDate = $inStartDate;
//$endDate = $inEndDate;
//Define the constructor
function __construct($inName, $inPm, $inMembers, $inDetails){
$this->name = $inName;
$this->pm = $inPm;
$this->members = $inMembers;
$this->details = $inDetails;
//Not sure if dates are necessary yet
//$startDate = $inStartDate;
//$endDate = $inEndDate;
}
//Function to create the Project within the database
public function createProject(){
echo "starting";
//Initiate database connection, checking for errors
$con = dbConnect();
if ($con->connect_errno){
echo "Connect failed: %s\n". $mysqli->connect_error;
exit();
}
//Insert the project into the projects database using the information used to instantiate
if ($stmt = $con->prepare("INSERT INTO projects (name, details) VALUES (?,?)")){
echo "Not getting here.";
$stmt->bind_param('ss', $this->name, $this->details);
$stmt->execute();
if (strlen($stmt->error) > 0){
return "Error creating project. Contact system administrator.";
}
elseif(count($members) == 0) {
//ensure there are members to enter
$last_insert = mysqli_insert_id($con);
$con->query('INSERT INTO project_member (pid,uid,rid) VALUES ('.$last_insert.','.$this->pm.',1');
exit();
}
else{
//get last inserted ID
$last_insert = mysqli_insert_id($con);
echo $last_insert;
//loop through members and create sql array
$sql = array();
foreach ($members as $user){
$sql[]='("'.$last_insert.','.$user.',0")';
}
//Add members to join table with roles
$con->query('INSERT INTO project_member (pid,uid,rid) VALUES '.implode(',', $sql));
$con->query('INSERT INTO project_member (pid,uid,rid) VALUES ('.$last_insert.','.$this->pm.',1');
return true;
}
$stmt->close();
}
}
}
It will get to the mysqli code loop, but not initiate it. Trying to echo from it results in nothing being submitted, and the PHP error logs don't note anything going on. I don't see anything strange on the MySQL logs as well.
The $members variable is going to be an array composed of integers, which is why it loops at the bottom through the array.
I am not getting any connection errors, and echoing after trying to capture errors results in success.
dbConnect() is from the global.php file above, and returns a mysqli connection. This is the inside of the connection:
function dbConnect(){
$con = mysqli_connect($_HOST, $_DBUNAME, $_DBPASS,$_DBTABLE);
if ($con->connect_errno){
printf("Connect failed: %s\n", $mysqli->connect_error);
return false;
}
return $con;
}
I have used that elsewhere on my site, and in much of the same situation. Not sure what I am doing wrong here, but any advice would be greatly appreciated.
Edit: I did try again with all of the above suggestions, and still getting the weird issue with it not wanting to go past the if loop.
Edit2: Never mind, I am a moron.
Issue was that the 'details' row in my database didn't exist. Instead, in my infinite wisdom, I called it description and didn't update the code. Changing it fixed the issue.
Again, thank you all for a great first post on StackOverflow. I am going to be back, but I will get better!
This loop:
foreach ($members as $user){
$sql='("'.$last_insert.','.$user.',0")';
}
should be:
foreach ($members as $user){
$sql[]='("'.$last_insert.','.$user.',0")';
}
You're just overwriting the variable with a string, not appending to the array.
I'm surprise implode(',', $sql) on the next line isn't reporting an error.
You initialize $sql as an array, but then assign a string to it; you need to add items to an array differently:
$sql = array();
foreach ($members as $user){
$sql[] ='("'.$last_insert.','.$user.',0")';
}
Note the square brackets - that adds an extra item to the $sql array.
I'd also look at the two queries you're running at the end:
$con->query('INSERT INTO project_member (pid,uid,rid) VALUES '.implode(',', $sql));
$con->query('INSERT INTO project_member (pid,uid,rid) VALUES ('.$last_insert.','.$pm.',1');
You're adding two sets of values to the same table - $pm is never defined. You've got $pm as a class variable, but you don't set it as such. The syntax for that would be:
function __construct($inName, $inPm, $inMembers, $inDetails){
$this->name = $inName;
$this->pm = $inPm;
$this->members = $inMembers;
$this->details = $inDetails;
That means that the rest of the class functions can access those variables as $this->name, and so on.
The problem starts at your Project constructor:
The way you're initializing $name, $pm, $members, $details is keeping them local to the constructor. You want to initialize these variables using $this.
//Define the constructor
function __construct($inName, $inPm, $inMembers, $inDetails){
$this->name = $inName;
$this->pm = $inPm;
$this->members = $inMembers;
$this->details = $inDetails;
}
You can then safely get rid of all the global variables defined within functions, some of them including:
global $name;
global $details;
global $members;
Finally you need to access the member variables name, pm, members, details and any others using:
$this->name, $this->pm, and so on
Lastly as other answerers have already pointed out on the SQL string generation.
$sql = array();
foreach ($members as $user){
$sql[] = '("'.$last_insert.','.$user.',0")';
}
I have a problem with my PHP class, when the user wants to follow another user the follow method is called and when the user wants to stop following the delete_follow is called:
class Follow {
protected static $table_name = "interests";
public function follow() {
global $dbh;
$sql = "INSERT INTO ".self::$table_name." (company_id,user_id,likedate) VALUES (:company_id,:user_id,NOW())";
$follow = $dbh->prepare($sql);
$follow->bindParam(':user_id',$_SESSION['user_id']);
$follow->bindParam(':company_id',$_GET['company']);
if($follow->execute() == true){
header("Location: profile.php?company=".$_GET['company']."");
exit;
} else {
header("Location: error.php");
exit;
}
}
public function delete_follow() {
global $dbh;
$sql = "DELETE FROM ".self::$table_name." WHERE company_id = :company_id AND user_id = :user_id LIMIT 1";
$delete_follow = $dbh->prepare($sql);
$delete_follow->bindParam(':user_id',$_SESSION['user_id']);
$delete_follow->bindParam(':company_id',$_GET['company']);
if($delete_follow->execute() == true) {
header("Location: profile.php?company=".$_GET['company']."");
exit;
} else {
header("Location: error.php");
exit;
}
}
}
My problem is that when the delete_follow method is called it actually calls the follow method I have no idea what is going on.
Here is the code for the follow buttons:
if(isset($_POST['follow'])) {
$follows = new Follow();
$follows->follow();
}
if(isset($_POST['delete_follow'])) {
$follows = new Follow();
$follows->delete_follow();
}
Help please.
The name of your class is Follow. The first method in your class is called follow(). PHP is case insensitive in this aspect and treats that follow() method as the constructor. So this statement--$follows = new Follow()--actually calls the follow() method from your class. Therein could lie your problem.
Read more about PHP constructors here.
I would imagine that there is an error in your form. Perhaps it would be better to have one field follow with a boolean value, say yes or no.
I am try to make an PDO sql inside function but it doesn't work. got no response from it. it works when not using function. my purpose is to make my code small. anyone can shed a light. thanks.
function Test() {
$get_name = $smt->prepare("SELECT * FROM customer WHERE id = '1'");
$get_name->execute();
foreach ($get_name as $temp) {
$name = $temp['name'];
$address = $temp['address'];
$phone = $temp['phone'];
$page = $temp['page'];
}
eval("\$page = \"$page\";");
echo $page;
eval("\$page = \"$page\";");
echo $page;
}
Test();
I'd probably refactor your code to something like:
function getCustomerInfo(PDO $pdo, $customerId)
{
// use a prepared statement that can get you info on any customer
$statement = $pdo->prepare(
"SELECT * FROM customer WHERE id = :customerId LIMIT 1");
// get the result resource from the database
$result = $statement->execute(array(
':customerId' => $customerId
));
// fetch the first row in the result as an associative array
// and return it to the caller.
return $result->fetchFirst(PDO::FETCH_ASSOC);
}
// use your connection in place of $pdo
$customerData = getCustomerInfo($pdo, 1);
// now you can do stuff with your data
var_dump($customerData);
This is better because it does not rely on global state, functions should never-ever-ever do that. and it uses prepared, parameterized sql that makes it faster and the function more useful for customers other that the one where id=1.
You need to make the pdo instance global within the function
function Test() {
global $smt;
PHP/MySQLisolating database access in class - how to handle multiple row Selects
Here’s a coding question.
I isolated all DB access functions in a class
<?php
class DB {
var $conn;
function DBClass () {
#$this-> conn = mysqli_connect (DB_SERVER, DB_USER, DB_PASS, DB_NAME);
}
function validateUser ($aUserid, $aPassword) {
… validation code – sql injection code etc..
$sql = "Select userid, name, level From users where userid = '$aUserid' and password = '$aPassword'";
$result = mysqli_query ( $this->conn, $sql );
if (!$result || (mysqli_num_rows ($result) < 1)) {
return false;
}
$dbarray = mysqli_fetch_assoc ($result); // get a row
return $dbarray;
}
function getProduct ($aProductid) {
return $dbarray;
}
function getProductList () {
// <----------- this would be the problem function
}
}
$DB = new DBClass();
?>
My calling routine:
<?php
$dbarray = $DB->validateUser ($_POST['userid'], $_POST['password']);
?>
No problem it works fine. I run into a problem with a result set of more than one row. Now I have to get back to the class object for each row. It’s no problem if I include the MySQL code in the calling routine, but I’d like to keep it isolated in my class and I’m not sure how to code it.
Any thoughts? Any examples?
If you use PHP 5.3.0 and mysqlnd, you can use the new function mysqli_fetch_all(). This returns an array of associative arrays.
If you use an earlier version of PHP, you could switch to using PDO, and use the function PDOStatement::fetchAll().
You ask in a comment what about a very large result set. It's true that an unbounded result set could cause the array to exceed your PHP memory limit and that would cause a fatal error and halt the script. But is this really a problem? How many products do you have? You could use LIMIT to make sure the query isn't unbounded.
Re the other part of your questions regarding going back to a class, I'd suggest making an Iterator class:
class DB implements IteratorAggregate
{
protected $_data = array();
public function getProductList() {
// fetch all results from SQL query, stuff them into $this->_data
return $this->getIterator();
}
public function getIterator() {
return new ArrayIterator($this->_data);
}
}
Now you can use the class in a foreach loop:
$db = new DB();
foreach ($db->getProductList() as $product) {
// do something with each product
}
The IteratorAggregate interface means you can even do this:
$db = new DB();
$db->getProductList();
// ...other steps...
foreach ($db as $product) {
// do something with each product
}
Of course you could only store one result set at a time with this method. If you used your DB class for any other queries in the meantime, it would complicate things. For this reason, most people don't try to write a single class to encapsulate all database operations. They write individual classes for each type of Domain Model they need to work with, decoupled from the database connection.
you could save the result in an array and return it:
function getProductList () {
$sql = "SELECT ...";
$result = mysqli_query ( $this->conn, $sql );
$myProducts = array();
while ($row = mysqli_fetch_assoc($result))
$myProducts[] = $row; // or array_push($myProducts, $row)
}
return $myProducts
}
As a result you'll have an array of arrays and each element of it will contain one row of the result.
You have a SQL injection right in your login page.
What happens if someone inputs that as password:
xxx' OR 'yyy' <> 'x