How to combine four queries in laravel? - mysql

I have draws on my site, in order to take part in the draw, you need to do a certain action per day. And there is a code that checks it all:
$date = Carbon::today();
$sta = \DB::table('ets')->where('user_id', $this->user->id)->where('created_at', '>=', $date)->get();
$sta = \DB::table('ets_1x1')->where('user_id', $this->user->id)->where('created_at', '>=', $date)->get();
$sta = \DB::table('ets_low')->where('user_id', $this->user->id)->where('created_at', '>=',$date)->get();
$sta = \DB::table('ets_duel')->where('user_id', $this->user->id)->where('created_at', '>=', $date)->get();
if ($sta == NULL) {
return response()->json(['status' => 'error', 'msg' => 'Error']);
}
This code checks if there is a user record in 4 possible tables. I made an entry in the table ets_1x1, but still I can’t take part, because the error seemed to not find me in the database. I removed all the tables and left only ets_1x1 and I was accepted into the drawing.
As I understand it, the value is taken from the last request. How can I combine a query into 1 and do a check on these 4 tables?
UPD:
I also tried to give new names to the variables and display the response code differently, now participation in the drawing is accepted from all people, even from those who have not fulfilled the conditions, now it looks:
if(!empty($sta_1) || !empty($sta_2) || !empty($sta_3) || !empty($sta_4)) {
return response()->json(['status' => 'error', 'msg' => 'Error']);
}
Where my mistake?

That code is not going to work because:
The first piece of code will evaluate only the last request (and in consecuence, only if there is any existent user on the last table only).
The second piece of code is not being evaluated correctly, you are running empty function on a Laravel collection.
Why don't you try this? I think it should work:
$date = Carbon::now();
$userExists = false;
$tables = ['ets', 'ets_1x1', 'ets_low', 'ets_duel'];
foreach ($tables as $tableName) {
$result = \DB::table($tableName)
->where('user_id', $this->user->id)
->where('created_at', '>=', $date)
->get()
;
if ($result->isNotEmpty()) {
$userExists = true;
break;
}
}
if (!$userExists) {
return response()->json(['status' => 'error', 'msg' => 'Error']);
}

Related

How to call Variable Column name in Laravel MYSQL Select Query

My concern:
if ($case=='private') {
$langtitle = 'title';
}
else {
$langtitle='title_gov';
}
if it is Government (falls under else case above) I want to select, 'title' as well as 'title_gov' with Select in query as,
Images::select($langtitle ,'id', 'title')
->groupBy('id')
->paginate('10');
If it is private, then only 'title' to be selected. I do not want to use if else case for Query, instead I want to call it using Variable or regex or some method. How can I?
You were on the right track, the only issue you were having is that when the case is "private" it will load the column "title" twice, instead you can do the following:
if ($case == 'private') {
$langtitle = ['id', 'title'];
}else{
$langtitle = ['id', 'title', 'title_gov'];
}
Images::select($langtitle)->groupBy('id')->paginate('10');
I think you can use the When eloquent function
$query = Images::query();
$query->when(
$case == 'private',
function ($query) {
return $query->select('title', 'id');
},
function ($query) {
return $query->select('title_gov' ,'id', 'title'));
}
)
->groupBy('id')
->paginate('10');
You can read more about it here.

Yii2 show item based on NOW() doesn't show the day itself

