Checking duplicated data in Laravel - php

This code work as send to inn_db table from ext_db.
but it cannot check if the data is the same or different in inn_db.
So there posited same values in inn_db.
How could I add that job?.
Laravel-5.4, MySQL, InnoDB.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use \DB;
class UpdateCustomerController extends Controller
{
public function db_update()
{
$customers = \DB::connection('ext_db')->table('customers')->orderBy('customer_id')->chunk(1000, function ($all){
foreach ($all as $kunde){
DB::connection('inn_db')->table('custoemrs')->insert(
[$kunde->customer_id
$kunde->name,
$kunde->email]);
}
});
}
}
Finally, I got the answer as below code with connect view when after discussion.
Thanks to #Pramid and #Badea :)
$customers = \DB::connection('ext_db')->table('customers')->orderBy('customer_id')->chunk(1000, function ($all){
foreach ($all as $kunde){
$existing_kunde = DB::connection('inn_db')->table('customers')->where([
['customer_id', '=', $kunde->customer_id],
['name', '=', $kunde->name],
['email', '=', $kunde->email]
])->first();
if ( ! $existing_kunde) {
DB::connection('inn_db')->table('customers')->insert([
'customer_id' => $kunde->customer_id,
'name', => $kunde->name,
'email', => $kunde->email
]);
}
}
});
$kundes = \DB::connection('ext_db')->table('customers')->get();
return view('kundes.index')
->with('kundes', $kundes);

Give this a try, you basically need to check each record of the chunk in your customer table if it doesn't exist then allow them to get insert into customer table
public function db_update()
{
$customers = \DB::connection( 'ext_db' )->table( 'customers' )->orderBy( 'customer_id' )->chunk( 1000, function ( $all ) {
foreach ( $all as $kunde ) {
$kunde_exist = DB::connection( 'inn_db' )->table( 'customers' )
->where( [
'customer_id' => $kunde->customer_id,
'name' => $kunde->name,
'email' => $kunde->email,
] )->first();
if ( ! $kunde_exists ) {
DB::connection( 'inn_db' )->table( 'customers' )->insert(
[ $kunde->customer_id
$kunde->name,
$kunde->email]);
}
}
} );
}

Yes, you need to check before inserting a customer. Just add a condition like bellow:
foreach ($all as $kunde){
$existing_kunde = DB::connection('inn_db')->table('custoemrs')->where('customer_id', $kunde->customer_id)->first();
if ( ! $existing_kunde) {
DB::connection('inn_db')->table('custoemrs')->insert(
[$kunde->customer_id
$kunde->name,
$kunde->email]);
}
}

Related

Pass id from first model into a Eloquent

