I have multiselect option in my website.
<select multiple name="genres[]">
<option value="1">action</option>
<option value="2">adult</option>
<option value="3">advanture</option>
<option value="4">anime</option>
<option value="5">biographic</option>
</select>
Also i have fields in db
shows
id name
1 grey's anatomy
2 the morning show
genres
id name
1 action
2 adult
3 advanture
3 anime
5 biographic
data_show_genres
id show_id genre_id
1 1 4
2 1 2
3 2 1
After Submit button, function do
foreach ($input['genres'] as $genre) {
DataShowGenres::updateOrCreate(
['show_id' => $id, 'genre_id' => $genre]
);
}
So adding work's, but when i try to remove, i mean unselect some data. Old still stays. I can always delete old data for that show but is there any way to do this better?
Edit:
Controller:
public function edit_update(Request $request, $id)
{
$request->validate([
'title' => 'required|min:1|max:300',
'imdb' => 'required|min:0|max:10000000|numeric',
'tvdb' => 'required|min:0|max:10000000|numeric',
'youtube' => 'nullable|url',
'hidden' => 'nullable',
]);
$input = $request->all();
$input['hidden'] = $request->has('hidden') ? 1 : 0;
$input['recommend'] = $request->has('recommend') ? 1 : 0;
if (empty($input["genres"])) {
} else {
foreach ($input['genres'] as $genre) {
$zanr = DataShowGenres::updateOrCreate(
['show_id' => $id, 'genre_id' => $genre]
);
}
}
$serija = Serija::FindOrFail($id_serije);
$serija->title = $input['title'];
$serija->imdb = $input['imdb'];
$serija->tvdb = $input['tvdb'];
$serija->imdb_rating = $input['imdb_rating'];
$serija->tmdb = $input['tmdb'];
$serija->hidden = $input['hidden'];
$serija->youtube = $input['youtube'];
$serija->save();
toast('Edited!', 'success');
return back();
}
Route:
Route::get('/serije/izmeni/{id}/{slug}', 'SerijeController#edit')->where(['id' => '[0-9]+', 'title' => '^[a-z0-9]+(?:-[a-z0-9]+)*$'])->middleware('permission:show_edit');
Route::post('/serije/izmeni/{id}/{slug}', 'SerijeController#edit_update')->where(['id' => '[0-9]+', 'naziv' => '^[a-z0-9]+(?:-[a-z0-9]+)*$'])->middleware('permission:show_edit');
Syncing Associations
You may use the sync method to construct many-to-many
associations. The sync method accepts an array of IDs to place on the
intermediate table. Any IDs that are not in the given array will be
removed from the intermediate table. So, after this operation is
complete, only the IDs in the given array will exist in the
intermediate table:
//...
$show = Show::findOrFail($id);
$show->genres()->sync($input['genres']);
//...
Related
I have the following tables:
users:
------
id
first_name
current_property_id
property_users:
---------------
id
user_id
property_id
chat_user_id
nickname
chat_users:
-----------
id
identity
chat_groups:
------------
id
name
type ['Single' means the group a user is having permutation without repetition for all property users that will serve as their 1:1 conversation (in short everyone is paired with everyone once), 'Group' means more than 2 people can be in the group]
last_messaged_at
chat_group_members:
-------------------
id
chat_group_id
user_id
chat_user_id
I need to make a query to fetch all users (except me) in the property I am in and get the chat_groups I have with them (Type == Single).
I tried doing it PHP way but it takes too long (for 125 users it takes +30s of response)
This is how I am doing it in PHP
$this->currentUser = auth()->user();
//this is Fluent using DB::table and joining property_users, chat_users, and users
$propertyUsers = $this->run(GetPropertyUsersJob::class, [
'property' => $this->property
]);
//this is using simple eloquent getting groups
$chatGroups = $this->run(GetGroupsJob::class, [
'property' => $this->property,
'type' => ChatGroup::TYPE_SINGLE
]);
$chatGroups->load('members.user');
//first level of loop
foreach($propertyUsers as $propertyUser) {
if($this->currentUser->id == $propertyUser->user_id) {
return [];
}
$chatGroupId = '';
$chatGroupName = '';
//second level of loop
foreach($chatGroups as $chatGroup) {
$found = 0;
//third level of loop
foreach($chatGroup->members as $member) {
if($member->user_id == $this->currentUser->id) {
$found++;
}
if($member->user_id == $propertyUser->user_id) {
$found++;
}
}
//just to get this, I need to do nested loop 3x
if($found == 2) {
$chatGroupId = $chatGroup->id;
$chatGroupName = $chatGroup->name;
}
}
$user[] = [
'id' => $propertyUser->user_id,
'first_name' => $propertyUser->user->first_name,
'nickname' => $propertyUser->nickname,
'chat_group_id' => $chatGroupId,
'chat_group_name' => $chatGroupName
];
}
How can I convert this to a query (eloquent/fluent) instead?
#Update:
User model: I am only adding related eager loading
-----------
public function property_users()
{
return $this->hasMany(PropertyUser::class, 'user_id', 'id');
}
PropertyUser model:
-------------------
public function user()
{
return $this->belongsTo(User::class);
}
public function chat_user()
{
return $this->hasOne(ChatUser::class, 'id', 'chat_user_id');
}
ChaUser model:
--------------
public function property_user()
{
return $this->belongsTo(PropertyUser::class, 'id', 'chat_user_id');
}
I use react native through firebase database
I have a database creating products each product has a number
I want to take a number and compare it with the product number
And if there is then I want to get a product
the function its give me my correct name but where i use it on render its not found the variable (name)
getAllContact = async key => {
let barCodeData2 = this.props.navigation.state.params.barcodeData
let self = this;
let contactRef = firebase.database().ref()
contactRef.on("value", dataSnapsot => {
if (dataSnapsot.val()) {
let contactResult = Object.values(dataSnapsot.val())
let contactKey = Object.keys(dataSnapsot.val())
contactKey.forEach((value, key) => {
contactResult[key]["key"] = value
})
self.setState({
fname: contactResult.fname,
data: contactResult.sort((a, b) => {
var nameA = a.barcode
var nameB = barCodeData2
const name = a.fname
console.log(`${nameA} What numers issssssss`);
if (nameA == nameB) {
alert(`${name} ........`)
console.log(`${nameA == nameB}is Equqlqlqlql`);
return name
}
}),
})
}
})
}
render() {
let t=this.state.name
alert(`${t} how?`)// is give Not found
// let d = this.props.navigation.state.params.barcodeData
return (
)
}
When you try such a comparison query i.e.
let ref = firebase.firestore();
ref.collection('zoo')
.where("id", "==", myID)
.get()
.then((snapshot) => {
console.log(snap.empty); //this will denote if results are empty
snapshot.forEach(snap => {
console.log(snap.exists); //alternatively this will also tell you if it is empty
})
})
well what you can do is run query based on you product no and if there's a product you will a product if there's none you will get an empty array.
read firebase documentation on queries
https://firebase.google.com/docs/reference/js/firebase.database.Query
I want to insert many record to database in one action.
In this controller I used foreach for insert to database, but just the last record inserts to database, I don't know why. I want to insert all the record to database.
My controller:
if (isset($_POST['month'])) {
$name = $_POST['month'];
$price = $_POST['Request'];
$i = 0;
foreach ($name as $month) {
$model->month = $month;
$model->price = $price['price'];
$model->save(false);
$i++;
}
$pay_info = [
'cost' => $price['price'],
'title' => 'title'];
return $this->render('payment', ['pay_info' => $pay_info]);
}
A simple way is based on the fact you should create a new model in you foreach for each instance you want save
(your controller code is not complete so i can't know your model )
if (isset($_POST['month'])) {
$name = $_POST['month'];
$price = $_POST['Request'];
$i = 0;
foreach ($name as $month) {
$model = new YourModel(); /* here */
$model->month = $month;
$model->price = $price['price'];
$model->save(false);
$i++;
}
$pay_info = [
'cost' => $price['price'],
'title' => 'title'];
return $this->render('payment', ['pay_info' => $pay_info]);
}
but i siggest to explore also the batchInsert command http://www.yiiframework.com/doc-2.0/yii-db-command.html#batchInsert()-detail
For batch insert you can build an asscociative array with month and price eg:
$my_array= [
['January', 30],
['Febrary', 20],
['March', 25],
]
\Yii::$app->db->createCommand()->
batchInsert('Your_table_name', ['month', 'price'],$my_array)->execute();
I am having a bit of a headache with a thing (I know something like has been asked before, but I'm pretty sure it's not quite the same thing).
To the point:
I have a View with a Telerik grid. On that grid I show some stuff from the model that I pass to the View BUT I want in the final column to put a CheckBox that is checked/unchecked based on some things in the Controller (the checks have nothing to do with the model that is being passed). In my ActionResult function that takes care of the View I store some Boolean values in the ViewData, and then I set the isChecked value in the CheckBox based on the values stored in the ViewData.
The code for the ActionResult is as follows:
[SecureThis(Roles = "User")]
public ActionResult Index()
{
//get bucket ids
var buckets = db.Buckets.ToList();
int i=1;
string cb = "checkbox" + i.ToString();
foreach (Bucket b in buckets)
{
var payByInvoice = db.PaymentOptions.Where(p => p.BucketId == b.Id).Select(p => p.CanPayByInvoice).SingleOrDefault();
if (payByInvoice == (int)PayByInvoiceState.Accepted)
ViewData["checkbox" + i.ToString()] = true;
else ViewData["checkbox" + i.ToString()] = false;
i++;
cb = "checkbox" + i.ToString();
}
return View(db.Buckets);
}
And the grid that should show all the stuff is this:
#{
int i=1;
string cb = "checkbox" + i.ToString();
}
#(Html.Telerik().Grid(Model)
.Name("BucketsGrid")
.DataKeys(keys => keys.Add(bucket => bucket.Id))
.Columns(
columns =>
{
columns.Template(model => ViewData[model.Id.ToString()])
.HeaderTemplate(
#<b>#Strings.Title_Customer</b>
);
columns.Bound(model => model.CreditFacility);
columns.Bound(model => model.Minimum);
columns.Bound(model => model.RefillLevel);
columns.Bound(model => model.NotificationEmail);
columns.Bound(model => model.NotificationSms);
columns.Template(model => Html.ActionLink(Strings.Edit, "Edit", new { id = model.Id }));
columns.Template(model => Html.ActionLink(Strings.NotificationOptions, "Bucket", "NotificationOptions", new { id = model.Id }, null));
columns.Template(model => Html.ActionLink("Refill", "Refill", "Payment", new { id = model.Id }, null));
columns.Template(model => Html.ActionLink(Strings.Details, "Details", new { id = model.Id }));
columns.Template(model => Html.ActionLink(Strings.Delete, "Delete", new { id = model.Id }));
columns.Template(model => Html.CheckBox("invoice", (Boolean)ViewData[#cb])).HeaderTemplate("Invoice Option");
#i++;
#cb = "checkbox" + i.ToString();
}
)
.Pageable(paging =>
paging.Enabled(true)
.PageSize(UserSettings.GridPageSize)
.Style(GridPagerStyles.NextPrevious)
.Position(GridPagerPosition.Bottom)
)
.Sortable()
.Scrollable()
.Resizable(resize=> resize.Columns(true))
)
The problem with this whole thing is that the checkboxes remain unchecked, no matter the data stored in the ViewData. I went with the debugger and the values are se accordingly in the ViewData, but for some reason (that I cannot yet tell) the checkboxes still remain unchcked.
Any ideas on this matter would be much appreciated.
I have found out the problem of all this. As expected, it was my own doing (or so to say). The problem was that I incremented the #i variable inside the Telerik grid declaration, thinking that it would happen for all the rows in the grid, but that thing is only triggered once. Hence, the ViewData[#cb] value would always have the 2nd value set in the Controller (which in my case was false) and all the checkboxes would then be unchecked.
The fix:
I used the ViewBag and set it up with a Dictionary<Guid, bool> to hold my values, and iterate through it using the model.Id property. For anyone who might be interested I'll post the code below.
Controller:
ViewBag.Dict = new Dictionary<Guid, bool>();
Dictionary<Guid, bool> dict = new Dictionary<Guid, bool>();
foreach (Bucket b in buckets)
{
var payByInvoice = db.PaymentOptions.Where(p => p.BucketId == b.Id).Select(p => p.CanPayByInvoice).SingleOrDefault();
if (payByInvoice != (int)PayByInvoiceState.Accepted)
{
dict.Add(b.Id, false);
}
if (payByInvoice == (int)PayByInvoiceState.Accepted)
{
dict.Add(b.Id, true);
}
}
ViewBag.Dict = dict;
View:
columns.Template(model => Html.CheckBox("invoice", (bool)ViewBag.Dict[model.Id])).HeaderTemplate("Invoice option");
I have a question about formatting the friendly URL for category and subcategory and getting the matching products. I am using PrestaShop 1.5.2.0
Let's say we have a structure like this:
Category 1
Spare Parts
Accessories
Category 2
Chips
Accessories
I want to display the link like this: /category-1/accessories and to display the products from category 1->accessories. How can I achieve this?
The current behavior is when I click on accessories, being in category 1, the link is /accessories and the products that are displayed belong from both /category-1/accessories and /category-2/accessories
Thanks!
This question was answered on the PrestaShop forum.
You can find it here http://www.prestashop.com/forums/topic/220017-category-subcategory-url/
The solution - add this changes to the fallowing classes
CLASSES/Dispatcher.php
'rule' => '{categories:/}{id}-{rewrite}/',
'categories' => array('regexp' => '[/_a-zA-Z0-9-\pL]*'),
CLASSES/Link.php
$cats = array();
foreach ($category->getParentsCategories() as $cat)
if (!in_array($cat['id_category'], array(1, 2, $category->id)))//remove root, home and current category from the URL
$cats[] = $cat['link_rewrite'];
$params['categories'] = implode('/', array_reverse($cats));
The above code is valid for the older versions, but it would not work for the newer/latest version. I updated the same solution for the newer version (1.7.7.4.), it might be used for others.
change CLASSES/Dispatcher.php
at about line 55 in the above file copy paste
public $default_routes = [
'category_rule' => [
'controller' => 'category',
**/** added 1 line below*/
'rule' => '{category:/}{id}-{rewrite}/',
/** commented 1line below*/
/**'rule' => '{id}-{rewrite}',*/
'keywords' => [
'id' => ['regexp' => '[0-9]+', 'param' => 'id_category'],
/*** added 1 line below*/
'category' => ['regexp' => '[_a-zA-Z0-9-\pL]*'],
'rewrite' => ['regexp' => self::REWRITE_PATTERN],
'meta_keywords' => ['regexp' => '[_a-zA-Z0-9-\pL]*'],
'meta_title' => ['regexp' => '[_a-zA-Z0-9-\pL]*'],**
],
],
In the file classes/link.php find the function getCategoryLink and replace it with the function code below
/**
* Create a link to a category.
*
* #param mixed $category Category object (can be an ID category, but deprecated)
* #param string $alias
* #param int $idLang
* #param string $selectedFilters Url parameter to autocheck filters of the module blocklayered
*
* #return string
*/
public function getCategoryLink(
$category,
$alias = null,
$idLang = null,
$selectedFilters = null,
$idShop = null,
$relativeProtocol = false
) {
$dispatcher = Dispatcher::getInstance();
if (!$idLang) {
$idLang = Context::getContext()->language->id;
}
$url = $this->getBaseLink($idShop, null, $relativeProtocol) . $this->getLangLink($idLang, null, $idShop);
// Set available keywords
$params = [];
if (!is_object($category)) {
$params['id'] = $category;
} else {
$params['id'] = $category->id;
}
// Selected filters is used by the module ps_facetedsearch
$selectedFilters = null === $selectedFilters ? '' : $selectedFilters;
if (empty($selectedFilters)) {
$rule = 'category_rule';
} else {
$rule = 'layered_rule';
$params['selected_filters'] = $selectedFilters;
}
if (!$alias) {
$category = $this->getCategoryObject($category, $idLang);
}
$params['rewrite'] = (!$alias) ? $category->link_rewrite : $alias;
if ($dispatcher->hasKeyword($rule, $idLang, 'meta_keywords', $idShop)) {
$category = $this->getCategoryObject($category, $idLang);
$params['meta_keywords'] = Tools::str2url($category->getFieldByLang('meta_keywords'));
}
if ($dispatcher->hasKeyword($rule, $idLang, 'meta_title', $idShop)) {
$category = $this->getCategoryObject($category, $idLang);
$params['meta_title'] = Tools::str2url($category->getFieldByLang('meta_title'));
}
if ($category !='var'){
$category = $this->getCategoryObject($category, $idLang);
$pcategory= new Category($category->id_parent, $idLang);
if($category->id_parent!=1 && $category->id_parent!=2){
$params['category'] = $pcategory->link_rewrite;
//append the categoryID with its name
$params['category'] = $category->id_parent . '-'. $params['category'];
}
}
return $url . Dispatcher::getInstance()->createUrl($rule, $idLang, $params, $this->allow, '', $idShop);
}
in the same file classes/link.php update if condition as follows at line 218 in the code for (function getProductLink)
if ($dispatcher->hasKeyword('product_rule', $idLang, 'categories', $idShop)) {
$product = $this->getProductObject($product, $idLang, $idShop);
$params['category'] = (!$category) ? $product->category : $category;
$cats = [];
foreach ($product->getParentCategories($idLang) as $cat) {
if (!in_array($cat['id_category'], Link::$category_disable_rewrite)) {
//remove root and home category from the URL
//commented the line below
//$cats[] = $cat['link_rewrite'];
//replaced the above line with the line below to append the category ID in the products link
$cats[] = $cat['id_category'].'-'.$cat['link_rewrite'];
}
}
$params['categories'] = implode('/', $cats);
}
I happened to be using the prestashop version 1.7.7.4. You can see this solution working on my site https://jinbaba.pk
Also after making the above changes in the code files, do not forget to update shopparameters-->SEO&URL Setting, change the category and product routes as follows (if they are not already like this)
"Route to category" = {category:/}{id}-{rewrite}
"Route to product" = {categories:/}{id}{-:id_product_attribute}-{rewrite}{-:ean13}.html
Just a suggestion for SEO : You do not need to remove category ID and product ID from the URL. They have minimal or no impact on SEO.
also the about solution will work for 2 level nesting e.g.
yourdomain.com/category-1/category-2/1-product.html
do not create more nesting of categories in your catalog. If you plan to do create deeper nesting your site you will need to update this solution. However, for SEO deep nesting is not recommended.