Laravel 5.7 many to many sync() not working - laravel

I have a intermediary table in which I want to save sbj_type_id and difficulty_level_id so I have setup this:
$difficulty_level = DifficultyLevel::find(5);
if ($difficulty_level->sbj_types()->sync($request->hard, false)) {
dd('ok');
}
else {
dd('not ok');
}
Here is my DifficultyLevel.php:
public function sbj_types() {
return $this->belongsToMany('App\SbjType');
}
and here is my SbjType.php:
public function difficulty_levels() {
return $this->hasMany('App\DifficultyLevel');
}
In the above code I have dd('ok') it's returning ok but the database table is empty.

Try to change
return $this->hasMany('App\DifficultyLevel');
to
return $this->belongsToMany('App\DifficultyLevel');
The sync() method takes an array with the id's of the records you want to sync as argument to which you can optionally add intermediate table values. While sync($request->hard, false) doesn't seem to throw an exception in your case, I don't see how this would work.
Try for example:
$difficulty_level->sbj_types()->sync([1,2,3]);
where 1,2,3 are the id's of the sbj_types.
You can read more about syncing here.

Related

Api platform add or update

Good afternoon I am adding data in via POST method in PLATFORM API can I make this method work like adding or updating data.
So that when the data is already there for the object, it will simply update the pinOrder field.
My input:
{
"chat": "/api/chats/01FVKRYXMMTHKJ2EZB02F4FZ3Z",
"pinOrder": 3
}
Insert or update (upsert) is not available in Api Platform. However, you can achieve this behavior with a custom (or decorated) Data Persister.
https://api-platform.com/docs/core/data-persisters/
In the persist method of the data persister you could manually check if an item matching your criteria does already exist and, if yes, update this one instead of persisting a new one.
You can use PRE_WRITE event. For exemple, an order item quantity.
public static function getSubscribedEvents(): array
{
return [
KernelEvents::VIEW => [
'updateExistingItemQuantity', EventPriorities::PRE_WRITE,
],
];
}
public function updateExistingItemQuantity(
ViewEvent $event
): void {
$item = $event->getControllerResult();
$method = $event->getRequest()->getMethod();
if (!$item instanceof MyItemObject || Request::METHOD_POST !== $method) {
return;
}
// find duplicateItem
if ($duplicateItem) {
$duplicateItem->setQuantity("UPDATED QUANTITY");
// save $duplicateItem
$event->setControllerResult($duplicateItem);
}
}

Querying single database row using rxjava2

I am using rxjava2 for the first time on an Android project, and am doing SQL queries on a background thread.
However I am having trouble figuring out the best way to do a simple SQL query, and being able to handle the case where the record may or may not exist. Here is the code I am using:
public Observable<Record> createRecordObservable(int id) {
Callable<Record> callback = new Callable<Record>() {
#Override
public Record call() throws Exception {
// do the actual sql stuff, e.g.
// select * from Record where id = ?
return record;
}
};
return Observable.fromCallable(callback).subscribeOn(Schedulers.computation());
}
This works well when there is a record present. But in the case of a non-existent record matching the id, it treats it like an error. Apparently this is because rxjava2 doesn't allow the Callable to return a null.
Obviously I don't really want this. An error should be only if the database failed or something, whereas a empty result is perfectly valid. I read somewhere that one possible solution is wrapping Record in a Java 8 Optional, but my project is not Java 8, and anyway that solution seems a bit ugly.
This is surely such a common, everyday task that I'm sure there must be a simple and easy solution, but I couldn't find one so far. What is the recommended pattern to use here?
Your use case seems appropriate for the RxJava2 new Observable type Maybe, which emit 1 or 0 items.
Maybe.fromCallable will treat returned null as no items emitted.
You can see this discussion regarding nulls with RxJava2, I guess that there is no many choices but using Optional alike in other cases where you need nulls/empty values.
Thanks to #yosriz, I have it working with Maybe. Since I can't put code in comments, I'll post a complete answer here:
Instead of Observable, use Maybe like this:
public Maybe<Record> lookupRecord(int id) {
Callable<Record> callback = new Callable<Record>() {
#Override
public Record call() throws Exception {
// do the actual sql stuff, e.g.
// select * from Record where id = ?
return record;
}
};
return Maybe.fromCallable(callback).subscribeOn(Schedulers.computation());
}
The good thing is the returned record is allowed to be null. To detect which situation occurred in the subscriber, the code is like this:
lookupRecord(id)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Record>() {
#Override
public void accept(Record r) {
// record was loaded OK
}
}, new Consumer<Throwable>() {
#Override
public void accept(Throwable throwable) {
// there was an error
}
}, new Action() {
#Override
public void run() {
// there was an empty result
}
});

Single transaction on multiple model function with CodeIgniter

