Cake PHP automagic forms and multiple tables - validation

I have a form with the following fields:
firstName
lastName
emailAddress
followed by (up to) ten name/email fields, like so
friendName-1
friendEmail-1
friendName-2
friendEmail-2
...
etc.
The firstName, lastName & emailAddress fields will be saved into a 'referrals' table, but 10 name/email pairs will go into a 'friends' table, containing a foreign key refferal_id.
Normally I use the cakephp 'automagic' forms, and set up my validation in the model, and do a $this->model->save(); If it fails I fall back on my model validation rules and the error messages get spat back into my form html. No problems.
How would I do this for TWO tables though? I'm thinking that the automagic stuff is not the way to go, but I feel I will lose a lot without it, such as validation in my models and custom error messages.
Is there a happy medium? I'm fairly new to cake so I'm wondering if theres a way to use automagic with multiple tables.

See http://book.cakephp.org/view/84/Saving-Related-Model-Data-hasOne-hasMany-belongsTo
Create the relationship in your Referral model:
var $hasMany = array('Friend');
Essentially, make sure you name your fields correctly, e.g.
echo $form->create('Referral');
echo $form->input('first_name');
echo $form->input('last_name');
echo $form->input('email');
foreach (range(0,9) as $index) {
echo $form->input('Friend.'.$index.'.name');
echo $form->input('Friend.'.$index.'.email');
}
echo $form->end();
And in your referrals controller:
function add() {
if(!empty($this->data)) {
$this->Referral->saveAll($this->data, array('validate'=>'first'));
}
}

First, I really hope that you don't have 20 fields in table called 'friendName-1', 'friendEmail-1', etc. Your second table should have 3 fields--your referral_id, friendname, and friendemail. If you don't want to normalize, then you don't need the second table.
But I digress, the way to keep your automagic forms is to put a "hasMany" in your referrals model and/or a "belongsTo" in your "friends" model. Then you can still use the FormHelper and Model->Save().

Related

Using Laravel Eloquent to count how many times something exists in an efficient manner

I have a table called rentals, within each row are columns state,city,zipcode which all house ids to another table with that info. There are about 3400 rentals. I am pulling each column to display the states,city and zipcode distinctly. I need to show how many rentals are in each one. I am doing this now via ajax, the person starts typing in what they want to see and it auto completes it with the count, but its slow because of the way im doing it.
$rentals_count = Rentals::where('published',1)->get();
foreach($states as $state) {
echo $state.”-“.$rentals_count->where(‘state’,$state->id)->count();
}
Above is roughly what im doing with pieces removed because they are not related to this question. Is there a better way to do this? It lags a bit so the auto complete seems broken to a new user.
Have you considered Eager loading your eloquent query? Eager loading is used to reduce query operations. When querying, you may specify which relationships should be eager loaded using the with method:
$rental_counts = Rentals::where('published',1)->with('your_relation')->get();
You can read more about that in Laravel Documentation
$rentals = Rentals::wherePublished(true)->withCount('state')->get();
When you loop through $rentals, the result will be in $rental->state_count
Setup a relation 'state' on rentals then call it like this
$rentals_count = Rentals::where('published',1)->with('state')->get()->groupBy('state');
$rentals_count->map(function($v, $k){
echo $v[0]->state->name .' - '. $v->count();
});
Meanwhile in Rentals Model
public function state(){
return $this->hasOne(State::class, 'state'); //state being your foreign key on rentals table. The primary key has to be id on your states table
}

How do I show a table's Has Many relationship on frontend?

Using Laravel + Voyager, I have a "Has Many" relationship:
Course hasMany Teachers.
In backend all is fine, but if I try to get the information in the frontend, I only get the value in table, not the relation, so the output goes something like:
0
id 1
teachers_id null
name "Math"
1
id 2
teachers_id null
name "English"
Current code in web routing:
Route::get('/course', function () {
$co= App\Course::all();
return $co;
});
How can I get the correct output?
teachers_id Xav, Titus
so like #Tpojka commented you can start by eager loading the relationship when you are initializing the course likeso $co = App\Course::with('teachers')->get(); after which you do not need to make another unnecessary call to your database for the teachers of that course. You can get a collection of all the teachers of that course by simply calling $teachers = $co->teachers; here $teachers is now a laravel collection you can simply loop through it on the client side and display the information about the teachers you want to display. I hope this helps.
Good luck and happy coding. :)

how to make relation between table and array of ids from another table laravel