I'm trying to create a 'next in the agenda' item to place on an index page for an application I created with Yii2.
With the function below I retrieve the next item in the database that is 'upcoming' and shown based on the class of the trip and the date. I'm using the NOW() expression.
However, this means the next upcoming item will be shown until it hits the NOW() date, so its not shown anymore on the day itself. Ideally, i should have the upcoming item to show also until the time has passed the $this->time or only show the item after this one the day after NOW().
Anyone any tips how I can achieve this?
public function searchANext($params)
{
$query = Trip::find();
$time = new Expression('NOW()');
$query->where(['class' => Trip::CLASS_A])
->andWhere(['>=', 'date', $time])
->limit(1);
$dataProvider = new ActiveDataProvider([
'query' => $query,
'sort' => ['defaultOrder' => ['date' => SORT_ASC]],
'pagination' => false
]);
if (!($this->load($params) && $this->validate())) {
return $dataProvider;
}
return $dataProvider;
}
I do not know why you are returning an ActiveDataProvider when you only want to get a single record, it is unnecessary for this case in my opinion.
Also, you are loading $params and validating the model after you create the query, so if the $params are not valid you will still get an error and you eventually return $dataProvider no matter what the load and validate methods return.
I suggest you make a few changes to your code:
public function searchANext($params)
{
// Try to load $params and validate the model first and return false
// instead of returning the result of the search.
if(!($this->load($params) && $this->validate())) {
return false;
}
// Let's get the currend DateTime. You might need to change this
// depending on the format of the 'date' field from 'Trip'
$now = date('Y-m-d H:i:s');
// Instead of creating an ActiveDataProvider, you can just get the one
// record directly and return it.
$model = Trip::find()
->where(['class' => Trip::CLASS_A])
->andWhere(['>=', 'date', $now])
->orderBy('date ASC')
->one();
return $model;
}

Add items to query result - Laravel

