How to do combination query parameter in fetching table records in CAKEPHP 3.x - cakephp-3.x

on cakephp 2, I have a method to 'collect' parameter in controller, for example, at view, I have combobox A, combobox B, input 'keyword' and on controller. Then I collect that data on COntroller to create conditions filter.
then I can use it on my conditions query, like: 'conditions'=>$condition. Then somehow in CakePHP 3, the array is changed into [ ], so i can't use this method anymore.
How can I mimic that method in CakePHP 3? or is there other approach to do conditions collection?
I tried the same way as array, but it won't work. I can't find it online yet. Here the example collection i did previously
$conditions = array();
$conditions['StoreProduct.stok >']=0;
$conditions['StoreProduct.deleted']=0;

I recommed you to use the Query Builder like:
$query = $articles
->find()
->select(['id', 'name'])
->where(['condition1 >' => 0, 'condition2' => 0])
->order(['created' => 'DESC']);
More informations: https://book.cakephp.org/3.0/en/orm/query-builder.html#selecting-data

Related

Laravel create multiple records in one query with Eloquent and get the created models

I know I can do the following to create multiple records with one query :
$users = [];
$users[] = ['name' => 'Tom'];
$users[] = ['name' => 'Jerry'];
$result = User::insert($users);
The problem of this approach is that ìnsert uses the query builder, and returns a boolean.
What if I wanted to have the created Eloquent models returned ? Would that be possible without having to do another query to retrieve them (how would I do that since I don't know the created ids ?) ?
I'm looking for something like the create method (which returns the created User model), but for multiple inserts (afaik createMany does not work outside of relationships)
Thanks

User::all show relationship items

I Laravel 5.5 I am returning users information like this...
$users = User::all();
return Response::json(array(
'error' => false,
'response' => $users,
));
I have a belongs to many categories relationship setup and would like to also show all of the categories each user belongs to.
Anyone have an example I can see?
Use the with() method to load categories for each user:
$users = User::with('categories')->get();
If you don't need to load all the columns from the categories table, use select() inside the with() closure. Also, since you're using Laravel 5.5 you could use Resource classes for formatting JSON.

Bulk insertion of array of eloquent models

Is it possible to insert several eloquent models in one query?
Let's say I have eloquent model Page and I want to insert array of pages or collection of pages in one query
$page1 = new Page();
$page2 = new Page();
$pages = [
$page1,
$page2,
];
or
$pages = Collection([$page1, $page2]);
I want something like
$pages->save();
But it warns that "Method save does not exist".
I saw this, but there they insert array of arrays and I want to insert array of eloquent models.
You could try the saveMany() option.
This example might work for you:
DB::table('pages')->saveMany($pages);
And if you are working with relationships you can even use a "cleaner" way (just showing you example of ways to use this function):
$book = App\Book::find(1);
$book->pages()->saveMany([
new App\Page(['title' => 'A new page.']),
new App\Page(['title' => 'Another page.']),
]);

When chaining firstOrCreate() and with(), Eloquent query returns unexpected results

A beginner question... I have the following Eloquent query. It returns me a collection of Sheets instead of just one Sheet which seems wrong - the documentation for firstOrCreate() says it will return the first row, not a collection:
// Original query which returns a collection instead of first row
$sheet = Sheet::firstOrCreate(["user_id" => $userId, “date" => $date])->with(“post.tags", “post.categories", “meta")->get();
If I remove the with() then I get just one sheet as expected, but I am missing my extra data:
// I get one Sheet as expected but I am missing my extra data
$sheet = Sheet::firstOrCreate(["user_id" => $userId, “date" => $date])->get();
I can fix it by using first() instead of get(), but this seems wrong:
// Works but seems like the wrong fix
$sheet = Sheet::firstOrCreate(["user_id" => $userId, “date" => $date])->with(“post.tags", “post.categories", “meta")->first();
The reason it seems wrong is that I am effectively specifying "get the first row" twice in the query builder. I'm not sure why adding with() makes firstOrCreate return a collection instead. Is there something I am doing wrong in my syntax or is this just a Laravel quirk?
Thanks!
When you're chaining methods like this, you need to be aware what each of the methods you're calling actually returns.
Here is a little bit of a breakdown:
// your original statement
$sheet = Sheet::firstOrCreate(["user_id" => $userId, "date" => $date])
->with("post.tags", "post.categories", "meta")->get();
// is equivalent to this:
// this creates an instance of Sheet
$sheet = Sheet::firstOrCreate(["user_id" => $userId, "date" => $date]);
// this calls with() on the Sheet instance, which returns an Eloquent Query Builder
$sheet = $sheet->with("post.tags", "post.categories", "meta");
// this calls get() on the Query Builder, which returns a Collection of Sheets
$sheet = $sheet->get();
Hopefully that should spread some light on why you were getting a Collection.
For your original question, though, since you already have the instance after the call to firstOrCreate(), all you're really looking to do is load the relationships for it. You can do this using the load() method:
$sheet = Sheet::firstOrCreate(["user_id" => $userId, "date" => $date])
->load("post.tags", "post.categories", "meta");
Use with when you're using the query builder. Use load when you already have an instance and you want to eager load the relationships for it.

Prevent SQL injection for queries that combine the query builder with DB::raw()

In Laravel 4, I want to protect some complex database queries from SQL injection. These queries use a combination of the query builder and DB::raw(). Here is a simplified example:
$field = 'email';
$user = DB::table('users')->select(DB::raw("$field as foo"))->whereId(1)->get();
I've read Chris Fidao's tutorial that it is possible to pass an array of bindings to the select() method, and therefore prevent SQL injection correctly, by using prepared statements. For example:
$results = DB::select(DB::raw("SELECT :field FROM users WHERE id=1"),
['field' => $field]
));
This works, but the example puts the entire query into a raw statement. It doesn't combine the query builder with DB::raw(). When I try something similar using the first example:
$field = 'email';
$user = DB::table('users')->select(DB::raw("$field as foo"), ['field' => $field])
->whereId(1)->get();
... then I get an error: strtolower() expects parameter 1 to be string, array given
What is the correct way to prevent SQL injection for queries that combine the query builder with DB::raw()?
I discovered the query builder has a method called setBindings() that can be useful in this instance:
$field = 'email';
$id = 1;
$user = DB::table('users')->select(DB::raw(":field as foo"))
->addSelect('email')
->whereId(DB::raw(":id"))
->setBindings(['field' => $field, 'id' => $id])
->get();
Eloquent uses PDO under the hood to sanitize items. It won't sanitize items added to SELECT statements.
The mysqli_real_escape_string method is still useful for sanitizing SQL strings, however.
Consider also (or instead) keeping an array of valid field names from the users table and checking against that to ensure there isn't an invalid value being used.
$allowedFields = ['username', 'created_at'];
if( ! in_array($field, $allowedFields) )
{
throw new \Exception('Given field not allowed or invalid');
}
$user = DB::table('users')
->select(DB::raw("$field as foo"))
->whereId(1)->get();

Resources