I've followed FOSComment's instruction to have multiple threads in one page. It's ok everything works. Just kidding, the world isn't that beautiful.
I'll try to explain my problem : When I submit my comment, i've got Integrity constraint violation due to the URL, I don't pass any Thread_id in my URL.
I found the piece of code in my controller which does that, but I've got no idea how to correct it. So, there's my controller :
public function indexAction(Request $request)
{
$stmt = $this->getDoctrine()->getEntityManager()
->getConnection()
->prepare('select ttrss_entries.id, title, content, body, thread_id '
. 'FROM ttrss_entries '
. 'LEFT JOIN ttrss_tags ON ttrss_entries.id = ttrss_tags.post_int_id '
. 'LEFT JOIN comment on comment.thread_id = ttrss_entries.id '
. 'WHERE ttrss_tags.tag_name = "politique" '
. 'GROUP BY ttrss_entries.id');
$stmt->execute();
$result = $stmt->fetchAll();
//Here my problem
$id = 'thread_id';
$thread = $this->container->get('fos_comment.manager.thread')->findThreadById($id);
if (null === $thread) {
$thread = $this->container->get('fos_comment.manager.thread')->createThread();
$thread->setId($id);
$thread->setPermalink($request->getUri());
$this->container->get('fos_comment.manager.thread')->saveThread($thread);
}
$comments = $this->container->get('fos_comment.manager.comment')->findCommentTreeByThread($thread);
return $this->render('AppBundle:Politique:index.html.twig', array(
'comments' => $comments,
'thread' => $thread,
'entities' => $result,
));
}
Here my view :
<div class="fos_comment_thread" data-thread-id="{{ thread.id }}">
{% include 'FOSCommentBundle:Thread:comments.html.twig' with {
'comments': comments,
'thread': thread
} %}
Thanks in advance for your help
PS : I'm a newbie with Symfony.
Related
Hi first of all I should tell you that English is not my first language so excuse any misunderstandings. What I'm trying here is to access to the "donors" table data using the foreign key in the "packets" table and I need to get that data in the controller to use. I refer PacketID in my view and in the staff controller I need to get the specific DonorMobile and DonorName to send an SMS to that donor. I have tried creating multiple model functions but didn't work. Can it be done by that way or is there any other way? TIA!
Screenshots of donors and packets tables
donors table and
packets table
Staff controller - I know you can't access data like $donorData->DonorID in the controller
public function markAsUsed($packet)
{
$this->load->Model('Donor_Model');
$donorData = $this->Donor_Model->getDonors($packet);
$this->load->Model('Donor_Model');
$data = $this->Donor_Model->markAsUsed($donorData->DonorID);
$sid = 'twilio sid';
$token = 'twilio token';
$donorMobile = '+94' . $donorData->DonorMobile;
$twilioNumber = 'twilio number';
$client = new Twilio\Rest\Client($sid, $token);
$message = $client->messages->create(
$donorMobile, array(
'from' => $twilioNumber,
'body' => 'Thank you ' . $donorData->DonorName . ' for your blood donation. Your donation has just saved a life.'
)
);
if ($message->sid) {
$this->load->Model('Donor_Model');
$this->Donor_Model->changeStatus($data->isAvailable);
redirect('staff/viewpackets');
}
}
Model
function getDonors($packet) {
$data = $this->db->get_where('packets', array('PacketID' => $packet));
return $data->row();
}
function markAsUsed($donor)
{
$data = $this->db->get_where('donors', array('DonorID' => $donor));
return $data->row();
}
function changeStatus($packet)
{
$data = array(
'isAvailable' => False,
);
return $this->db->update('packets', $data, ['PacketID' => $packet]);
}
What you did in the answer is not advisable, using loops to fetch from tables will slow the system by large when you have large datasets. What was expected is to use JOIN queries to join the donors and packets tables as shown below:
$this->db->select('donors_table.DonorName,donors_table.DonorMobile,packets_table.*')->from('packets_table');
$this->db->join('donors_table','donors_table.DonorID=packets_table.DonorID');
$query = $this->db->get();
$result = $this->db->result();
Then you can iterate through each donor as below:
foreach($result as $row){
$donarName = $row->DonorName;
$donorMobile = $row->DonorMobile;
}
NB: It is always advisable to perform any fetch, insert, delete or update operations from the model, that is why Codeigniter is an MVC. Stop fetching data directly from database within Controllers.
Found the answer! You can do this only using the controller.
$packetData = $this->db->get_where('packets', array('PacketID' => $packet));
foreach ($packetData->result() as $row) {
$donorID = $row->DonorID;
$packetDonatedDate = $row->DonatedDate;
}
$donorData = $this->db->get_where('donors', array('DonorID' => $donorID));
foreach ($donorData->result() as $row) {
$donarName = $row->DonorName;
$donorMobile = $row->DonorMobile;
}
I have a class Pagination with a method that counts the total number of articles. When I instantiate the class, I explicitly type the sql query and give him the parameters. Here is an example:
$pagination = new Pagination(self::DATABASE_FORUM_TOPICS, $this->currentPage, self::TOPICS_IN_CATEGORY, [
'query' => 'SELECT COUNT(*) as count FROM ' . self::DATABASE_FORUM_TOPICS . ' WHERE title LIKE ?',
'params' => "%$keyWord%"
]);
The method that handles the query runs it and returns the result:
return $this->db->getRows($this->query['query'], [$this->query['params']]);
Everything works perfect, however, for this particular case (for searching articles) I want not only to count the results that match title but also by content, in other words I want to change to:
'SELECT COUNT(*) as count FROM ' . self::DATABASE_FORUM_TOPICS . ' WHERE title LIKE ? OR content LIKE ?'
But how do I pass the second parameter in 'params' => "%$keyWord%" ?
Edit:
Pagination class.
public function __construct(string $table, $currentPage = 1, $perPage, $query = [])
{
$this->db = Database::getInstance();
$this->currentPage = $currentPage;
$this->perPage = $perPage;
$this->table = $table;
$this->query = $query;
$getTotalRows = $this->countResultsFromTable();
$getTotalRows = $getTotalRows[0]->count;
$this->total = ceil($getTotalRows / $this->perPage);
}
public function countResultsFromTable()
{
if(empty($this->query))
{
return $this->db->getRows("SELECT COUNT(*) as count FROM $this->table");
}
else
{
return $this->db->getRows($this->query['query'], [$this->query['params']]);
}
}
Try the following: extend your call to
$pagination = new Pagination(self::DATABASE_FORUM_TOPICS, $this->currentPage, self::TOPICS_IN_CATEGORY, [
'query' => 'SELECT COUNT(*) as count FROM ' . self::DATABASE_FORUM_TOPICS . ' WHERE title LIKE ? AND content LIKE ?',
'title' => "%$keyWord%",
'content' => $CONTENT
]);
and the query evaluation to
return $this->db->getRows($this->query['query'],
[$this->query['title'], $this->query['content']]
);
If you don't want to change the Pagination class, append the content to the query before instantiating the Pagination:
$pagination = new Pagination(self::DATABASE_FORUM_TOPICS, $this->currentPage, self::TOPICS_IN_CATEGORY, [
'query' => 'SELECT COUNT(*) as count FROM ' . self::DATABASE_FORUM_TOPICS . ' WHERE title LIKE ? AND content LIKE "%' . your_escaping_function($content) . '%"',
'title' => "%$keyWord%"
]);
I have a script like this :
<?
public function read($slug, $read_more) {
$artikel = App\Post::where('read_more', $read_more)->first();
$comments = App\Comment::where('post_id', $artikel->id)->where('active', '1')->get();
$pops = App\Post::orderBy('count', 'desc')->limit(5)->get();
$coms = App\Comment::orderBy('active', 'desc')->orderBy('created_at', 'desc')->limit(5)->get();
$categorys = App\Category::all();
$title = 'Artikel ' . $artikel->category->category . ' ยป ' . $artikel->title;
$description = str_limit($artikel->content, 70);
$keywords = $artikel->category->category . ', teknologi, komputer, artikel, pemrograman, informasi, terbaru, linux';
$view = view('guest.read', compact('artikel', 'comments', 'categorys', 'title', 'description', 'keywords', 'pops', 'coms'));
if (Cookie::get('__urda') == $artikel->id) {
return $view;
} else {
$count = App\Post::find($artikel->id);
$count->count = $artikel->count + 1;
$count->save();
$cookie = new Response($view);
$cookie->withCookie(cookie()->forever('__urda', $artikel->id));
return $cookie;
}
}
?>
Problem while reading the article.
If you read article A, the number of readers increases.
If you read article B, the number of readers increases.
If you reread article A, the number of readers will increase again. (Should not increase)
example : http://www.jinggacloud.com
What is the solution
You can store also an array in the cookie, with all read books. But the user can delete the cookies. Another solution is a database table, where you store, which ip open the video. Maybe you can match these ideas to improve your counting.
When i run this code , it throws me an error
$result = Commission::leftJoin("bill" , "bill.id" , "=" , "Commissions.bill_id")->selectRaw( $raw )->groupBy("Commissions.id")->get();
but this second code works fine
$result = Commission::leftJoin("bill" , "bill.id" , "=" , "Commissions.bill_id")->selectRaw( $raw )->groupBy("Commissions.id")->get()->first();
even i put ->take(10) , still throws me an error of
Maximum function nesting level of '1000' reached, aborting!
as you can see on the error message , i have set the xdebug.max_nesting_level to 1000
now that being said, i need to get all bill with same Commission ID , but the get() function wont allow me to do so unless i put first(). I am wondering what else may cause this error? Any help is much appreciated.
UPDATE
I have figured it out. Thanks for helping me sorting out possible causes . Anyway, I have to explain what was happened. The above code has nothing to do about the error(Apologies , I wasn't investigating enough and have to ask here).
I have Controller.php
public function retrieve( $type , $str = '' ){
$base = new BaseReport();
$class = ($type == "BaseReport" ? "Reports\\" . $type : "Reports\\" . $base->getMap($type) ) ;
$report = new $class();
return $report->getVariable($str);
}
public function retrieveData($items , $type , $where , $groupby)
{
$base = new BaseReport();
$class = ($type == "BaseReport" ? "Reports\\" . $type : "Reports\\" . $base->getMap($type) ) ;
$report = new $class();
return $report->retrieveData($items , $where , $groupby);
}
And a BaseReport.php
public function retrieveData($items , $where , $groupby = '' ){
//SOME LONG CODE
//THIS IS THE CODE I STATED IN THE QUESTION
$result = $model->leftJoin($table , $table . "." $pk , "=" , $base_table . "." . $fk)
->selectRaw( $raw )
->groupBy($base_table . "." . $pk)
->get();
return $result;}
Which I used consecutively somewhere in my page
$base_ = "commissions"
$transactions = $print_format->retrieveData($fcs , $base_ . ".report" , $where , $table_group_by );
$cellItem = $print_format->retrieve( $base . ".report" , $fcs[$i]);
And the $print_format->retrieve is returning null and caused the error
Thanks Again for sorting out things.
I believe this is happening because one of the chained methods you're calling is calling itself,causing a loop and the failure message you are receiving.
My hunch is it is the selectRaw method. What SQL are you passing in?
In addition it looks like you could use eager loading rather than a join to achieve the end you seek.
http://laravel.com/docs/5.1/eloquent-relationships#eager-loading
So Commission::with('bill')->where... or something similar.
Softdelete behavior works fine on execute delete statement via the entity manager as the following code:
$entity = $this->em->getRepository('Users')->find(7);
$this->em->remove($entity);
$this->em->flush();
but when execute the same functionality via QueryBuilder hard delete will execute on database
$qb = $this->em->createQueryBuilder();
$qb->delete('Users', 'p');
$qb->where($qb->expr()->eq('p.id', ':id'));
$qb->setParameters(array("id" => 7));
$result = $qb->getQuery()->getResult();
How can I allow softdelete in all cases either via entity manager or query builder
If you use DQL then you have to use a Query Hint. This should do the trick:
$query = $qb->getQuery()
$query->setHint(
\Doctrine\ORM\Query::HINT_CUSTOM_OUTPUT_WALKER,
'Gedmo\SoftDeleteable\Query\TreeWalker\SoftDeleteableWalker'
);
$result = $query->getResult();
Update:
The docs mention that you have to use a Query Hint but don't provide an example so I pulled the usage from their tests.
Docs: https://github.com/l3pp4rd/DoctrineExtensions/blob/master/doc/softdeleteable.md
Test Usage: https://github.com/l3pp4rd/DoctrineExtensions/blob/master/tests/Gedmo/SoftDeleteable/SoftDeleteableEntityTest.php
my old solution after previous answer by #Ken Hannel is:
Edit:
/vendor/doctrine/orm/lib/Doctrine/ORM/Query/SqlWalker.php
Replace walkDeleteClause function as the following:
public function walkDeleteClause(AST\DeleteClause $deleteClause)
{
$class = $this->em->getClassMetadata($deleteClause->abstractSchemaName);
$tableName = $class->getTableName();
$sql = 'DELETE FROM ' . $this->quoteStrategy->getTableName($class, $this->platform);
$this->setSQLTableAlias($tableName, $tableName, $deleteClause->aliasIdentificationVariable);
$this->rootAliases[] = $deleteClause->aliasIdentificationVariable;
//check if SoftDeleteableListener is attached
foreach ($this->em->getEventManager()->getListeners() as $eventName => $listeners) {
foreach ($listeners as $listener) {
if ($listener instanceof \Gedmo\SoftDeleteable\SoftDeleteableListener) {
$date = date('Y-m-d H:i:s');
$sql = 'UPDATE ' . $this->quoteStrategy->getTableName($class, $this->platform) . " SET deletedAt = ' " . $date . " ' ";
}
}
}
return $sql;
}
but really but I think Ken Hannel way is more professional and up to standard.