I'm attempting to set up my API for iOS app. This is my first time to use Laravel as a API so here is what I have in my tables:
Cars
Schema::create('cars', function (Blueprint $table) {
$table->increments('id');
$table->string('name')->nullable();
$table->string('age')->nullable();
$table->string('model')->nullable();
$table->string('color')->nullable();
Users
$table->increments('id');
$table->string('name')->nullable();
$table->string('street')->nullable();
$table->string('niehgborhood')->nullable();
$table->string('city')->nullable();
Contract
$table->increments('id');
$table->integer('user_id')->unsigned;
$table->foreign('user_id')->references('id')->on('users');
$table->integer('car_id')->unsigned;
$table->foreign('car_id')->references('id')->on('cars');
Models
protected $table = 'users';
protected $guarded = ['id'];
protected $fillable = ['phone', 'email',
'street','city','niehgborhood'
,'national_id'];
public function cars()
{
return $this->hasMany('App\User');
}
Users
protected $guarded = ['id'];
protected $fillable = ['name', 'age',
'color, model'
];
public function users()
{
return $this->belongsToMany('App\Cars');
}
in my controller I'm familiar with saving requested data
$user = JWTAuth::parseToken()->authenticate();
$user->phone = $request->phone;
$user->city = $request->city;
$user->save();
my goal with this project is to display the data(contracts) saved by iOS app users in my dashboard. For example, users info and the cars they are interested in my table. Can someone help me with what to do query in the controller(not views). Or provide helpful links for projects like this.
Your relation between User and Cars should be many-to-many. Please read the docs to apply this relation properly.
If your relations are in the place then you can do as:
$user = JWTAuth::parseToken()->authenticate();
$cars = $user->cars; // returns collection of cars associated with the user.
For example - In your User model define the following relation:
public function cars()
{
return $this->belongsToMany('App\Car');
}
Update
To save the user and associate cars, you can do it as following:
$user = JWTAuth::parseToken()->authenticate();
$user->phone = $request->phone;
$user->city = $request->city;
$user->save();
$car_ids = $request->car_ids; // it should return an array
$user->cars()->sync($car_ids);
There is more way to store the data. Please read the docs here for more info.
Related
I have these two very simple models:
class Episode extends Model
{
protected $fillable = ['number', 'language_code', 'published_at'];
function content()
{
return $this->hasOne('App\EpisodeContent');
}
}
class EpisodeContent extends Model
{
protected $table = 'episodes_content';
protected $fillable = ['episode_id', 'title', 'description'];
function episode()
{
return $this->belongsTo('App\Episode');
}
}
Where basically every Episode has one content. I could've used a single table, but I thought it could make sense to keep these sets of data separate.
In a form, I'd like to edit the Episode and its content at the same time, but after several attempts I haven't figured out how.
This is what I'm doing:
public function update(Request $request, $id)
{
$rules = [
'number' => 'required',
];
$this->validate($request, $rules);
$episode = Episode::with('content')->findOrFail($id);
$episode->published_at = $request->get('published_at');
$episode->number = $request->get('number');
$episode->content->title = $request->get('title');
$episode->update();
return redirect('admin/episodes');
}
This way, nothing changes in the episodes_content table.
In another attempt, I tried this:
$episode->published_at = $request->get('published_at');
$episode->number = $request->get('number');
$episode->active = $request->get('active');
$episodeContent = new EpisodeContent;
$episodeContent->title = $request->get('title');
$episode->content()->save($episodeContent);
This way, a new episodes_content row is created, while I'd like to update an existing one.
Try this I guess it will work
$episode = Episode::with('content',function($query) use($id){
$query->where('episode_id',$id);
})->where('id',$id);
Here I'm assuming your field name is id in parent table and episode_id in child table. Let me know if it doesn't work.
I'm working with project where tables are created all the time depending on user adding new properties, so for my model i have below
class Hotel extends Model
{
public function __construct($hotel)
{
$this->table = $hotel;
}
protected $fillable = ['date', 'sold', 'sold_diff', 'rev', 'rev_diff', 'row', 'date_col', 'sold_col', 'rev_col'];
}
and i can use the table in controller by doing
$hotel_table = new Hotel($table);
but i like to use Model::updateOrCreate() when I'm adding or updating rows in table, and I'm not sure how to do that.
This is the signature for the updateOrCreate function
"static Model updateOrCreate( array $attributes, array $values = array())"
For you to update or create, you can pass the condition that must be met to update the table to the first argument and the values to be updated to the second.
for example.
$primaryKey = isset($request->input('id')) ? $request->input('id') : null;
$myModel = Model::updateOrCreate(['id' => $primaryKey], $request->all());
so with this if id is in the request object the table will be updated but if not a new record will be created.
In Laravel 5.2 you can use simply like this
class Hotel extends Model
{
protect $table = 'hotels'
protected $fillable = ['date', 'sold', 'sold_diff', 'rev', 'rev_diff', 'row', 'date_col', 'sold_col', 'rev_col'];
// protected $guarded = []; you can use this instead of `$fillable` this is for all columns fillable
}
now in your controller you can use
Model::update();
Model::create();
ZF2 project - no Doctrine, using native Zend\Db: Have the following structure:
Controller
ProductController
Model
Product
ProductTable
ProductType
ProductTypeTable
Product is the model, has variables corresponding to the “products" table fields.
ProductTable is table class which is connected to the database via tableGateway. ProductTable has getItem() method to retrieve requested product by “id”.
ProductType is the model, has variables like id, name, description corresponding to the “productTypes" table fields.
ProductTypeTable is table class just like ProductTable.
Each product belongs to a certain ProductType
products.productTypeId = productTypes.id
is the relation.
In ProductTable->getItem() method, I can simply get productTypeId.
I can use joins to get productTypes.name, productTypes.description, or any field from "productTypes" table.
But I don’t want to do this - instead dealing with new variables in Product entity like productTypeName, productTypeDesc,
I’d like to have Product->getProductType() and set it to be a ProductType object, so I can get Product->getProductType() ->getName() to get product type name.
Simply I’d like to assign a child model as a variable of the parent model.
I can do this in the controller like below:
$product = $this->getProductTable()->getItem(7); // id = 7
$product->setProductType($this->getProductTypeTable()
->getItem($product->getProductTypeId());
But I’d like to make it happen in product table class getItem() method. So I don’t have to think about it in every controller, and it is kind of encapsulated.
What is the right way to do this?
Thank you.
The issue that you have is the Table Gateway pattern is only really any good at abstracting database access to a a single database table. It does not in anyway allow for the hydration of entities or management of relationships. Object Relationship Mappers (ORM's), such as Doctrine, solve this problem.
If Doctrine, for whatever reason, is inappropriate for your use case an alternative could be implementing the Data Mapper Pattern
The Data Mapper is a layer of software that separates the in-memory objects from the database. Its responsibility is to transfer data between the two and also to isolate them from each other
The data mapper will use the table gateway to fetch the required data for each table and construct the Product instance, including it's associated ProductType. You would then expose the mapper to the controller (rather than the table gateway).
A simple example of a ProductMapper.
class ProductMapper
{
// #var \Zend\Db\TableGateway\TableGateway
protected $productTable;
protected $productTypeMapper;
// an 'identity map' of loaded products
protected $loaded = [];
public function __construct(ProductTable $productTable, ProductTypeMapper $productTypeMapper)
{
$this->productTable = $productTable;
$this->productTypeMapper = $productTypeMapper;
}
protected function hydrate(Product $product, array $data)
{
$product->setId($data['id']);
$product->setName($data['name']);
$product->setFoo($data['foo']);
if (isset($data['type_id'])) {
// Load a fully constructed product type from the database
$type = $this->productTypeMapper->findById($data['type_id']);
$product->setType($type);
}
return $product;
}
public function findById($id)
{
if (isset($this->loaded[$id])) {
return $this->loaded[$id];
}
// Get the data
$row = $this->productTable->select(['id' => $id]);
if (empty($row)) {
throw new SomeCustomException("No product could be found with id $id");
}
// Create and hydrate the product
$product = $this->hydrate(new Product, $row->current())
$this->loaded[$id] = $product;
return $product;
}
public function save(array $data);
public function update($data);
public function delete($id);
}
You can achieve this, you just have to follow the following 3 steps:
Make your Product->exchangeArray() function smarter
Get all required ProductType fields, using a prefix helps for example: type_
Add #var ProductType so you will have proper autocompete (works for me in Eclipse)
<?php
namespace Product\Model\Product;
class Product {
public $id;
...
/**
* #var ProductType
*/
public $productType;
...
public function exchangeArray( $data ) {
$this->id = (isset($data['id'])) ? $data['id'] : null;
...
$productType = new ProductType();
$typeData = array(
'id' => $data['type_id'],
'value' => $data['type_value']
);
$productType->exchangeArray( $typeData );
$this->productType = $productType;
}
}
I want to get:
list of ApplicationUsers who are in role "NormalUser" to anybody
list of all ApplicationUsers only to Admins only.
I did this:
// GET: ApplicationUsers
public ActionResult Index() {
// if you are Admin you will get all users
if (User.IsInRole("Admin"))
return View(db.Users.ToList());
//if you are somebody else(not Admin) you will see only list of NormalUsers
//HERE I GET ERROR
var list = db.Users.Where(x => UserManager.IsInRole(x.Id, "NormalUser")).ToList(); // here I get error
return View(list);
}
UserManager inside code above is: UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(db));
But unfortunately my LINQ expresiion is incorrect. I get error:
LINQ to Entities does not recognize the method 'Boolean IsInRole[ApplicationUser,String](Microsoft.AspNet.Identity.UserManager`2[WebApplication2.Models.ApplicationUser,System.String], System.String, System.String)' method, and this method cannot be translated into a store expression.
Question: How to correctly get list of users who are in role "NormalUser"?
The UserManager.IsInRole function isn't supported at the database, but if your application can bear the weight of pulling the whole User table back from the database before applying your filter then you can just add a ToList between your Users table reference and your Where filter, i.e.
var list = db.Users.ToList().Where(x => UserManager.IsInRole(x.Id, "NormalUser")).ToList();
I reached here for a good quick answer but could not find one. So decided to put on what I got for any other visitor who comes here. To get the List of Users in any particular Role, one can use this code.
public async Task<ActionResult> Index()
{
List<ApplicationUser> appUsers=new List<ApplicationUser>();
await Task.Run( () =>
{
var roleManager = new RoleManager<IdentityRole>( new RoleStore<IdentityRole>( db ) );
var adminRole=roleManager.FindByName("Admin");
appUsers = db.Users.Where( x => x.Roles.Any( s => s.RoleId == adminRole.Id ) ).ToList();
} );
return View( appUsers );
}
It would be useful to know how Roles and Application users relate.
If the user can only belong to one role, it would be fine for you to do something like this:
var list = db.Users.ToList().Where(x => x.Role == "NormalUser").ToList();
Id the user can be part of multiple roles, it would look something more like this:
var list = db.Users.ToList().Where(x => x.Roles.Contains("NormalUser")).ToList();
Hope this helps.
I want to get & list all the users that belongs to the same idempresa that the user logged in has. idempresa is related to users in a sf_guard_profile table and yes I have the relation declared on schema.yml file. I think in write a method in sfGuardUserTable.class.php but I'm not so sure it will works in others words I don't know where to touch or what to handle this. Can any point me in the right direction on this? This is the method (unfinished):
public function getUsersByCompany() {
$user = sfContext::getInstance()->getUser()->getProfile()->getIdEmpresa();
$q = $this->createQuery('g');
return $q;
}
Any advice?
It's generally not good practice to use sfContext::getInstance(). Read this post http://webmozarts.com/2009/07/01/why-sfcontextgetinstance-is-bad/.
How about adding a static method to your sfGuardUserTable.class.php, e.g
// \lib\form\sfGuardUserTable.class.php
static public function getUsersByIdEmpresa($idempresa)
{
//...
$q->andWhere('idempressa = ?', $idempresa);
return $q->execute();
}
Then calling it in your controller or from where you need, e.g
// \app\myApp\modules\myModule\actions\action.class.php
public function executeMyAction() {
$profile = $this->getUser()->getProfile();
$usersRelatedByIdempresa = sfGuardUserTable::getUsersByIdempresa($profile->getIdempresa());
//...
}