Best way to check if Joomla! 3.4.0 article already exists - php

I am creating articles in Joomla! programmatically using JTable.
Since I have a lot of articles that need to get synchronized periodically, I need to check each article if it already exists before inserting it (otherwise it produces errors).
What is the best way to do so?
My idea was to retrieve all articles from database and compare unique fields. But problems (blank page) occured while retreiving the articles. Here is the code:
function getExistingArticles(){
// Create a new query object.
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->select('*')->where('`a.created_by_alias`= `article_synchronizer`'); // Prepare query.
$query->from('`#___categories` AS a');
// Reset the query using newly populated query object.
$db->setQuery($query);
$articles = $db->loadObjectList(); // Execute query, return result list.
return $articles;
}
If this is the "best" way in Joomla! to check if a certain article already exists, where is the problem in this code, that results in a blank page?
Otherwise which is the best way to check if a Joomla! article with a certain content already exists?

I haven't tested your query, but I would suggest quoting column names and values using Joomla's API like so:
function getExistingArticles()
{
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->select($db->quoteName(array('a.*')))
->from($db->quoteName('#__categories', 'a'))
->where($db->quoteName('a.created_by_alias') . ' = ' . $db->quote('article_synchronizer')); // Quoted query.
$db->setQuery($query);
$articles = $db->loadObjectList();
return $articles;
}
I've fixed your query a little. You were using 3 underscores when defining the table prefix (only 2 should be used). The where and from clauses were also the wrong way round.

Related

update current database table

I'm making a WordPress plugin and I need to update tables for the current database in a query. However, instead of writing the database name into the sql, I need some way to select it in the query so that way it will work no matter what your database's name is. This is the code I currently have:
$stmt = $conn->prepare("UPDATE `wp_plugin_development` . `wp_users` SET `user_pass` = ? WHERE `user_login` = ?") or trigger_error($mysqli->error);
$stmt->bind_param('ss', $user_password[$i], $user_login[$i]);
wp_plugin_development is my current database name, but needs to be replaced with some other way of selecting the database name. I wish I could write something like UPDATE SELECT DATABASE() but that obviously doesn't work. Maybe there's an entirely different way to code this? I still consider myself new to all this, so I'm sorry if I'm missing something obvious. Any help is greatly appreciated.
You don't need the current database name, because the connection is already established with the current database.
You need the tablename! The prefix is set when setting up wordpress. You need the prefix, because every installation is different.
The proper Wordpress way is like this:
global $wpdb;
$table_name = $wpdb->prefix . 'plugin_development';
The prefix is stored (wp_). In WP; you don't use PDO or MySqli directly, you work with the global $wpdb object.
$wpdb->update($table_name, $data, $where, $format = null, $where_format = null);
If you really need the database name, it's stored in $wpdb->dbname;.
Here are examples and the class reference:
https://codex.wordpress.org/Class_Reference/wpdb
I was using another database as the connection method (this was defined in the $conn variable). So I made a new connection to the current database using $wpdb and named it $this_db. Now I don't have to specify the database name in the query and it works like I want it to. For better context, here's the code I added/changed:
$thisServername = $wpdb->dbhost;
$thisUsername = $wpdb->dbuser;
$thisPassword = $wpdb->dbpassword;
$thisDBname = $wpdb->dbname;
$this_db = new mysqli($thisServername, $thisUsername, $thisPassword, $thisDBname);
$stmt = $this_db->prepare("UPDATE `wp_users` SET `user_pass` = ? WHERE `user_login` = ?") or trigger_error($mysqli->error);
$stmt->bind_param('ss', $user_password[$i], $user_login[$i]);
So, for solving this specific issue, this solution works. Sorry I forgot to mention using the external database. That was an important thing I left out of the question. And thank you everyone for your input.
The function database() returns the DB name - http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_database -
so you can run SELECT DATABASE(); first to get the DB name.

Add a count of related data to each item in a joomla MVC list view