i have 2 tables, stores and products
stores table has field called products_ids
in this case i am saving the products in the stores by their ids in products_ids field as an array like this [1,2,3,4,5] i know it's not good practice to do it like this but this is the situation.
how can i make a relation in the model to achieve thing like this
Store::with('products')->get();
thanks
I don't know if this would work for you, but try it anyway:
in your Store model add the following:
public function products ()
{
return Product::whereIn('id', $this->products_ids)->get();
}

Yii2, few tables with uncomfortable generic field names for 1 Model

I'm building REST++ service with Yii2, which should be able to deal with 2 table schemes, (databases storing ~the~same~ data):
a_new_one, which is perfect to be handled with ActiveRecord;
the_old_one, which has 1 generic table 'Object' with columns like 'field1', 'field2', etc, and few additional tables.
I want my request methods and controllers to be all the same for both schemes (would be very great, really). That means, that I need to have THE SAME MODELS for both cases.
The troubles all relate to the_old_one database:
Let's say data of model User is stored in tables Object and UserProfile. If I make 2 ActiveRecord classes for both tables, will it be possible to make hasOne() relations to them in 3d class User (not sure about inheritance here), so it can be manipulated like this:
$user = User::find()->someFilters()->someOrderingAndPagination()->one();
$user->Name = $your_new_name;
$user->Age = $why_not_90;
$user->save();
// and so on.
Because I really don't want to be forced to write it like this:
$user = User::find()->notSureAboutRelations()
->filters()->ordering()->pagination()->one();
$user->object->field7 = $your_new_name;
$user->userProfile->Age = $why_not_90;
$user->save();
I learned, Doctrine has easy model mapping ($user->Name can be mapped to db's Object.field7), but it's still impossible to map to 2 different tables within 1 Entity. Or am I incorrect ? If so, would it be a good idea to use Doctrine within Yii2 ?
So finished with idea to have the same controllers and models. Only URLs remain the same.
The old db Model data could be gained this way:
$user = User::find()
->select([
'Object.field7 as Name',
'UserProfile.Age as Age',
// ...
])->from('Object')
->join('UserProfile', ['UserProfile.ObjectId = Object.Id'])
->andWhere('User.Id' => $id);
And it's an ugly mess up when saving this models. Cos you need to assign a lot of fields in BEFORE_INSERT, BEFORE_UPDATE events.

Finding Related Rows in Doctrine -- "Cleanest" Design?

I'm new to Doctrine, and I'm trying to get my head around both Doctrine and Symfony at the same time, so please bear with me.
I have a "Sentence" object. Sentences can be "rated" (scored out of five) by Users. I'm modelling this with the fairly obvious design where I have a Sentence table, a User table and a Rating table. Each row in the Rating table represents one user's rating of one sentence.
Rating:
...
columns:
rating: { type: integer } # This is my score out of five
sentence_id: { type: integer }
user_id: { type: integer }
relations:
sfGuardUser: { local: user_id }
Sentence: { local: sentence_id, onDelete: CASCADE, foreignAlias: Ratings }
That's working fine, but I'm struggling to find the cleanest way of asking questions of my model.
For example, in my code I have a logged-in User, related to my session, and I'm displaying a page representing a Sentence, which is also already sitting in a variable. I want to display the logged-in user's rating of that Sentence.
In raw SQL, effectively what I want to do is:
SELECT
rating
FROM
rating_table
WHERE
sentence_id = {$sentence->id} AND user_id = {$user->id}
Now, I know I could just do this on the RatingTable, simply by writing a new query with a bit of DQL, or even using one of the "magic" finders. But that seems a bit clumsy and not very OO, when I already have a Sentence object in memory with a getRatings() method generated by Doctrine for me which must already have the rating I want in its Collection of "all ratings for this sentence".
Is there an easy, efficient way that I'm missing of doing something like $sentence->getRatings()->findByUserId($user->getId())?
Or is it actually sensible just to ignore the fact that I've already got a collection of "ratings for this sentence" in memory and dive back out to the database, ignoring them completely?
There isnt a finder within a collection like that that im aware of (unlike with Propel)... if there is and I missed it in the Doctrine API then im going to leanr a blissful piece of code when someone posts it :-)
Having said that, IF you already have the collection loaded i would just add a custom method tot he model.. for example:
public function getUserRating($user){
if($user instanceof Doctrine_Record){ // or sfGuardUser depending on how tightly you want to couple
$user = $user->getId();
}
foreach($this->getRatings() as $rating){
if($user == $rating->getUserId()){
return $rating;
}
}
return null;
}

Resources