I'm slowly moving my API to Laravel and coming to grips with the Query Builder.
I'm trying to achieve this:
$data = array();
$query = "SELECT * FROM blog_posts WHERE post_type = 3 AND post_status = 1 ORDER BY id DESC";
$result = mysqli_query($cms_connection, $query);
if($result) {
while($row = mysqli_fetch_assoc($result)) {
$row['post_seo'] = seoUrl($row['post_title']);
$data['data'][] = $row;
}
$data['success'] = true;
$response = json_encode($data);
}
My problem isn't necessarily with getting the query, but as you can see I'm using the result of the query and then injecting it back into the final array.
So essentially, I'm fetching rows, transforming some of the attributes fetched, and then injecting the newly created attributes into the resulting array.
This is what I have so far:
$posts = DB::table('blog_posts')
-where(['post_type' => 1, 'post_status' => 1)
->orderBy('id', 'desc')
->take(5)->get();
You could do it this way
// get your data (yours part of code)
$posts = DB::table('blog_posts')
-where(['post_type' => 1, 'post_status' => 1])
->orderBy('id', 'desc')
->take(5)->get();
// add post_seo
foreach ($posts as $post) {
$post->post_seo = seoUrl($post->post_title);
}
// set result array
$data['data'] = $posts;
$data['success'] = true;
// response
$response = response()->json($data);
// or in case you want to return it just
return response()->json($data);
EDIT
You could do it also a bit better, using Eloquent. If you have such model (you need to add valid namespaces and use statements)
class BlogModel extends Model
{
protected $table = 'blog_posts';
protected $appends = ['post_seo'];
public function getPostSeoAttribute($value)
{
return seoUrl($this->post_title);
}
}
(added accessor to post_seo attribute and added post_seo to results when converting to array)
You can now do (shorter syntax than in previous example):
// get your data
$posts = BlogPost::where('post_type',1)
->where('post_status',1)
->orderBy('id', 'desc')
->take(5)->get();
// response
$response = response()->json(['data' => $posts, 'success' => true]);

How to avoid the instruction "return" inside a function in Symfony2?

I would like to know how to avoid the instruction "return" inside a function in Symfony2. In other words how can I make a void function which doesn't return anything. In fact I have tried that for a long time but every time I run the code I did I see this error message: "The controller must return a response" ... By the way, this is the code that I have:
public function AddeventsgroupeAction(Request $request) {
$eventg = new eventsgroupe();
$form = $this->createForm(new eventsgroupeType(), $eventg);
$em = $this->getDoctrine()->getManager();
$securityContext = $this->get('security.context');
$token = $securityContext->getToken();
$user = $token->getUser();
$id = $user->getId();
$groupe=$this->getRequest('groupe');
$idg = intval($groupe->attributes->get('id'));
$qb = $em->createQueryBuilder();
$qb->select('l')
->from('IkprojGroupeBundle:Groupe', 'l')
->from('IkprojGroupeBundle:eventsgroupe', 'e')
->where(' l.id = :g and e.idGroupe = l.idAdmin and l.id = e.idEventGroupe');
$qb->setParameter("g", $idg);
$query = $qb->getQuery();
$res = $query->getResult();
$rows = array();
foreach ($res as $obj) {
$rows[] = array(
'id' => $obj->getId());
}
if ($request->isMethod('POST')) {
$form->handleRequest($request);
if ($form->isValid()) {
$eventg-> setIdGroupe($id);
$eventg-> setIdEventGroupe($idg);
$em->persist($eventg);
$em->flush();
return $moslem="yes";
}
} else {
return $this->render('IkprojGroupeBundle:GroupeEvents:Addeventgroupe.html.twig', array(
'groupe' => $rows,
'event' => $eventg,
'form' => $form->createView(),
));
}
}
How can I replace the instruction : return $moslem="yes"; in order to not return anything??...Is that possible??
To answer your basic question, a simple return will return a void from your function.
The "controller must return a response" message actually comes from the request handler. You need to tell the request handler what you want it to do. There is no default page so a void return will trigger the error.
In most cases, after successfully processing a posted form you will want to return a redirect response.
Something like:
$form->handleRequest($request);
if ($form->isValid()) {
...
$em->flush();
return $this->redirect($this->generateUrl('task_success'));
I should point out that your form code seems to be from S2.1 or older. It's unnecessarily complicated. You should be using at least 2.3. Make sure you are looking at the correct version of the documentation. Hint: the isValid() takes care of the POST check.
http://symfony.com/doc/current/book/forms.html#handling-form-submissions
It's also worth while to understand the request/response workflow.
http://symfony.com/doc/current/book/http_fundamentals.html
Digging into the code can also help in understanding where the error message is coming from:
Symfony\Component\HttpKernel\HttpKernel#handleRaw($request)
Simple, delete the else statement and if $request->isMethod('POST') or $form->isValid() returns false the code inside will not be executed then the script return the default view.
EDIT: you can also make a redirect with a flash message where needed like this:
$this->get('session')->getFlashBag()->add('success', 'your success message');
return $this->redirect($this->generateUrl('your_route'));
Remember to add support for flash message in your view looking at the Symfony2 docs

Laravel 4 Method Improvement

I have this index method:
public function index()
{
// In the view, there are several multiselect boxes (account managers, company names and account types). This code retrives the values from the POST method of the form/session.
$company_names_value = Input::get('company_names_value');
$account_managers_value = Input::get('account_managers_value');
$account_types_value = Input::get('account_types_value');
// If there has been no form submission, check if the values are empty and if they are assign a default.
// Essentially, all of the records in the table column required.
if (is_null($company_names_value))
{
$company_names_value = DB::table('accounts')
->orderBy('company_name')
->lists('company_name');
}
if (is_null($account_managers_value))
{
$account_managers_value = DB::table('users')
->orderBy(DB::raw('CONCAT(first_name," ",last_name)'))
->select(DB::raw('CONCAT(first_name," ",last_name) as amname'))
->lists('amname');
}
if (is_null($account_types_value))
{
$account_types_value = DB::table('account_types')
->orderBy('type')
->lists('type');
}
// In the view, there is a dropdown box, that allows the user to select the amount of records to show per page. Retrieve that value or set a default.
$perPage = Input::get('perPage', 10);
// This code retrieves the order from the session that has been selected by the user by clicking on a table column title. The value is placed in the session via the getOrder() method and is used later in the Eloquent query and joins.
$order = Session::get('account.order', 'company_name.asc');
$order = explode('.', $order);
// Here we perform the joins required and order the records, then select everything from accounts and select their id's as aid. Then whereIn is used to select records where company name, account manager name and account type matches the values of the multiselect boxes or the default set above.
$accounts_query = Account::leftJoin('users', 'users.id', '=', 'accounts.user_id')
->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
->orderBy($order[0], $order[1])
->select(array('accounts.*', DB::raw('accounts.id as aid')));
if (!empty($company_names_value)) $accounts_query = $accounts_query->whereIn('accounts.company_name', $company_names_value);
$accounts = $accounts_query->whereIn(DB::raw('CONCAT(users.first_name," ",users.last_name)'), $account_managers_value)
->whereIn('account_types.type', $account_types_value)
->paginate($perPage)->appends(array('company_names_value' => Input::get('company_names_value'), 'account_managers_value' => Input::get('account_managers_value'), 'account_types_value' => Input::get('account_types_value')));
$accounts_trash = Account::onlyTrashed()
->leftJoin('users', 'users.id', '=', 'accounts.user_id')
->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
->orderBy($order[0], $order[1])
->select(array('accounts.*', DB::raw('accounts.id as aid')))
->get();
$message = Session::get('message');
$default = ($perPage === null ? 10 : $perPage);
$this->layout->content = View::make('admin.accounts.index', array(
'accounts' => $accounts,
'accounts_trash' => $accounts_trash,
'company_names' => DB::table('accounts')->orderBy('company_name')->lists('company_name', 'company_name'),
'account_managers' => DB::table('users')->orderBy(DB::raw('CONCAT(first_name," ",last_name)'))->select(DB::raw('CONCAT(first_name," ",last_name) as amname'))->lists('amname', 'amname'),
'account_types' => DB::table('account_types')->orderBy('type')->lists('type', 'type'),
'perPage' => $perPage,
'message' => $message,
'default' => $default
));
}
Basically, I am building a query that searches several tables (hence the joins). In the view a user has the ability to select multiple values from various multi-select boxes and then submit a form which will then populate the $company_names_value, $account_managers_value and $account_types_value variables.
Initially, when there is no form submission, I'm using Query Builder to select all records for each type, and then using them in the query.
It works but it is slow and messy. I was wondering if any of you Laravel 4 gurus could help me improve it further, so that the queries are faster and the code is lighter.
Thanks in advance.
This has now been refactored significantly, and it is very fast now. I've moved most of my code in to my models, as well as refactoring that code.
Here's the new index method:
public function index()
{
$account = explode(',', Input::get('account'));
$account_manager = explode(',', Input::get('account_manager'));
$account_type = explode(',', Input::get('account_type'));
$perPage = Input::get('perPage', 10);
$order = Session::get('account.order', 'company_name.asc');
$order = explode('.', $order);
$accounts = Account::accounts($order, $account, $account_manager, $account_type)->paginate($perPage)->appends(array(
'account' => Input::get('account'),
'account_manager' => Input::get('account_manager'),
'account_type' => Input::get('account_type'),
'perPage' => Input::get('perPage')
));
$accounts_trash = Account::accountsTrash($order)->get();
$message = Session::get('message');
$default = ($perPage === null ? 10 : $perPage);
$this->layout->content = View::make('admin.accounts.index', compact('accounts', 'accounts_trash', 'message', 'default'));
}
And the new getAccountByName() method in my controller that is used during my AJAX call. This should probably go in the model:
public function getAccountByName()
{
$name = Input::get('account');
return Account::select(array('id', DB::raw('company_name as text')))->where('company_name', 'like', "%$name%")->get();
}
And finally two new methods in my model for retrieving accounts and accounts trash:
public function scopeAccounts($query, $order, $account, $account_manager, $account_type)
{
$query->leftJoin('users', 'users.id', '=', 'accounts.user_id')
->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
->orderBy($order[0], $order[1])
->select(array('accounts.*', DB::raw('accounts.id as aid')));
if (!empty($account[0])) {
$query = $query->whereIn('accounts.id', $account);
}
if (!empty($account_manager[0])) {
$query = $query->whereIn('users.id', $account_manager);
}
if (!empty($account_type[0])) {
$query = $query->whereIn('account_types.id', $account_type);
}
}
public function scopeAccountsTrash($query, $order)
{
$query->onlyTrashed()
->leftJoin('users', 'users.id', '=', 'accounts.user_id')
->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
->orderBy($order[0], $order[1])
->select(array('accounts.*', DB::raw('accounts.id as aid')));
}
Again, there's probably a ton of things to get tidied up here but I'm certainly closer to a much faster and cleaner solution. Doing it like this has reduced the loading times from 12 seconds to 234ms.