I have a custom joomla MVC component.
The component has a table of items,
and a table of bids to deliver each item. An item can have multiple bids.
i need to show a COUNT of the bids on the items LIST view within each row of the foreach.
What is the BEST way of achieving this? I have tried adding the following to the items model but I am stumped at how to define $id for each item row.
public function getBidsByItemId() {
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->select('COUNT(*)');
$query->from($db->quoteName('#__table_bids'));
$query->where($db->quoteName('item_id')." = ".$id);
// Reset the query using our newly populated query object.
$db->setQuery($query);
$count = $db->loadResult();
}
Here you can see the full component/models/items.php to which I added it: http://ideone.com/yPJHRk
Grateful for help from the MVC experts out there.
The best way would probably be a JOIN. Try adding in line 83 something like the following (you'll have to adapt it to your db table structure):
// Join over the fields by field 'item_id'
$query->select('itemBids.bids AS bidsNum');
$query->join('LEFT', '#__entrusters_bids AS itemBids ON itemBids.item_id = a.item_id');
Then you'll be able to fetch the value from the object. I can't test it to be more specific to your problem so tell me if it works.
you should definently make a join, but from what I understand what you want is the bid-count? In that case you should make a group-by query, similar to what ilias is saying, but:
$query->select('count(itemBids.bids) AS bidsNum');
$query->join('LEFT', '#__entrusters_bids AS itemBids ON itemBids.item_id = a.id');
$query->group('a.id');
also notice to the reference change in the on-statement in the join,
regards Jonas

Silverstripe - Better way to delete Dataobjects instead of using custom sql querys

Is there a better way deleting dataobject older than x-days instead of using custom sql queries?
that's what I do now
$host = 'localhost';
$username = 'db123';
$password = 'pass';
$db_name = 'db123';
mysql_connect("$host", "$username", "$password")or die("cannot connect");
mysql_select_db("$db_name")or die("cannot select DB");
$sql = "DELETE FROM Cart WHERE Created < (CURDATE() - INTERVAL 1 DAY)";
$result = mysql_query($sql);
mysql_close();
first of all, using mysql_query is bad, not just in this case.
mysql_query has been deprecated and should no longer be used.
secondly, SilverStripe already has a DB connect, do not attempt to create another one.
SilverStripe offers many ways to query the database.
Option 1:
the cleanest way of course is to use the SilverStripe ORM.
A DataObject has a method called ->delete().
Using delete has several advantages over writing your own SQL query.
its easy
it will delete the DataObject from all its tables for you (eg the DataObject class Folder is a subclass of File, so if you do $myFolder->delete() it will go and delete this Folder in the File Table but also in the Folder Table (if there is a Folder table))
it will execute the SilverStripe delete hooks (onBeforeDelete and onAfterDelete)
its pretty straight forward:
// to delete all `DataObject`s in a List, just loop it and call ->delete()
foreach($list as $item) {
$item->delete();
}
// there also is a method that does that for you, however, I would advise against it
// because it is currently inconsistently implemented and might lead to unexpected results
// $list->removeAll(); // i STRONGLY RECOMMEND AGAINST THIS
// if $list is a DataList, it will delete all records
// if $list is a ManyManyList, it will unlink all records
// if $list is a ArrayList, it will error because there is no removeAll() method on ArrayList
to solve your problem:
$date = date('Y-m-d H:i:s', strtotime("now -1 day"));
$list = Cart::get()->filter('Created:LessThan', $date);
foreach($list as $item) {
$item->delete();
}
it however has also a major disadvantage when deleting many DataObjects: performance.
I will however still recommend using ->delete() if you can say that performance is not a huge problem. The benefits usually outweigh the drawbacks.
Read more about DataList, ::get(), ->filter() and ->delete() in the SilverStripe docs for Datamodel / ORM and DataObject
Option 2:
if you however really need to, it is possible to use a lower level of the ORM to perform the delete:
$query = new SQLQuery();
$query->setDelete(true);
$query->setFrom('Cart');
$query->setWhere('Created < (CURDATE() - INTERVAL 1 DAY)"');
// if you want to debug the query, you can use ->sql() to get it as string
// echo $query->sql();
$query->execute();
Read more about SQLQuery in the SilverStripe docs
Option 3:
if you for some reason really want to avoid the ORM at all, SilverStripe also lets you execute raw SQL queries:
DB::query("DELETE FROM Cart WHERE Created < (CURDATE() - INTERVAL 1 DAY)");

Symfony2 - Show all tables from database

I would like to retrieve all the tables of my database as a list.
i tried to do a "Show databases" on a query but as i'm not using a class I defined (entity) in symfony it's not working.
And with DQL :
$em = $this->getDoctrine()->getEntityManager();
$query = $em->createQuery(
'show databases');
$result = $query->getResult();
This error :
[Syntax Error] line 0, col 0: Error: Expected SELECT, UPDATE or DELETE, got 'show'
Any idea to help me ?
As mentioned in a different answer, you can use Doctrine\DBAL for that:
/** #type \Doctrine\DBAL\Connection $connection */
$connection = ...;
/** #type \Doctrine\DBAL\Schema\MySqlSchemaManager $sm */
$sm = $connection->getSchemaManager();
And then just list the tables as Array:
var_dump( $sm->listDatabases() );
My 2 cents:
getContainer()->get('doctrine.dbal.default_connection')->getSchemaManager()->listTableNames()
This will give you an array of table names.
i have a couple cases where I need to use complex sql statements/functions that I just couldn't do in DQL. Luckily, Symfony2/doctrine provide a method to grab the current database connection and bypass doctrine entirely.
//get connection
$conn = $this->get('database_connection');
//run a query
$users= $conn->fetchAll('select * from users');
Be very careful when using this method, however. Since you are bypassing doctrine, you need to handle any security concerns like SQL injection yourself.
You can add Doctrine DBAL to your project and it will give you the tools you need. You can list databases, tables from a database, columns from a table etc etc
More in Doctrine DBAL documentation: http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/schema-manager.html
Doctrine is a ORM, it is not intended to list all the databases. Beside that, usually for the current user you don't have the right to show all databases in the server, this can prove to be a big security breach.
Basicly, doctrine does not know how to interpret your query, you have to use a native query for this: Doctrine Native Query

SELECT query to mysql and return object

I'm new to PHP. I've created classes that represent my database tables (I come from a .Net entity framework background). I would like to run my SELECT statement and pass back a User object. All the examples I've found parse the returned data. Is there a way to just do something like this and have it pass back a User object:
$user = new user();
$user = $mysqli->query($query, MYSQLI_STORE_RESULT);
return $user;
or do I have to parse the result first?
Note: all the fields in the user class match the fields in the database
I.E. $user->UserName = [user].[UserName]
Try use PDO with "fetchobject":
$statement = $db->query($query);
$user = $statement->fetchObject('User');
http://www.php.net/manual/en/pdostatement.fetchobject.php
or convert (cast) each "row" of data to User Object (example function)
or try a ORM PHP solution

Categories