Laravel subquery other table - laravel

How can I get data from another table?
// ServiceComplexController
public function index(Store $store): JsonResponse
{
/* #var User $user */
$user = auth()->user();
$this->listQuery = $user->store->serviceComplexes()->getQuery();
return response()->json([
'data' => StoreServiceComplexResource::collection($this->listQuery->get()),
]);
}
// StoreServiceComplexResource
public function toArray($request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'description' => $this->description,
'base_service_ids' => $this->base_service_ids,
'more_service_ids' => $this->more_service_ids,
];
}
// Dump $this->listQuery->get()
array (
0 =>
array (
'id' => 3,
'name' => 'Complex 1',
'description' => 'Desc complex 1',
'base_service_ids' =>
array (
0 => 1,
1 => 2,
),
'more_service_ids' =>
array (
0 => 10,
),
),
)
How to get base services from another table(services) based on field "base_service_ids" and "more_service_ids" and add them to response ?
Is it possible to give this data also through Collection Resource ? For example
// StoreServiceComplexResource
public function toArray($request): array
{
return [
...
'service' => [] //StoreServiceResource::collection() ....
...
];
}

Related

Add order Laravel

I am adding order to database. It works like this: When ordering is clicked, the order is created in the Order table, at the same time the product items are also added to the OrderItem table, via the order_id foreign key. But I don't know how to get the order_id, because it is added at the same time, and the Order id is increments.
public function save(array $data, int $id = null){
$idCurrent = Auth::id();
$orderItems = $data['orderItems'];
//add to Order
Order::updateOrCreate(
[
'id' => $id
],
[
'user_id' => $idCurrent,
'shipping_fee' => $data['shipping_fee'],
'total' => $data['total'],
'payment' => $data['payment'],
'status_id' => 1,
]
);
//add to OrderItem
foreach($orderItems as $item){
OrderItem::Create([
'order_id' => 222, //=> ?????????????
'product_id' => $item -> product_id,
'quantity' => $item->quantity,
]);
}
return true;
}
$order = Order::updateOrCreate(
[
'id' => $id
],
[
'user_id' => $idCurrent,
'shipping_fee' => $data['shipping_fee'],
'total' => $data['total'],
'payment' => $data['payment'],
'status_id' => 1,
]
);
//add to OrderItem
foreach($orderItems as $item){
OrderItem::Create([
'order_id' =>$order->id
'product_id' => $item -> product_id,
'quantity' => $item->quantity,
]);
}
return true;
Avoid multiple call to databases.
When you create order with
$order = Order::updateOrCreate(
[
'id' => $id
],
[
'user_id' => $idCurrent,
'shipping_fee' => $data['shipping_fee'],
'total' => $data['total'],
'payment' => $data['payment'],
'status_id' => 1,
]
);
next you should is to send just one request to database with
// create batch array
$insertOrderItems = [];
foreach($orderItems as $item){
$insertOrderItems[] = [
'product_id' => $item->product_id,
'quantity' => $item->quantity,
];
}
// insert all at once in batch mode making just one call to database
$order->orderItems()->create($insertOrderItems);
Presuming you have sorted relations in Order and OrderItem models.

How to access nested item in Rule::requiredIf() validation