I have a problem wanting to pass the id of Products in the subqueries.
The first code is what I have so far. The second is the way I want to do with Eloquent, but I can't.
$result = [];
Product::with(['locals.presentations'])->each(function ($product) use (&$result) {
$body['id'] = $product->id;
$body['nombre'] = $product->nombre;
$sedes = [];
$product->locals->each(function ($local) use (&$sedes, $product) {
$presentations = [];
$local->presentations->each(function ($presentation) use (&$presentations, $local, $product) {
if ($presentation->local_id == $local->id && $presentation->product_id == $product->id) {
$presentations[] = [
'local_id' => $presentation->local_id,
'product_id' => $presentation->product_id,
'presentacion' => $presentation->presentation,
'precio_default' => $presentation->price
];
}
});
...
});
return $result;
I want transform the previous code into this with Eloquent, but I can't pass the product_id into the subqueries:
$products = Product::with(['locals' => function ($locals) {
//How to get the id from Product to pass in the $presentations query ??????
$locals->select('locals.id', 'descripcion')
->with(['presentations' => function ($presentations) {
$presentations
// ->where('presentations.product_id', $product_id?????)
->select(
'presentations.local_id',
'presentations.product_id',
'presentations.id',
'presentation',
'price'
);
}]);
}])->select('products.id', 'nombre')->get();
return $products;
Product
public function locals()
{
return $this->belongsToMany(Local::class)->using(LocalProduct::class)
->withPivot(['id', 'is_active'])
->withTimestamps();
}
Local
public function presentations()
{
return $this->hasManyThrough(
Presentation::class,
LocalProduct::class,
'local_id',
'local_product_id'
);
}
You can simply use the has() method if you have set the relations correctly on the Product and Local models. This will return ONLY the products which has locals AND presentations.
If you want every product but only the locals and presentations with the product_id equals to the products.id, then you don't have to do anything. The relationship you set in your models already checks if the id matches.
$products = Product::has('locals.presentations')
->with(['locals' => function ($locals) {
$locals
->select('locals.id', 'descripcion')
->with(['presentations' => function ($presentations) {
$presentations->select(
'presentations.local_id',
'presentations.product_id',
'presentations.id',
'presentation',
'price'
);
}]);
}])->select('products.id', 'nombre')->get();

Laravel improve exists() boolean queries with eager loading

I'm trying to get rid of queries that look like this:
SELECT EXISTS(
SELECT *
FROM `ignorings`
WHERE `ignorings`.`user_id` = 80101 AND
`ignorings`.`user_id` IS NOT NULL AND
(`ignorable_id` = 79141)
) AS `exists`
SELECT EXISTS(
SELECT *
FROM `favorites`
WHERE `favorites`.`favorited_id` = 341 AND
`favorites`.`favorited_id` IS NOT NULL AND
`favorites`.`favorited_type` = '' App\Review
'' AND `user_id` = 80101
) AS `exists`
I'm trying to do it by eager loading:
auth()->user()->load(['favorite', 'ignoring']);
Here is my User model:
public function ignoring()
{
return $this->hasMany(Ignoring::class);
}
public function isIgnoring($userId)
{
return $this->ignoring()
->where(['ignorable_id' => $userId])
->exists();
}
Here is my blade file:
#if (! auth()->user() || ! auth()->user()->isIgnoring($review->user->id))
How can I get rid of these queries by eager loading a boolean? I want to load all the auth()->users() ignoring relationships, so to speak.
Here is what I came up with so far:
In the Controller method:
if (auth()->user()) {
$ignorings = auth()->user()->ignoring()->get();
foreach ($ignorings as $ignoring) {
$ignoringArray[] = $ignoring->ignorable_id;
}
$favoriteReviews = auth()->user()->favorite()->where('favorited_type', 'App\Review')->get();
foreach ($favoriteReviews as $favoriteReview) {
$favoriteReviewArray[] = $favoriteReview->favorited_id;
}
$favoriteReviewComments = auth()->user()->favorite()->where('favorited_type', 'App\ReviewComment')->get();
foreach ($favoriteReviewComments as $favoriteReviewComment) {
$favoriteReviewCommentArray[] = $favoriteReviewComment->favorited_id;
}
}
if (empty($ignoringArray)) {
$reviews = Review::with([
'product',
'user',
'favorites',
'reviewComments',
'reviewComments.favorites'
])
->where('created_at', '>=', Carbon::today()->subDays(7))
->paginate(20);
} elseif (! empty($ignoringArray)) {
$reviews = Review::whereNotIn('user_id', $ignoringArray)
->with('product', 'user', 'favorites', 'reviewComments.favorites')
->with([
'reviewComments' => function ($query) use ($ignoringArray) {
$query->whereNotIn('user_id', $ignoringArray);
}
])
->where('created_at', '>=', Carbon::today()->subDays(7))
->paginate(20);
}
return view('new-reviews.index', [
'reviews' => $reviews,
'favoriteReviewArray' => $favoriteReviewArray ?? null,
'favoriteReviewCommentArray' => $favoriteReviewCommentArray ?? null
]);
In the blade file:
#if(in_array($reviewComment->id, $favoriteReviewCommentArray ?? []))
#if(in_array($review->id, $favoriteReviewArray ?? []))
It's not pretty but it works.
You can easily use Model::withExists('relation') and $model->loadExists('releation') functions.
so you can use if like this
if($model->relation_exists){
//do something
}

Modify data before pagination in CakePhp

I'm trying to create an Api using cakephp.
I generate a json on server and it works fine , but I tired to use pagination and I got a problem.
in the first case I take the image's path and I encode it to base64 and I generate json => works
in the second case I defined the pagination by the limits and the max and I kept the same code but as a result the image field is still the path from the database and it's not encoded
this my code in my controller :
class PilotsController extends AppController {
public $paginate = [
'page' => 1,
'limit' => 5,
'maxLimit' => 5
];
public function initialize() {
parent::initialize();
$this->loadComponent('Paginator');
$this->Auth->allow(['add','edit','delete','view','count']);
}
public function view($id) {
$pilot = $this->Pilots->find()->where(['Pilots.account_id' => $id], [
'contain' => ['Accounts', 'Pilotlogs']
]);
foreach ($pilot as $obj) {
if ($obj->image_pilot!= NULL) {
$image1 = file_get_contents(WWW_ROOT.$obj->image_pilot);
$obj->image_pilot = base64_encode($image1);
}
}
$this->set('pilot', $this->paginate($pilot));
$this->set('_serialize', ['pilot']);
}
}
If I remove the pagination from the code it works fine . Any idea how to fix it ??
I'd suggest to use a result formatter instead, ie Query::formatResults().
So you'll have something like this :
public function view($id) {
$pilot = $this->Pilots->find()
->where(['Pilots.account_id' => $id], [
'contain' => ['Accounts', 'Pilotlogs']]);
->formatResults(function($results) {
return $results->map(function($row) {
$image1 = file_get_contents(WWW_ROOT.$row['image_pilot']);
$row['image_pilot'] = base64_encode($image1);
return $row;
});
});
}
You can simply first paginate the data and then get the array values and after that modify that data as you want. Check this
public function view($id) {
$pilot = $this->Pilots->find()->where(['Pilots.account_id' => $id], [
'contain' => ['Accounts', 'Pilotlogs']
]);
$pilot = $this->paginate($pilot);
$pilot = $pilot->toArray();
foreach ($pilot as $obj) {
if ($obj->image_pilot!= NULL) {
$image1 = file_get_contents(WWW_ROOT.$obj->image_pilot);
$obj->image_pilot = base64_encode($image1);
}
}
$this->set('pilot', $pilot);
$this->set('_serialize', ['pilot']);
}

Laravel 5 collection issue: Where not equal to

I am currently working on a modal where a user can insert an excel file. The task of the system is to upload and/or add a new database record if the records are new or identical to what exists in the database. BUT it also needs a delete function for getting rid of those records where the slug column is not identical to the name column.
At the moment I am using Laravel 5.3, and this is my controller as it is now:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Product;
use App\Http\Requests;
use Illuminate\Support\Facades\DB;
use Input;
use Maatwebsite\Excel\Facades\Excel;
class ProductsController extends Controller {
public function importExcel(Request $request) {
if (Input::hasFile('productFile')) {
$path = Input::file('productFile')->getRealPath();
$checkbox = Input::get('productCheckbox');
$data = Excel::load($path, function($reader) {
})->get();
if (!empty($data) && $data->count()) {
foreach ($data as $key => $value) {
$product = Product::all()->where('slug', $value->slug)->first();
$product_false = Product::all()->where('slug', '!=' , 'name')->get();
if ($product_false !== null){
//delete row if slug does not matches name
dd($product_false);
}
The dd above returns all products, so the collection query is not working properly (see below for the raw SQL that I am trying to run in this collection)
if ($product !== null) {
//update row if exist
$product->name = $value->name;
$product->description = $value->description;
$product->price = $value->price;
$product->save();
} else {
//add new row if not exist
$product = new Product;
$product->slug = $value->slug;
$product->name = $value->name;
$product->description = $value->description;
$product->price = $value->price;
$product->save();
}
}
header("Location: /products");
}
}
}
}
This is the Product model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'slug', 'name', 'description', 'price',
];
}
Here is the PHPMyAdmin raw SQL (which works) that I basically am looking for to use in the collection:
SELECT * FROM `products` WHERE `slug` != `name`
I hope someone can help me out from this pit. I have been sailing the waves of the internet for about 12 hours now just to get this done.
~ nitsuJ
Collections, eloquent and query builder are not the same. Collection provide a bunch of methods to work on arrays, rather then on the database or model.
In collection context whereNot() is not available.
but the same function can be achieved through whereNotIn('key', [value])
collect([
[
'name' => 'foo',
'rank' => 2
],[
'name' => 'bar',
'rank' => 3
],[
'name' => 'foobar',
'rank' => 4
],
])->whereNotIn('rank', [4])
same as where rank not in (4)
Change
$product = Product::all()->where('slug', $value->slug)->first();
$product_false = Product::all()->where('slug', '!=' , 'name')->get();
Into
$product = Product::where('slug', $value->slug)->first();
$product_false = Product::where('slug', '!=' , 'name')->get();
Try this
$product = Product::where('slug', $value->slug)->first();
$product_false = Product::whereRaw('slug != name')->get();
Simple where won't work as it compares products.slug with "name"(string).
I managed to solve it.
$data = Excel::load($path, function($reader) {
$importedSlugs = $data->select(array('slug'))->toArray();
//collection of imported slugs
$collectionOfImportedSlugs = collect($importedSlugs)->flatten()->all();
//get all product slugs
$productSlugs = Product::all()->pluck('slug');
//get all different slugs!
$diffSlugsArray = $productSlugs->diff($collectionOfImportedSlugs)->all();
//dd($diffSlugsArray);
foreach ($diffSlugsArray as $diffSlug) {
$product_false = Product::all()->where('slug', $diffSlug)->first();
echo $product_false->slug . 'has been deleted!';
$product_false->delete();
}
})->get();