I need to insert into 2 tables if anything goes wrong while inserting in any of the table I want to rollback commited queries.
I wrote queries inside controller
for example:
$this->db->trans_start();
$this->db->insert_batch('market_users_mapping', $marketData);
$this->db->insert_batch('maincategory_users_mapping', $maincategoryData);
$this->db->trans_complete();
if ($this->db->trans_status() === FALSE) {
throw error
}
This works perfectly. But I think it's not good practice to write queries inside controller. So I did this, called model function and I wrote those insert_batch queries in respective model function.
$this->db->trans_start();
$this->maincategory_model->function_name()
$this->market_model->function_name();
$this->db->trans_complete();
if ($this->db->trans_status() === FALSE) {
throw error
`enter code here`
}
but this didnt work as expected
You changed places of queries in those examples regarding names in case it matters. I think that you can't have tied transactions between different methods (your second example). But you can and should set your DB related code to model.
So make those queries in model:
// controller code
$this->db->trans_start();
$this->maincategory_model->first_function($maincategoryData);
$this->market_model->second_function($marketData);
$this->db->trans_complete();
if ($this->db->trans_status() === FALSE) {
throw error
`enter code here`
}
// Maincategory_model code
public function first_function($maincategoryData)
{
return $this->db->insert_batch('maincategory_users_mapping', $maincategoryData);
}
// Market_model code
public function second_function($marketData)
{
return $this->db->insert_batch('market_users_mapping', $marketData);
}
First shift your db related operation in module and then start transaction.
Sample code in module,
First module :
function insert_data_market_maincategory($marketData,$maincategoryData)
{
$status = TRUE;
$this->db->trans_start();
$this->db->insert_batch('market_users_mapping', $marketData);
$this->second_module_name->maincategoryData($maincategoryData)
$this->db->trans_complete();
if ($this->db->trans_status() === FALSE) {
$status = FALSE;
}
return $status;
}
second module :
function maincategoryData($data)
{
$this->db->insert_batch('table_name', $data);
}
and your controller call this function
sample code in controller,
function inser_user_data()
{
$result = $this->module_name->maincategoryData($marketData,$maincategoryData)
if($result == FALSE)
{
throw error
`enter code here`
}
else
{
//data inserted successfully
}
}
I am using CI 3 and I can use single transaction on multiple model in Controller.
I have tried to insert error data to test if rollback or not, the transaction is successfully rollback.
I did not use Tpojka's anwser but my model methods return true or false. Everything seems okay.

Why isn't my Where working as I think it should?

I'm trying to get some data from a database whose results can be more than one row.
I've the following code for that:
public System.Linq.IQueryable<Users> getUser2(string idUser)
{
try
{
using (Entities c = new Entities())
{
c.ContextOptions.LazyLoadingEnabled = false;
c.ContextOptions.ProxyCreationEnabled = false;
return c.Users.Include("Empresas").Where(x => x.Login == idUser && x.Empresas.Activa == true);
}
}
catch (Exception ex)
{
throw ex;
}
}
But it doesn't seem to get any result, it shows something like a badly formed Iqueryable, I mean if I expand its results view I can see a message that says "ObjectContext instance has been eliminated and cannot be used for operations that need a connection" If I try to access any Users element with the function ElementAt(index) I get an IndexOutOfBounds error as it looks like it has no data if watched on debug mode.
I've deduced that it's Where fault because this code Works fine in returning the first user it finds that fulfills the condition:
public Users getUser(string idUser)
{
try
{
using (Entities c = new Entities())
{
c.ContextOptions.LazyLoadingEnabled = false;
c.ContextOptions.ProxyCreationEnabled = false;
return c.Users.Include("Empresas").FirstOrDefault(x => x.Login == idUser && x.Empresas.Activa == true);
}
}
catch (Exception ex)
{
throw ex;
}
}
Does that Where work differently than what I think I should? If then, how could I get several data that fulfills the conditions I'm passing the same as in getUser but for several rows?
Thanks for your attention.
You need to enumerate the result, so after the "where" statement add. ToList() which will enumerate and execute the query against your database. FirstOrDefault is executing the query thats why you get a result.
You need to check the deferred methods and understand how they work.
EDIT
The following are some links to show you the deference between the Deferred method vs Immediate methods in LINQ
1- http://www.dotnetcurry.com/showarticle.aspx?ID=750
2- http://www.codeproject.com/Articles/627081/LINQ-Deferred-Execution-Lazy-Evaluation
3- http://visualcsharptutorials.com/linq/deferred-execution
Hope that helps.

Using NHibernate.Linq and getting 2 queries for a simple select, why?

so here's the code with irrelevant bits left out:
public IEnumerable<T> GetByQuery(Expression<Func<T, bool>> filter
{
try
{
return Session.Linq<T>().Where(filter);
}
catch(Exception ex)
{
// custom exception handling here
}
finally
{
CloseSession();
}
return null;
}
and an example of it being called looks like this:
IEnumerabl<ClientReport> clientReports =
clientReportRepository.GetByQuery(item => item.ClientId = id);
So as you can see, nothing fancy and being called in this way, we're hitting one table in the database with no relationships to any other tables. But when I have show_sql = true in the configuration, It's displaying 2 of the same query.
Any ideas?
Thanks
clientReports will probably execute the query every time you enumerate it (or get the Count(), for example).
To avoid that, use .ToList() in the assignment.

Resources