I'm trying to validate an array inside a custom Request. The rule evaluates to required if two conditions are met:
attribute3 is true
another column from the same array is true
Here's what I'm doing:
public function rules()
{
return [
'attribute1' => 'required',
'attribute2' => 'required',
'attribute3' => 'required',
...
'attribute10.*.column3' => Rule::requiredIf(fn() => $this->attribute3), // <- array
'attribute10.*.column4' => Rule::requiredIf(fn() => $this->attribute3), // <- array
'attribute10.*.column5' => Rule::requiredIf(fn() => $this->attribute3), // <- array
];
}
What I really need is this:
'attribute10.*.column4' => Rule::requiredIf(fn($item <- magically hint this currently looped item) => $this->attribute3 && $item->column2 <- so I can use it like this), // <- array
Assuming the incoming request has a structure like the following:
[
'attribute1' => 1,
'attribute2' => 0,
'attribute3' => 1,
'attribute10' => [
[
'column1' => 1,
'column2' => 1,
'column3' => 0,
],
[
'column1' => 0,
'column2' => 1,
'column3' => 0,
],
],
]
You can set the rules array to a variable, and then loop over the attribute10 field array elements and merge each rule on the rules variable. Then you'll have access to the other elements on the nested array.
Ie:
public function rules()
{
$rules = [
'attribute1' => 'required',
'attribute2' => 'required',
'attribute3' => 'required',
];
foreach($this->attribute10 as $key => $item) {
array_merge($rules, [
'attribute10.'.$key.'.column2' => Rule::requiredIf($this->attribute3 && $item['column1']),
'attribute10.'.$key.'.column3' => Rule::requiredIf($this->attribute3 && $item['column2']),
//...
]);
}
return $rules;
}

How to insert all json file data in database?

I have JSON file and have data in it. I want to import all data in the database through DB seeders. I am getting an error Trying to get property name of non-object. I have multiple data how I can insert in the database?
public function run()
{
$json = File::get("public/kmz/WASASubdivisions.geojson");
$data = json_decode($json);
// dd($data);
foreach ($data as $obj){
Regions::create(array(
'name' => $obj[0]->Name,
'description' => $obj[0]->description,
'altitudeMode' => $obj[0]->altitudeMode,
'Town' => $obj[0]->Town,
'AC' => $obj[0]->AC,
'No_of_TW' => $obj[0]->No_of_TW,
'No' => $obj[0]->No,
'DC'=> $obj[0]->DC,
'HH_2017' => $obj[0]->HH_2017,
'FID' => $obj[0]->FID,
'Area_ha' => $obj[0]->Area_ha,
'Field_1' => $obj[0]->Field_1,
'Pop_Dens' => $obj[0]->Pop_Dens,
'Id' => $obj[0]->Id,
'Pop_2017' => $obj[0]->Pop_2017,
'Area_Sq'=> $obj[0]->Area_Sq,
));
}
}
Sample Json Format
31 => {#837
+"type": "Feature"
+"properties": {#838
+"Name": "Gujjar Pura"
+"description": null
+"altitudeMode": "clampToGround"
+"Town": "Shalimar Town"
+"AC": "31"
+"No_of_TW": "11"
+"No": "13"
+"DC": "38"
+"HH_2017": "30478"
+"FID": "31"
+"Area_ha": "648.327"
+"Field_1": "Gujjar Pura"
+"Pop_Dens": "54063.141167"
+"Id": "0"
+"Pop_2017": "196619"
+"Area_Sq": "3.63684"
}
+"geometry": {#839
+"type": "MultiPolygon"
+"coordinates": array:1 [
0 => array:1 [
0 => array:169 [ …169]
]
]
}
}
Let's support I have a model Post and I want to save additional data in JSON format in the posts table. In that case, we can use property $casts in Laravel. Which will cast our field value to whatever we gave.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
protected $table='posts';
protected $fillable = ['user_id', 'title', 'short_description', 'description', 'status', 'json_data'];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'json_data' => 'array',
];
}
Now we want to save data something like this
$data = [
'user_id' => 1,
'title' => 'abc',
'short_description' => 'test',
'description' => 'test',
'status' => true,
'json_data' => [
'additional_info' => '',
'post_image' => '',
...
],
];
$item = new Post;
$item->fill($data)->save();
This will save your json_data array values to JSON in the database. But when you will get data from the database it will convert that to array automatically.
For reference read this
since i am not a big fan of processing the json as a object
So the json_decode will accept the second arg so
$json = File::get("public/kmz/WASASubdivisions.geojson");
$data = json_decode($json,true);
dd($data);
foreach ($data as $obj)
{
Regions::create(array(
'name' => $obj['Name'],
'description' => $obj['description'],
'altitudeMode' => $obj['altitudeMode'],
'Town' => $obj['Town'],
'AC' => $obj['AC'],
'No_of_TW' => $obj['No_of_TW'],
'No' => $obj['No'],
'DC'=> $obj['DC'],
'HH_2017' => $obj['HH_2017'],
'FID' => $obj['FID'],
'Area_ha' => $obj['Area_ha'],
'Field_1' => $obj['Field_1'],
'Pop_Dens' => $obj['Pop_Dens'],
'Id' => $obj['Id'],
'Pop_2017' => $obj['Pop_2017'],
'Area_Sq'=> $obj['Area_Sq'],
));
}
Can You Post the dd() result and fileds sets of the table
public function run()
{
$json = File::get("public/kmz/WASASubdivisions.geojson");
$data = json_decode($json);
dd($data);
foreach ($data as $obj){
Regions::create(array(
'name' => $obj->Name,
'description' => $obj->description,
'altitudeMode' => $obj->altitudeMode,
'Town' => $obj->Town,
'AC' => $obj->AC,
'No_of_TW' => $obj->No_of_TW,
'No' => $obj->No,
'DC'=> $obj->DC,
'HH_2017' => $obj->HH_2017,
'FID' => $obj->FID,
'Area_ha' => $obj->Area_ha,
'Field_1' => $obj->Field_1,
'Pop_Dens' => $obj->Pop_Dens,
'Id' => $obj->Id,
'Pop_2017' => $obj->Pop_2017,
'Area_Sq'=> $obj->Area_Sq,
));
}
}
The attributes are under the properties key, but you're referencing them from the root of the object. e.g. $obj[0]->Name should be $obj[0]->properties->Name, etc.