Cluttered Controllers in Laravel 5.1

Is there a better way of organizing or writing the below controller method in Laravel 5.1?
I want to keep my Controllers short and sweet. I am using a repository setup as i'm building quite a large application and I want to keep everything organised.
Please advise on the best way to organise the below code.
/**
* Show the form for creating a new resource.
*
* #return Response
*/
public function create(CreateTimesheetRequest $request)
{
$data = $request->only('user_id', 'template_id');
$data['submitted_by'] = Auth::user()->id;
$timesheetId = $this->timesheet->createTimesheet($data);
foreach($request->get('row') as $key => $row)
{
foreach($row as $field => $value)
{
$this->timesheet->saveTimesheetRows([
'timesheet_id' => $timesheetId,
'field_id' => $this->timesheetFields->where('name', $field)->first()->id,
'field_name' => $field,
'field_value' => $value,
'field_key' => $key
]);
}
}
return Redirect::back()->withMessage('The timesheet was successfully created.');
}
All I can suggest - move this:
$data = $request->only('user_id', 'template_id');
$data['submitted_by'] = Auth::user()->id;
... into yours request class. For example, into some data() method:
class CreateTimesheetRequest ... {
...
public function data() {
return array_merge(
$this->only('user_id', 'template_id'),
['submitted_by' => Auth::user()->id]
);
}
}
Also, $this->timesheet->saveTimesheetRows(array) looks more like $this->timesheet->saveTimesheetRow(array) for me - name intends to save multiple rows, but you feed that method only with one row per call.
Maybe, you can refactor that method to smth. like this:
function saveTimesheetRows($timesheetId, $key, $rows, $fieldIds) {
foreach($rows as $field => $value) {
$this->saveTimesheetRow([
'timesheet_id' => $timesheetId,
'field_id' => $fieldIds[$field],
'field_name' => $field,
'field_value' => $value,
'field_key' => $key
]);
}
}
function saveTimesheetRow(array $row) {
// old saveTimesheetRows implementation
}
Upd.
And another tip: use Eloquent's keyBy() method like so:
$keyIDs = $this->timesheetFields->whereIn('name', $fields)->get(["name", "id"])->keyBy("name");
So, finally:
public function create(CreateTimesheetRequest $request) {
$data = $request->data();
$timesheetId = $this->timesheet->createTimesheet($data);
foreach($request->get('row') as $key => $row) {
$this->timesheet->saveTimesheetRows(
$timesheetId,
$key,
$row,
$this->timesheetFields
->whereIn('name', array_keys($row))
->get(["name", "id"])
->keyBy("name") // probably, can be moved into $this->timesheetFields implementation
);
}
return Redirect::back()->withMessage('The timesheet was successfully created.');
}

Categories