Laravel 5.4: Storing the 'Where' clause in a variable - php

I want to write a dynamic update query in Laravel which accepts arguments and can be used in whole project.
Following is my Controller function:
public function editquery(Request $request)
{
$city_id = $request->input('city_id');
$city_name = $request->input('city_name');
$tbl = 'city';
$data = ['city_name'=>$city_name];
$wher = ('city_id',1);
General_model::editrecord($data,$wher,$tbl);
return redirect()->action('Admin_controller#cities_page')->with('status','Record Updated Successfully!');;
}
Below is my Model function:
public static function editrecord($data,$wher,$tbl)
{
return DB::table($tbl)->where($wher)->update($data);
}
The only problem here is that I cannot store the value ('city_id',1) in the $wher variable. This is the screenshot of the error:
link to the image file
Is there any other way to do this. Please Help.

The where method accepts an array of conditions.
$table = 'city';
$conditions = [
['city_id', '=', '1']
];
$data = ['city_name' => $city_name];
General_model::editRecord($table, $conditions, $data);
// In your model
public static function editRecord($table, $conditions, $data)
{
return DB::table($table)->where($conditions)->update($data);
}
You can also set multiple conditions.
$conditions = [
['city_id', '=', '1'],
['test', '=', 'test'],
];
Edit
This is the default where method
where($column, $operator = null, $value = null, $boolean = 'and')
Setting the fourth parameter to or will make the condition orWhere.
Example
$conditions = [
['city_id', '=', '1'],
['test', '=', 'test', 'or'],
];

You can't do this
public static function editrecord($data,$wher,$tbl)
{
return DB::table($tbl)->where($wher)->update($data);
}
Since, where is a function; it expects 2 or 3 arguments and not just 1 argument.
You will have to pass both the arguments like so
public static function editrecord($data, $where_column, $where_val, $tbl)
{
return DB::table($tbl)->where($where_column, $where_val)
->update($data);
}
Then, in your controller function
$where_column = 'city_id';
$where_val = 1;
General_model::editrecord($data,$where_column,$where_val,$tbl);

Your code is not exactly in the style of Laravel, why would you want to create a separate static function, if such tasks are easily solved by the standard features of Eloquent / Query Builder?
Eloquent example:
app/City.php
<?php
class City extends Model {
protected $table = 'city';
protected $primaryKey = 'city_id';
protected $fillable = ['city_name'];
}
In your controller:
City::findOrFail($city_id)->update([
'city_name' => $city_name
]);
Query Builder example:
DB::table('city')->where(['city_id' => $city_id])->update([
'city_name' => $city_name
]);
This is much easier to read, understand and support than functions that do similar things in an incomprehensible way.

Related

Updating a one to many relationship without the use of implode laravel