CakePHP 3 validation Range not working - i get no error message

I am trying to validate my Entity but it wont work. Only the isUnique works. But noEmpty, minLength and range are ignored. I would like to get these messages displayed too. What am I doing wrong? Or does the theruleschecker override the validation?
CitiesTable.php
<?php
namespace App\Model\Table;
use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;
class CitiesTable extends Table
{
public function initialize(array $config)
{
parent::initialize($config);
$this->table('cities');
$this->displayField('name');
$this->primaryKey('id');
$this->addBehavior('Timestamp');
$this->hasMany('Fields', [
'foreignKey' => 'city_id'
]);
}
public function validationDefault(Validator $validator)
{
$validator
->integer('id')
->allowEmpty('id', 'create');
$validator
->requirePresence('name', 'create')
->notEmpty('name')
->add('name', [
'length' => [
'rule' => ['minLength', 15],
'message' => 'Titles need to be at least 10 characters long',
]
])
->lengthBetween('username', [15, 20])
->minLength('name',15,'TestMessage');
$validator
->integer('fields_per_pieces_x')
->range('fields_per_pieces_x',[1,5],'TeestMessage')
->requirePresence('fields_per_pieces_x', 'create')
->notEmpty('fields_per_pieces_x');
$validator
->integer('fields_per_pieces_y')
->requirePresence('fields_per_pieces_y', 'create')
->notEmpty('fields_per_pieces_y');
$validator
->integer('field_pieces')
->requirePresence('field_pieces', 'create')
->notEmpty('field_pieces');
return $validator;
}
public function buildRules(RulesChecker $rules){
$rules->add($rules->isUnique(['name']));
return $rules;
}
}
and this:
$map['city'] = $this->generateCity('Kantosddd', -2, -2, -4);
pr($map);
die();
shows the following:
Array
(
[city] => App\Model\Entity\City Object
(
[name] => Kantosddd
[fields_per_pieces_x] => -2
[fields_per_pieces_y] => -2
[field_pieces] => -4
[[new]] => 1
[[accessible]] => Array
(
[*] => 1
)
[[dirty]] => Array
(
[name] => 1
[fields_per_pieces_x] => 1
[fields_per_pieces_y] => 1
[field_pieces] => 1
)
[[original]] => Array
(
)
[[virtual]] => Array
(
[get] => Array
(
[0] => fields_per_pieces_all
[1] => fields_in_x
[2] => fields_in_y
[3] => count_of_all_fields
)
)
[[errors]] => Array
(
[name] => Array
(
[_isUnique] => This value is already in use
)
)
[[invalid]] => Array
(
[name] => Kantosddd
)
[[repository]] => Cities
)
)
generateCity Function
function generateCity(string $name, int $fieldsPerPiecesX, int $fieldsPerPiecesY, int $fieldPieces ): City
{
$citiesTable = TableRegistry::get('Cities');
$city = $citiesTable->newEntity();
$city->set('name', $name);
$city->set('fields_per_pieces_x', $fieldsPerPiecesX);
$city->set('fields_per_pieces_y', $fieldsPerPiecesY);
$city->set('field_pieces', $fieldPieces);
if(!$citiesTable->save($city)){
foreach($city->errors() as $fields => $field){
foreach($field as $rule => $message){
$this->Flash->error($fields.": ".$message);
}
}
}
return $city;
}
Thank you for the help :)
When you use the set function, validation is not done, only rules. Try this:
$city = $citiesTable->newEntity([
'name' => $name,
'fields_per_pieces_x' => $fieldsPerPiecesX,
'fields_per_pieces_y' => $fieldsPerPiecesY,
'field_pieces' => $fieldPieces
]);
Or, equivalently,
$city = $citiesTable->newEntity();
$city = $citiesTable->patchEntity($city, [
'name' => $name,
'fields_per_pieces_x' => $fieldsPerPiecesX,
'fields_per_pieces_y' => $fieldsPerPiecesY,
'field_pieces' => $fieldPieces
]);

Magento 1.9: How to create order programmatically

I found similar topics, but they are not up to date.
I have to generate around 1000 orders with random products. I found good article about creating orders http://inchoo.net/magento/programmatically-create-order-in-magento/ but it's kinda old and it's not working on version 1.9.
I get following errors:
array (size=5)
0 => string 'Please specify the product's option(s).' (length=39)
1 => string 'Please specify the product's option(s).' (length=39)
2 => string 'Please specify the product's option(s).' (length=39)
3 => string 'Please specify the product's option(s).' (length=39)
4 => string 'Please specify the product's option(s).' (length=39)
#0 E:\xampp\htdocs\magento\app\code\core\Mage\Adminhtml\Model\Sales\Order\Create.php(1631): Mage::throwException('')
#1 E:\xampp\htdocs\magento\app\code\core\Mage\Adminhtml\Model\Sales\Order\Create.php(1523): Mage_Adminhtml_Model_Sales_Order_Create->_validate()
As you can see in my create method I add options to product, so why do I get this errors?
Here is my class
class MyNamespace_MyModule_Model_Generate_Sample {
protected $orderData;
protected $product;
public function run()
{
//$customer is a random customer object
$product = Mage::getModel('catalog/product')->load(342);
$this->product = $product;
$this->orderData = array(
'session' => array(
'customer_id' => $customer->getId(),
'store_id' => Mage::app()->getStore('default')->getId(),
),
'payment' => array(
'method' => 'checkmo',
),
'add_products' =>array(
$product->getId() => array('qty' => 1),
),
'order' => array(
'currency' => 'USD',
'account' => array(
'group_id' => $customer->getGroupId(),
'email' => $customer->getEmail()
),
'billing_address' => array(
'customer_address_id' => $customer->getCustomerAddressId(),
'prefix' => '',
'firstname' => $customer->getFirstname(),
'middlename' => '',
'lastname' => $customer->getLastname(),
'suffix' => '',
'company' => '',
'street' => array($customer->getStreet(),''),
'city' => $customer->getCity(),
'country_id' => $customer->getCountryId(),
'region' => '',
'region_id' => $customer->getRegionId(),
'postcode' => $customer->getPostcode(),
'telephone' => $customer->getTelephone(),
'fax' => '',
),
'shipping_address' => array(
'customer_address_id' => $customer->getCustomerAddressId(),
'prefix' => '',
'firstname' => $customer->getFirstname(),
'middlename' => '',
'lastname' => $customer->getLastname(),
'suffix' => '',
'company' => '',
'street' => array($customer->getStreet(),''),
'city' => $customer->getCity(),
'country_id' => $customer->getCountryId(),
'region' => '',
'region_id' => $customer->getRegionId(),
'postcode' => $customer->getPostcode(),
'telephone' => $customer->getTelephone(),
'fax' => '',
),
'shipping_method' => 'flatrate_flatrate',
'comment' => array(
'customer_note' => 'This order has been programmatically created via import script.',
),
'send_confirmation' => 0
),
);
$this->create();
}
/**
* Creates order
*/
public function create()
{
$orderData = $this->orderData;
if (!empty($orderData)) {
$this->_initSession($orderData['session']);
$this->_processQuote($orderData);
if (!empty($orderData['payment'])) {
$this->_getOrderCreateModel()->setPaymentData($orderData['payment']);
$this->_getOrderCreateModel()->getQuote()->getPayment()->addData($orderData['payment']);
}
$item = $this->_getOrderCreateModel()->getQuote()->getItemByProduct($this->product);
foreach($this->product->getAttributes() as $option)
{
if ($option->getIsVisibleOnFront()) {
$item->addOption(new Varien_Object(
array(
'product' => $this->product,
'code' => $option->getAttributeCode(),
'value' => $option->getFrontend()->getValue($this->product)
)
));;
}
}
Mage::app()->getStore()->setConfig(Mage_Sales_Model_Order::XML_PATH_EMAIL_ENABLED, "0");
$_order = $this->_getOrderCreateModel()
->importPostData($orderData['order'])
->createOrder();
$this->_getSession()->clear();
Mage::unregister('rule_data');
return $_order;
}
return null;
}
protected function _processQuote($data = array())
{
/* Saving order data */
if (!empty($data['order'])) {
$this->_getOrderCreateModel()->importPostData($data['order']);
}
$this->_getOrderCreateModel()->getBillingAddress();
$this->_getOrderCreateModel()->setShippingAsBilling(true);
/* Just like adding products from Magento admin grid */
if (!empty($data['add_products'])) {
$this->_getOrderCreateModel()->addProducts($data['add_products']);
}
/* Collect shipping rates */
$this->_getOrderCreateModel()->collectShippingRates();
/* Add payment data */
if (!empty($data['payment'])) {
$this->_getOrderCreateModel()->getQuote()->getPayment()->addData($data['payment']);
}
$this->_getOrderCreateModel()
->initRuleData()
->saveQuote();
if (!empty($data['payment'])) {
$this->_getOrderCreateModel()->getQuote()->getPayment()->addData($data['payment']);
}
return $this;
}
/**
* Retrieve order create model
*
* #return Mage_Adminhtml_Model_Sales_Order_Create
*/
protected function _getOrderCreateModel()
{
return Mage::getSingleton('adminhtml/sales_order_create');
}
/**
* Retrieve session object
*
* #return Mage_Adminhtml_Model_Session_Quote
*/
protected function _getSession()
{
return Mage::getSingleton('adminhtml/session_quote');
}
/**
* Initialize order creation session data
*
* #param array $data
* #return Mage_Adminhtml_Sales_Order_CreateController
*/
protected function _initSession($data)
{
/* Get/identify customer */
if (!empty($data['customer_id'])) {
$this->_getSession()->setCustomerId((int) $data['customer_id']);
}
/* Get/identify store */
if (!empty($data['store_id'])) {
$this->_getSession()->setStoreId((int) $data['store_id']);
}
return $this;
}
}
Thanks for any help

Resources