I am trying to update my data into my database where the relationship is that I have many schools, so when I try to save inside my database, I want to get something like this:
[![enter image description here][1]][1]
But I only know how to use implode function to do it, and I can only make it like this:
I tried doing this but it doesn't work:
public function update1(Request $request, $user_id){
$rows = qualification::where('user_id', $user_id)->get();
foreach ($rows as $row){
switch ($row['meta_key']){
case 'school_name':
$row['meta_value'] = $request->input('School');
break;
case 'start_date':
$row['meta_value'] = $request->input('SDate');
break;
case 'end_date':
$row['meta_value'] = $request->input('EDate');
break;
case 'qualification_list':
$row['meta_value'] = $request->input('qualification');
break;
}
$row->save();
}
return redirect('/home');
}
When I try using that code it will give me this error, Array to string conversion
PersonalInfo model:
class PersonalInfo extends Eloquent
{
use SoftDeletes;
protected $table = 'personal_infos';
protected $primaryKey = 'id';
protected $dates = ['deleted_at'];
public function userQualifications()
{
return $this->hasMany('App\Qualification','user_id');
}
Qualification model:
class Qualification extends Model
{
protected $table = "qualifications";
public function PersonalInfos() {
return $this->belongsTo('App\PersonalInfo');
}
}
No error message:
Assuming you have your relationship setup properly in your User model, you could try something like this (not tested):
public function update1(Request $request, $user_id){
// get the user
$user = PersonalInfo::find($user_id);
// create the new array of meta data
$data = array();
// loop through the inputs array count
for($i=0; $i < count($request->input('School')); $i++) {
$data[] = [
'meta_key' => 'school_name',
'meta_value' => $request->input('School')[$i]
];
$data[] = [
'meta_key' => 'start_date',
'meta_value' => $request->input('SDate')[$i]
];
$data[] = [
'meta_key' => 'end_date',
'meta_value' => $request->input('EDate')[$i]
];
$data[] = [
'meta_key' => 'qualification_list',
'meta_value' => $request->input('qualification')[$i]
];
}
// create the relationships
$user->userQualifications()->createMany($data);
return redirect('/home');
}

Laravel 5.5 - Method paginate not found

I don't know what's wrong, but here's my script at my AppController.
function getData () {
$list_data = MyModel::all()->sortBy('id')->paginate(15);
$count_data = $list_siswa->count();
return view('pages.list', ['list' => $list_data, 'count' => $count_data]);
}
And here's my model
class MyModel extends Model {
protected $table = 'students';
protected $fillable = [
'id',
'name',
'class',
'gender',
'address'
];
}
Any idea? I think the problem is in my controller.
You must paginate a database query not a collection, therefore you must user orderBy instead of combining all with sortBy, I have tested the below code and can confirm it works
function getData () {
$list_data = MyModel::orderBy('id')->paginate(15);
$count_data = $list_data->count();
return view('pages.list', ['list' => $list_data, 'count' => $count_data]);
}

How to get flexibility in laravel sql query

I want to add a sql filter where('comment_id', '=', 1) to php code
$datas = $this->model->ADD HERE->orderBy('created_at', 'DESC')->paginate(15);
Trying to add the string to code take me hours. How to make it?
Here is my code:
CommentResource.php passing the sql filter as string parameter.
<?php
class CommentResource extends BaseResource
{
public function index()
{
$filter = "where('comment_id', '=', 1)";
return parent::index_filter($filter);
}
CommentResource.php
<?php
class BaseResource extends Controller
{
protected function index_filter($filter)
{
$datas = $this->model->ADD HERE->orderBy('created_at', 'DESC')->paginate(15);
return view($this->resourceView.'.index')->with('datas', $datas);
}
}
As I understand you want to use different types of where as filters in your queries. That's why you want to make them dynamic. I would suggest the following solution for your task:
<?php
class CommentResource extends BaseResource
{
public function index()
{
$filter = [ 'operator' => 'where', 'args' => ['comment_id', '=', 1]];
return parent::index_filter($filter);
}
<?php
class BaseResource extends Controller
{
protected function index_filter($filter)
{
$where = $filter['operator'];
$args = $filter['args'];
$datas = $this->model->$where(...$args)->orderBy('created_at', 'DESC')->paginate(15);
return view($this->resourceView.'.index')->with('datas', $datas);
}
}
However, it will work starting from Php5.6+ because of oeprator ...
I am not sure if I got your requirements correctly, but if you rewrite index_filter to accept field and value separately, then you may user a regular where() from laravel:
protected function index_filter($field,$value)
{
$datas = $this->model->where($field,$value)->orderBy('created_at', 'DESC')->paginate(15);
return view($this->resourceView.'.index')->with('datas', $datas);
}
You can find the docs here. In case you really need more flexibility:
protected function index_filter($filter)
{
$datas = $this->model->whereRaw($filter)->orderBy('created_at', 'DESC')->paginate(15);
return view($this->resourceView.'.index')->with('datas', $datas);
}
Have in mind though that this is really dangerous, as you expose the possibility to inject malicious code, it should be definitely properly escaped beforehand.
My latest code works right. I'll post here.
<?php
class CommentResource extends BaseResource
{
public function index()
{
$options = [
'filters'=>[
[ 'operator' => 'where',
'args' => [
[ 'article_id', '=', $article_id ],
[ 'comment_id', '=', $comment_id ],
// add filter args...
],
],
// add filter operators here...
],
'sorts' => [
'column' => $sortColumn, // change sort column...
'order' => $sortOrder, // change sort order...
],
];
return parent::index_filter($options);
}
<?php
class BaseResource extends Controller
{
protected function index_filter($options, $number=15)
{
$result = $this->model;
foreach ($options['filters'] as $filter) {
$operator = $filter['operator'];
$args = $filter['args'];
$result = $result->$operator($args);
}
if ( $options['sorts'] != [] ) {
$column = $options['sorts']['column'];
$order = $options['sorts']['order'];
$result = $result->orderBy($column, $order);
}
return $result->paginate($number);
}
}
The reason I change ...$args to $args is, when 'args' has more than on value, for example,
'args' => [
[ 'article_id', '=', $article_id ],
[ 'comment_id', '=', $comment_id ],
// add filter args...
],
...$args will change 'args' to one array, but $args will remain 'args' as nest array, which is the operator 'where' want.

laravel querying multiple classes and or tables

How do I query more than two tables. What I want to do is have a list of products queryed by a genre and then query productvariations - where a product variation has a producttype_id = $producttype->id
Route::get('browse/{producttype_slug}/{genre_slug}', array(
'as' => 'products.viewbygenre',
function($productype_slug, $genre_slug)
{
$producttype = ProductTypes::where('slug', '=', $productype_slug)->firstOrFail();
$genre = GenreTypes::where('slug', '=', $genre_slug)->firstOrFail();
// error below
$products = Product::with(array('ProductVariations', 'GenreTypes'))
->where('genre', '=', $genre->id)->get();
return View::make('products.viewbygenre')->with(compact('productvariations', 'genre', 'producttype'));
}))->where('producttype_slug', '[A-Za-z\-]+')->where('genre_slug', '[A-Za-z\-]+');
products class
class Product extends \Eloquent {
protected $table = "products";
protected $fillable = ['keywords', 'description', 'title', 'slug', 'release_date', 'clip'];
public function productvariations() {
return $this->hasMany("ProductVariations");
}
public function variations() {
$variations = $this->productvariations()->get();
return $variations;
}
public function genres() {
return $this->belongsToMany('GenreTypes', 'product_genretypes', 'product_id', 'genretype_id')->withTimestamps();
}
}
I didn't quite understand the issue so I will just refer to this bit:
// error below
$products = Product::with(array('ProductVariations', 'GenreTypes'))
->where('genre', '=', $genre->id)->get();
I believe you cannot use a where clause this way on a 'with' array. I am not 100% sure if this works when you have more than one parameter in your with method but this is worth trying:
$products = \Product::with(array('ProductVariations', 'GenreTypes' => function ($query)
{
// Note I think you also had a mistake in your column name
// (genre should be genretype_id?)
// Also ... not sure how you are getting the $genre->id variable
// as I cannot see the the $genre object / collection in this method you provided !
$query->where('genretype_id', '=', $genre->id);
}))->get();
Let us know how you get on.

DQL Update with relations

Following Models:
class User extends Doctrine_Record {
public function setTableDefinition() {
$this->hasColumn ( 'iron', 'integer', 4 );
}
public function setUp() {
$this->hasMany ('Field as Fields', array(
'local' => 'id',
'foreign' => 'owner_id'
));
}
}
class Field extends Doctrine_Record {
public function setTableDefinition() {
$this->hasColumn('owner_id','integer',4);
$this->hasColumn('ressource_id','integer',4);
$this->hasColumn('ressource_amount','integer','2');
}
public function setUp() {
$this->hasOne('User as Owner',array(
'local' => 'owner_id',
'foreign' => 'id'
));
}
}
And I try following DQL:
$sqlRessourceUpdate = Doctrine_Query::create()
->update('Field f')
->set('f.Owner.iron','f.Owner.iron + f.ressource_amount')
->where('f.ressource_id = ?',1);
Result:
'Doctrine_Query_Exception' with message 'Unknown component alias f.Owner'
Basicly I just want to update the "iron" attribute from the Field-Owner according to the fields' value
I am guessing you can't reference other tables like that in your query.
This may not be the best way but, here is what I do
$q = Doctrine_Query::create()
->select('*')
->from('Field')
->where('ressource_id = ?',1); //btw resource has one 's'
$field = $q->fetchone();
$field->Owner['Iron'] += $field->ressource_amount;
$field->save();
EDIT:
Actually I don't know if that will work... this is more like what I do
$q = Doctrine_Query::create()
->select('*')
->from('Field')
->where('ressource_id = ?',1); //btw resource has one 's'
$field = $q->fetchone();
$user = $field->Owner;
$user['Iron'] += $field->ressource_amount; // I have never used a += like this, but in theory it will work.
$user->save();

Categories